摘要

背景:在做高德地图的定位时,发现在微信浏览器中只要最开始把定位权限关闭后,就再也没有位置可以再次打开定位权限,导致在微信浏览器中再也无法定位(mmp,就离谱),所以本文要使用微信自带的定位接口,实现在微信浏览器里的定位,以防止定位权限再也无法打开的情况。
本文主要介绍两点:
1.使用微信JSSDK进行微信定位的开发流程(非原理)
2.VUE中具体实现,以及本地如何进行测试

一、使用微信JSSDK进行微信定位的开发流程

步骤一:绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”,如下图
在这里插入图片描述
点击设置,进行安全域名设置
在这里插入图片描述
注意:这里写线上的安全域名,即使保存次数用完了也没关系,可以在本地进行测试。

步骤二:引入JS文件

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)。

备注:支持使用 AMD/CMD 标准模块加载方法加载

在VUE中直接使用npm进行安装,在使用的地方import即可

npm isntall weixin-js-sdk --save

import wx from 'weixin-js-sdk'

步骤三:通过config接口注入权限验证配置

wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appId: '', // 必填,公众号的唯一标识
  timestamp: , // 必填,生成签名的时间戳,后端返回
  nonceStr: '', // 必填,生成签名的随机串,后端返回
  signature: '',// 必填,签名,后端返回
  jsApiList: [] // 必填,需要使用的JS接口列表
});

除了jsApiList,我们都需要从后端获取。
我们就向后端发起一个请求,然后后端封装一下返回给前端是不是就好了。

appId,直接从微信后台拿来用就行。

timestamp,后端返回,但要注意要以秒为单位。

nonceStr,后端返回,随机串。

signature,生成方式如下。

signature的生成(后端处理,与前端无关)

1、参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
2、用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket)
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功返回如下JSON:

{
  "errcode":0,
  "errmsg":"ok",
  "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  "expires_in":7200
}

3、签名算法
示例:

noncestr=Wm3WZYTPz0wzccnW // 后端随机生成的字符串
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg // 第二步从微信那里拿到的ticket
timestamp=1414587457 // 时间戳(秒)
url=http://mp.weixin.qq.com?params=value // 当前网页的URL,不包含#及其后面部分,前端传过来的

将以上四个变量按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1(所有参数名均为小写字符)
拼好后如下

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

然后将拼好的string1进行sha1签名,得到signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

注意事项

1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

2.签名用的url必须是调用JS接口页面的完整URL。

3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

4.signature生成不对前端就会出现invalid signature错误,解决方法见下面的常见问题。

步骤四:通过ready接口处理成功验证

wx.ready(function(){
  // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});

步骤五:通过error接口处理失败验证

wx.error(function(res){
  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});

二、VUE中具体实现,以及本地如何进行测试

1、搭建本地测试环境

1.首先下载微信开发者工具下载地址
2.将本地的localhost改为 第一步中所绑定的js安全域名
(在这之前判断你的VUE工程调用接口的地址是否跟所绑定的js安全域名一样,如果一样,则通过服务器ip地址调用接口。)
修改host文件(位置 C:\Windows\System32\drivers\etc
如下图
在这里插入图片描述
3.VUE工程将本地端口号设为80
如下图,在跟目录的vue.config.js添加如下代码

devServer: {
    open: process.platform === 'darwin',
    host: '0.0.0.0',
    port: '80',
    disableHostCheck: true,
    https: false,
    hotOnly: false,
    overlay: {
      warnings: false,
      errors: true
    }
    // proxy: {
    //   '/api': {
    //     target: 'xxxxxx', // 自己的代理
    //     changeOrigin: true,
    //     pathRewrite: {
    //       '^/api': '/'
    //     }
    //   }
    // }
  },

4.查看本地80端口是否被占用
window下使用如下命令

netstat -aon|findstr "80"

如下图
在这里插入图片描述
打开任务管理器,将pid为上图19572的服务关闭,如下图
在这里插入图片描述
5.最后运行你的VUE项目,在微信开发者工具中打开,注意不要使用localhost访问,使用第一步所修改的域名,不需要加端口号,如下图
在这里插入图片描述
本地环境已搭建完毕

2、VUE中具体实现

1.引入JS文件

npm isntall weixin-js-sdk --save

2.配置微信

import wx from 'weixin-js-sdk'
import apis from '@/api'

// 初始化微信sdk方法
wxJsSdkInit() {
	const url = window.location.href
	const jsApiList = ['getLocation'] // 微信获取地理位置接口
	const request = { ...apis.ACCOUNT.WX_SIGN } // 接口地址
	request.params = { // 参数
	  url
	}
	this.$request(request) // 调用接口
	.asyncThen(
	  (resp) => {
	  	// 成功返回
	    wx.config({
	      debug: true, // 开发时设为true方便调试
	      signature: resp.data.signature,
	      nonceStr: resp.data.nonceStr,
	      timestamp: resp.data.timestamp,
	      appId: resp.data.appId,
	      jsApiList
	    })
	    wx.error((res) => {
	      // 微信配置失败
	      // console.log(res)
	      // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
	    })
	    wx.ready((res) => {
	      // 微信配置成功
	      // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
	      // console.log(res)
	    })
	  },
	  (err) => {
	    console.error(err)
	  }
	)
	.asyncErrorCatch((err) => {
	  console.error(err)
	})
}

配置好如下图所示
在这里插入图片描述

3.调用微信getLocation方法

import wx from 'weixin-js-sdk'

getLocationByWx() [
	const ua = window.navigator.userAgent.toLowerCase()
    if (ua.match(/micromessenger/i) != null) {
     wx.getLocation({
       type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
       success: (res) => {
         var lat = res.latitude // 纬度,浮点数,范围为90 ~ -90
         var lng = res.longitude // 经度,浮点数,范围为180 ~ -180。
         // var speed = res.speed // 速度,以米/每秒计
         // var accuracy = res.accuracy // 位置精度
       },
       fail: (error) => {
         // this.$message({
         //   type: 'error',
         //   message: `微信定位失败,请稍后重试`
         // })
       },
       cancel: (error) => {
         // this.$message({
         //   type: 'error',
         //   message: `微信定位未授权,请稍后重试`
         // })
       }
     })
    }
}

定位后如下图所示
在这里插入图片描述

三、常见问题

1.invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,仅支持80(http)和443(https)两个端口,因此不需要填写端口号
2.invalid signature签名错误
按以下顺序进行

  1. 确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。判断后端返回的signature是否正确。
  2. 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
  3. 确认url是页面完整的url(请在当前页面alert(location.href.split(’#’)[0])确认),包括’http(s)😕/‘部分,以及’?‘后面的GET参数部分,但不包括’#'hash后面的部分。
  4. 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
  5. 确保一定缓存access_token和jsapi_ticket。
  6. 确保你获取用来签名的url是动态获取的

注意:如果以上都没有问题(部署到线上就是好的,本地就不行,mmp这就离谱,本地都失败了,谁敢部署到线上。死锁了。。。),那一定是本地测试所访问的地址和所配置的js安全域名不一致,本地用了localhost,而js安全域名是线上的地址,所以一定要搭建本地测试环境。

3.getLocation定位不准:只会在微信开发者工具上会有问题,不必担心。

四、参考地址

1.微信JS-SDK说明文档
2.https://www.cnblogs.com/xiaofeng-blog/p/10216988.html

Logo

前往低代码交流专区

更多推荐