背景:在做高德地图的定位时,发现在微信浏览器中只要最开始把定位权限关闭后,就再也没有位置可以再次打开定位权限,导致在微信浏览器中再也无法定位(mmp,就离谱),所以本文要使用微信自带的定位接口,实现在微信浏览器里的定位,以防止定位权限再也无法打开的情况。
本文主要介绍两点:
1.使用微信JSSDK进行微信定位的开发流程(非原理)
2.VUE中具体实现,以及本地如何进行测试
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“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'
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳,后端返回
nonceStr: '', // 必填,生成签名的随机串,后端返回
signature: '',// 必填,签名,后端返回
jsApiList: [] // 必填,需要使用的JS接口列表
});
除了jsApiList,我们都需要从后端获取。
我们就向后端发起一个请求,然后后端封装一下返回给前端是不是就好了。
appId,直接从微信后台拿来用就行。
timestamp,后端返回,但要注意要以秒为单位。
nonceStr,后端返回,随机串。
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×tamp=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错误,解决方法见下面的常见问题。
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
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访问,使用第一步所修改的域名,不需要加端口号,如下图
本地环境已搭建完毕
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签名错误
按以下顺序进行
注意:如果以上都没有问题(部署到线上就是好的,本地就不行,mmp这就离谱,本地都失败了,谁敢部署到线上。死锁了。。。),那一定是本地测试所访问的地址和所配置的js安全域名不一致,本地用了localhost,而js安全域名是线上的地址,所以一定要搭建本地测试环境。
3.getLocation定位不准:只会在微信开发者工具上会有问题,不必担心。
1.微信JS-SDK说明文档
2.https://www.cnblogs.com/xiaofeng-blog/p/10216988.html