微信 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 + '';
}

至此,各類簽名錯誤的問題纔算是所有解決。

相關文章
相關標籤/搜索