微信 jssdk 簽名錯(cuò)誤invalid signature的解決方法
幾乎每一個(gè)開(kāi)發(fā)用于微信公眾號(hào)頁(yè)面的工程師都遇到過(guò)微信jssdk
報(bào)的各種錯(cuò)誤,通常是permission denied
,類(lèi)似這樣:
通常他們會(huì)建議你把debug
選項(xiàng)開(kāi)開(kāi),比如這樣:
wechat.config({ debug: true, appId: appId, timestamp: timestamp, nonceStr: nonceStr, signature: signature, jsApiList: ['scanQRCode'], });
結(jié)果你又遇到了invalid signature
。類(lèi)似這樣:
簽名不對(duì),這是什么意思?可是這簽名是后端給過(guò)來(lái)的,我怎么知道它為什么不對(duì)?后端用的是標(biāo)準(zhǔn)算法,不可能不對(duì)啊。
查網(wǎng)上各種教程,或者微信官網(wǎng),他們總是不厭其煩地告訴你,讓你去檢查簽名算法,然而根本沒(méi)有用!
90%
的這種情況下,其實(shí)只是一個(gè)原因:你用于計(jì)算簽名的URL
地址不對(duì),跟算法沒(méi)有任何關(guān)系,完全不必浪費(fèi)時(shí)間去看什么簽名算法。
微信要求:如果我們需要在頁(yè)面中調(diào)用微信的某個(gè)方法,則必須用這個(gè)頁(yè)面的URL
地址獲取簽名。聽(tīng)上去似乎很好理解,但是實(shí)際上URL
地址包含的部分很多,有問(wèn)號(hào),有#
號(hào),你所要做的是取出#
前面的部分。比如說(shuō)你的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)前頁(yè)面的URL
地址呢?這個(gè)很簡(jiǎn)單:
let wechaturl = window.location.href.split('#')[0];
然而你以為事情就這樣結(jié)束了?太天真。你的頁(yè)面還是無(wú)法正常使用微信函數(shù)的。
因?yàn)椋何⑿艃?nèi)嵌瀏覽器在iOS
和安卓下的表現(xiàn)不一樣。
在安卓下,你確實(shí)用上面的方法是可以調(diào)用了。但是在iOS
下,簽名依然失??!因?yàn)樵?code>iOS下,微信需要你傳遞的是入口URL
,而不是當(dāng)前頁(yè)面的URL
!
比如說(shuō),你在微信公眾號(hào)的某個(gè)菜單鏈接進(jìn)入了A
頁(yè)面,然后從A
頁(yè)面的某個(gè)鏈接跳轉(zhuǎn)到B
頁(yè)面,然后你在B
頁(yè)面獲取簽名,如果是在安卓下,你應(yīng)該用B
頁(yè)面的URL
地址來(lái)獲取,但是在iOS
下,你還必須用A
頁(yè)面的URL
地址來(lái)獲取,否則就還是簽名失??!
知道了原因,就有很多種解決辦法。
首先,我們可以在入口的A
頁(yè)面里增加這樣的判斷:
if (navigator.userAgent.indexOf('iPhone') !== -1) { window.wechaturl = window.location + ''; }
然后,在B
頁(yè)面需要調(diào)用簽名的地方,再增加這樣的判斷:
let wechaturl = window.location.href.split('#')[0]; if (window.wechaturl !== undefined) { wechaturl = window.wechaturl; }
這樣我們就有效地區(qū)分開(kāi)了iOS
和安卓。但問(wèn)題是在iOS
下,如果我的另外一個(gè)菜單入口是B
頁(yè)面,我從B
頁(yè)面跳轉(zhuǎn)到A
頁(yè)面,這時(shí)候我的入口鏈接被強(qiáng)制變成了A
頁(yè)面,依然會(huì)產(chǎn)生簽名失敗的錯(cuò)誤。
所以我們還需要在微信公眾號(hào)的每一個(gè)入口菜單鏈接里加一個(gè)特殊的參數(shù),例如wechat=1
,變成這樣:https://www.abc.com/abc.html?abc=def&wechat=1
,
然后我們?cè)僭黾右粚优袛?,變成這樣:
if (navigator.userAgent.indexOf('iPhone') !== -1) { if (this.$route.query.wechat !== undefined && this.$route.query.wechat === '1') { window.wechaturl = window.location + ''; } }
這里我用了vue
的寫(xiě)法,但原理是一樣的。只有我檢測(cè)到了wechat
這個(gè)參數(shù),我才認(rèn)為當(dāng)前頁(yè)面是入口頁(yè)面,如果沒(méi)有檢測(cè)到,則不必強(qiáng)行設(shè)置為入口頁(yè)面。
這樣似乎就解決了微信簽名失敗的問(wèn)題。
但是,我們又遇到了另外一種情況:在微信小程序里用web-view
內(nèi)嵌的網(wǎng)頁(yè),在安卓下也報(bào)permission denied
和invalid signature
錯(cuò)誤。不過(guò)有了上面的經(jīng)驗(yàn),我們?cè)\斷錯(cuò)誤根源還是URL
入口地址的問(wèn)題。果然,在安卓下用入口地址獲取簽名成功,而用當(dāng)前地址獲取簽名失敗,為此,我們?cè)谌肟陧?yè)面里再加一個(gè)判斷:
if (navigator.userAgent.indexOf('miniProgram') !== -1) { window.wechaturl = window.location + ''; }
至此,各種簽名錯(cuò)誤的問(wèn)題才算是全部解決。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS中call和apply函數(shù)用法實(shí)例分析
這篇文章主要介紹了JS中call和apply函數(shù)用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了call和apply函數(shù)繼承功能的使用方法、區(qū)別及操作注意事項(xiàng),需要的朋友可以參考下2018-06-06JavaScript event對(duì)象整理及詳細(xì)介紹
這篇文章主要介紹了JavaScript event對(duì)象整理及詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2016-10-10Ionic3 UI組件之a(chǎn)utocomplete詳解
這篇文章主要為大家詳細(xì)介紹了Ionic3 UI組件之a(chǎn)utocomplete的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06JavaScript跨域調(diào)用基于JSON的RESTful API
這篇文章主要介紹了JavaScript跨域調(diào)用基于JSON的RESTful API的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07JS+CSS實(shí)現(xiàn)可拖拽的漂亮圓角特效彈出層完整實(shí)例
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)可拖拽的漂亮圓角特效彈出層,以完整實(shí)例形式分析了彈出層特效及圓角矩形的實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-02-02關(guān)于火狐(firefox)及ie下event獲取的兩種方法
經(jīng)常有同事問(wèn)我在火狐瀏覽器怎么獲取event的方法,大多是想獲取event.keyCode的功能,接下來(lái)為您介紹兩種實(shí)現(xiàn)方法,需要了解的朋友可以參考下2012-12-12Java 正則表達(dá)式學(xué)習(xí)總結(jié)和一些小例子
字符串處理是許多程序中非常重要的一部分,它們可以用于文本顯示,數(shù)據(jù)表示,查找鍵和很多目的.在Unix下,用戶(hù)可以使用正則表達(dá)式的強(qiáng)健功能實(shí)現(xiàn)這些 目的2012-09-09javascript iframe內(nèi)的函數(shù)調(diào)用實(shí)現(xiàn)方法
用下面的方法可以調(diào)用iframe中的函數(shù),實(shí)現(xiàn)一些比較特殊的效果,不過(guò)能跨域的。2009-07-07