问题描述
之前在 html+js
的项目中使用微信JS-SDK
,wx.config
配置正常,使用图片上传和扫一扫等功能都正常。
现在的问题是,在 vue history模式 项目中,一直是签名无效,iOS和Android 都不行。
按照官方文档中的1~6排查了都没问题,打印出来的url编码前后和后端获取到的签名的url编码前后都是一致的,但就是一直 invalid signature 签名无效。
invalid signature签名错误。建议按如下顺序检查:
1.确认签名算法正确,可用http://mp.weixin.qq.com/debug… 页面工具进行校验。
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是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签> 名,前端需要用js获取当前页面除去’#’hash部分的链接(可用location.href.split(‘#’)[0]获取,而且需要encodeURIComponent),因为页> 面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
问题分析
经过查资料发现,参考资料前两篇里都说是
从 A页面,跳转到B页面,由于没有刷新,B调用 JSSDK的 内容,由于vue-router切换的时候 都是操作的浏览器历史记录,真实url为第一次刚进入时的url。每次路由变化时都重新请求下签名,签名的url 需要用第一次进入时的url
IOS:微信IOS版,每次切换路由,SPA的url是不会变的,发起签名请求的url参数必须是当前页面的url就是最初进入页面时的url
Android:微信安卓版,每次切换路由,SPA的url是会变的,发起签名请求的url参数必须是当前页面的url(不是最初进入页面时的)
在另一篇文章微信 jssdk 签名错误 invalid signature里,说是:
在iOS下,签名依然失败!因为在iOS下,微信需要你传递的是入口URL,而不是当前页面的URL!
比如说,你在微信公众号的某个菜单链接进入了A页面,然后从A页面的某个链接跳转到B页面,然后你在B页面获取签名,如果是在安卓下,你应> 该用B页面的URL地址来获取,但是在iOS下,你还必须用A页面的URL地址来获取,否则就还是签名失败!
有点儿懵 -_-||
尝试解决
按前两篇文里说的方法试着改了一下代码
在A组件增加:
if (navigator.userAgent.indexOf('iPhone') !== -1) {
// IOS 记录微信菜单打开时的url
window.entryUrl = location.href.split('#')[0]
}
在B组件修改:
let href = window.location.href.split('#')[0]
let signLink = /(Android)/i.test(navigator.userAgent) ? href : window.entryUrl
let encodeURI = encodeURIComponent(signLink)
let data = {
url: encodeURI
}
let url = '/.../getconfig.json' //接口省略了
this.$get(url, data, response => {
let rtn = response.data
wx.config({
// beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题 [这是企业微信的使用]
// debug: false, // 关闭调试模式
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来
appId: rtn.appId, // 必填,公众号的唯一标识
timestamp: rtn.timestamp, // 必填,生成签名的时间戳
nonceStr: rtn.nonceStr, // 必填,生成签名的随机串
signature: rtn.signature, // 必填,签名,见附录1
jsApiList: ['checkJsApi', 'chooseImage', 'uploadImage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
})
结果:
还是invalid signature 签名无效,依然是 iOS和Android 都不行。
真是让人头疼啊。。。。抓狂。。。。
等问题解决了再来更新问题的原因和解决办法,哎…………
以上是2019-07-25下午
以下是2019-07-26上午
解决了
来更新了,问题解决了,去掉了encodeURIComponent就好了。。。。
那么为什么官方文档中的常见错误及解决方法第6条,以及别的文章里都说要encodeURIComponent呢?
6.确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去’#’hash部分的链接(可用location.href.split(‘#’)[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
有同学疑惑这个encodeURIComponent是干嘛用的,其实具体很简单,就是因为我们在微信分享的时候,会自动给我们带上参数(记得告诉后端的伙伴要decodeURIComponent),切记只要带参数就一定要转码!
然而,在vue里,我们把encodeURIComponent去掉了,反倒问题解决了,额。。。。。
参考资料
微信JS-SDK说明文档 附录5-常见错误及解决方法
vue 单页面(SPA) history模式调用微信jssdk 跳转后偶尔 “invalid signature”错误解决方案
关于微信JSSDK中遇到的“invalid signature”的天坑
微信 jssdk 签名错误 invalid signature
VUE解决微信签名,SPA微信invalid signature问题,完美处理
微信jssdk常见错误及解决方法
vue cli单页模式下偶尔报错 invalid signature 的错误
vue 项目如何引入微信sdk,使用微信分享接口
微信分享JSSDK-invalid signature签名错误的解决方案
微信JS-SDK获取signature签名以及config配置