微信 jssdk 簽名錯誤invalid signature的解決方法
幾乎每一個開發(fā)用于微信公眾號頁面的工程師都遇到過微信jssdk報的各種錯誤,通常是permission denied,類似這樣:

通常他們會建議你把debug選項(xiàng)開開,比如這樣:
wechat.config({
debug: true,
appId: appId,
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
jsApiList: ['scanQRCode'],
});
結(jié)果你又遇到了invalid signature。類似這樣:

簽名不對,這是什么意思?可是這簽名是后端給過來的,我怎么知道它為什么不對?后端用的是標(biāo)準(zhǔn)算法,不可能不對啊。
查網(wǎng)上各種教程,或者微信官網(wǎng),他們總是不厭其煩地告訴你,讓你去檢查簽名算法,然而根本沒有用!
90%的這種情況下,其實(shí)只是一個原因:你用于計(jì)算簽名的URL地址不對,跟算法沒有任何關(guān)系,完全不必浪費(fèi)時間去看什么簽名算法。
微信要求:如果我們需要在頁面中調(diào)用微信的某個方法,則必須用這個頁面的URL地址獲取簽名。聽上去似乎很好理解,但是實(shí)際上URL地址包含的部分很多,有問號,有#號,你所要做的是取出#前面的部分。比如說你的URL地址是這樣:https://www.abc.com/abc.html?abc=def#xyz,那么你用于計(jì)算簽名的URL地址不可以是https://www.abc.com/abc.html,也不能是https://www.abc.com/abc.html?abc=def#xyz,而必須只能是https://www.abc.com/abc.html?abc=def。
如何獲取當(dāng)前頁面的URL地址呢?這個很簡單:
let wechaturl = window.location.href.split('#')[0];
然而你以為事情就這樣結(jié)束了?太天真。你的頁面還是無法正常使用微信函數(shù)的。
因?yàn)椋何⑿艃?nèi)嵌瀏覽器在iOS和安卓下的表現(xiàn)不一樣。
在安卓下,你確實(shí)用上面的方法是可以調(diào)用了。但是在iOS下,簽名依然失??!因?yàn)樵?code>iOS下,微信需要你傳遞的是入口URL,而不是當(dāng)前頁面的URL!
比如說,你在微信公眾號的某個菜單鏈接進(jìn)入了A頁面,然后從A頁面的某個鏈接跳轉(zhuǎn)到B頁面,然后你在B頁面獲取簽名,如果是在安卓下,你應(yīng)該用B頁面的URL地址來獲取,但是在iOS下,你還必須用A頁面的URL地址來獲取,否則就還是簽名失?。?/p>
知道了原因,就有很多種解決辦法。
首先,我們可以在入口的A頁面里增加這樣的判斷:
if (navigator.userAgent.indexOf('iPhone') !== -1) {
window.wechaturl = window.location + '';
}
然后,在B頁面需要調(diào)用簽名的地方,再增加這樣的判斷:
let wechaturl = window.location.href.split('#')[0];
if (window.wechaturl !== undefined) {
wechaturl = window.wechaturl;
}
這樣我們就有效地區(qū)分開了iOS和安卓。但問題是在iOS下,如果我的另外一個菜單入口是B頁面,我從B頁面跳轉(zhuǎn)到A頁面,這時候我的入口鏈接被強(qiáng)制變成了A頁面,依然會產(chǎn)生簽名失敗的錯誤。
所以我們還需要在微信公眾號的每一個入口菜單鏈接里加一個特殊的參數(shù),例如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這個參數(shù),我才認(rèn)為當(dāng)前頁面是入口頁面,如果沒有檢測到,則不必強(qiáng)行設(shè)置為入口頁面。
這樣似乎就解決了微信簽名失敗的問題。
但是,我們又遇到了另外一種情況:在微信小程序里用web-view內(nèi)嵌的網(wǎng)頁,在安卓下也報permission denied和invalid signature錯誤。不過有了上面的經(jīng)驗(yàn),我們診斷錯誤根源還是URL入口地址的問題。果然,在安卓下用入口地址獲取簽名成功,而用當(dāng)前地址獲取簽名失敗,為此,我們在入口頁面里再加一個判斷:
if (navigator.userAgent.indexOf('miniProgram') !== -1) {
window.wechaturl = window.location + '';
}
至此,各種簽名錯誤的問題才算是全部解決。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript密碼強(qiáng)度校驗(yàn)代碼(兩種方法)
為了保證網(wǎng)站個人信息的安全,很多網(wǎng)站在注冊頁面都設(shè)置密碼強(qiáng)度這項(xiàng),用javascript如何實(shí)現(xiàn)密碼強(qiáng)度校驗(yàn)代碼呢?下面小編給大家整理了兩種方法使用javascript密碼強(qiáng)度校驗(yàn)代碼,有需要的朋友可以參考下2015-08-08
JavaScript中函數(shù)(Function)的apply與call理解
這篇文章主要介紹了JavaScript中函數(shù)(Function)的apply與call理解,本文講解了JavaScript函數(shù)調(diào)用分為4中模式以及通過apply和call實(shí)現(xiàn)擴(kuò)展和繼承兩方面,需要的朋友可以參考下2015-07-07
通過javascript實(shí)現(xiàn)段落的收縮與展開
這篇文章主要介紹了通過javascript實(shí)現(xiàn)段落的收縮與展開,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-06-06

