微信 jssdk 签名错误 invalid signature

几乎每个开发用于微信公众号页面的工程师都遇到过微信jssdk报的各类错误,一般是permission denied,相似这样:html

clipboard.png

一般他们会建议你把debug选项开开,好比这样:vue

wechat.config({
      debug: true,
      appId: appId,
      timestamp: timestamp,
      nonceStr: nonceStr,
      signature: signature,
      jsApiList: ['scanQRCode'],
    });

结果你又遇到了invalid signature。相似这样:web

clipboard.png

签名不对,这是什么意思?但是这签名是后端给过来的,我怎么知道它为何不对?后端用的是标准算法,不可能不对啊。算法

查网上各类教程,或者微信官网,他们老是不厌其烦地告诉你,让你去检查签名算法,然而根本没有用!小程序

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 deniedinvalid signature错误。不过有了上面的经验,咱们诊断错误根源仍是URL入口地址的问题。果真,在安卓下用入口地址获取签名成功,而用当前地址获取签名失败,为此,咱们在入口页面里再加一个判断:

if (navigator.userAgent.indexOf('miniProgram') !== -1) {
  window.wechaturl = window.location + '';
}

至此,各类签名错误的问题才算是所有解决。

相关文章
相关标签/搜索