几乎每个开发用于微信公众号页面的工程师都遇到过微信jssdk
报的各类错误,一般是permission denied
,相似这样:html
一般他们会建议你把debug
选项开开,好比这样:vue
wechat.config({ debug: true, appId: appId, timestamp: timestamp, nonceStr: nonceStr, signature: signature, jsApiList: ['scanQRCode'], });
结果你又遇到了invalid signature
。相似这样:web
签名不对,这是什么意思?但是这签名是后端给过来的,我怎么知道它为何不对?后端用的是标准算法,不可能不对啊。算法
查网上各类教程,或者微信官网,他们老是不厌其烦地告诉你,让你去检查签名算法,然而根本没有用!小程序
90%
的这种状况下,其实只是一个缘由:你用于计算签名的URL
地址不对,跟算法没有任何关系,彻底没必要浪费时间去看什么签名算法。后端
我又遇到了一种新状况,因此仍是有必要进入微信公众号管理后台按照如下顺序检查: 第一,在接口配置页面检查是否把你的服务器的域名加入了信任域名?第二,在基本配置页面检查是否把你的服务器的IP地址加入了白名单?
微信要求:若是咱们须要在页面中调用微信的某个方法,则必须用这个页面的URL
地址获取签名。听上去彷佛很好理解,可是实际上URL
地址包含的部分不少,有问号,有#
号,你所要作的是取出#
前面的部分。好比说你的URL
地址是这样:https://www.abc.com/abc.html?abc=def#xyz
,那么你用于计算签名的URL
地址不能够是https://www.abc.com/abc.html
,也不能是https://www.abc.com/abc.html?abc=def#xyz
,而必须只能是https://www.abc.com/abc.html?abc=def
。微信小程序
如何获取当前页面的URL
地址呢?这个很简单:浏览器
let wechaturl = window.location.href.split('#')[0];
然而你觉得事情就这样结束了?太天真。你的页面仍是没法正常使用微信函数的。服务器
由于:微信内嵌浏览器在iOS
和安卓下的表现不同。微信
在安卓下,你确实用上面的方法是能够调用了。可是在iOS
下,签名依然失败!由于在iOS
下,微信须要你传递的是入口URL
,而不是当前页面的URL
!
好比说,你在微信公众号的某个菜单连接进入了A
页面,而后从A
页面的某个连接跳转到B
页面,而后你在B
页面获取签名,若是是在安卓下,你应该用B
页面的URL
地址来获取,可是在iOS
下,你还必须用A
页面的URL
地址来获取,不然就仍是签名失败!
知道了缘由,就有不少种解决办法。
首先,咱们能够在入口的A
页面里增长这样的判断:
if (navigator.userAgent.indexOf('iPhone') !== -1) { window.wechaturl = window.location + ''; }
而后,在B
页面须要调用签名的地方,再增长这样的判断:
let wechaturl = window.location.href.split('#')[0]; if (window.wechaturl !== undefined) { wechaturl = window.wechaturl; }
这样咱们就有效地区分开了iOS
和安卓。但问题是在iOS
下,若是个人另一个菜单入口是B
页面,我从B
页面跳转到A
页面,这时候个人入口连接被强制变成了A
页面,依然会产生签名失败的错误。
因此咱们还须要在微信公众号的每个入口菜单连接里加一个特殊的参数,例如wechat=1
,变成这样:https://www.abc.com/abc.html?abc=def&wechat=1
,
而后咱们再增长一层判断,变成这样:
if (navigator.userAgent.indexOf('iPhone') !== -1) { if (this.$route.query.wechat !== undefined && this.$route.query.wechat === '1') { window.wechaturl = window.location + ''; } }
这里我用了vue
的写法,但原理是同样的。只有我检测到了wechat
这个参数,我才认为当前页面是入口页面,若是没有检测到,则没必要强行设置为入口页面。
这样彷佛就解决了微信签名失败的问题。
可是,咱们又遇到了另一种状况:在微信小程序里用web-view
内嵌的网页,在安卓下也报permission denied
和invalid signature
错误。不过有了上面的经验,咱们诊断错误根源仍是URL
入口地址的问题。果真,在安卓下用入口地址获取签名成功,而用当前地址获取签名失败,为此,咱们在入口页面里再加一个判断:
if (navigator.userAgent.indexOf('miniProgram') !== -1) { window.wechaturl = window.location + ''; }
至此,各类签名错误的问题才算是所有解决。