微信公眾號(hào)中的JSSDK接入及invalid signature等常見錯(cuò)誤問(wèn)題分析(全面解析)
最近在搞微信公眾號(hào)開發(fā),進(jìn)行到網(wǎng)頁(yè)開發(fā)部分被坑了一天,最坑的問(wèn)題就是invalid signature,而網(wǎng)上大部分解答這個(gè)問(wèn)題的都沒有說(shuō)清楚,都直接丟文檔。博主認(rèn)為這樣很不好。本文是博主結(jié)合自身遇到的問(wèn)題所寫,整個(gè)流程跟問(wèn)題都很詳細(xì),雖然排版可能有點(diǎn)不好。但是絕對(duì)對(duì)遇到類似問(wèn)題的朋友有所幫助。請(qǐng)認(rèn)真看下去
一、綁定JS接口安全域名
生產(chǎn)號(hào)綁定方法:登錄微信公眾平臺(tái)進(jìn)入“公眾號(hào)設(shè)置”的“功能設(shè)置”里填寫“JS接口安全域名”。
測(cè)試號(hào)綁定方法:進(jìn)入測(cè)試號(hào)管理頁(yè)面,找到JS接口安全域名項(xiàng)綁定
JS接口安全域名官方說(shuō)法是:開發(fā)者可在該域名下調(diào)用微信開放的JS接口
域名格式:如果你的項(xiàng)目域名是http://test.domain.com,那么JS接口安全域名為test.domain.com。切記!
域名綁定失敗或者域名不存在會(huì)報(bào)錯(cuò)誤:invalid url domain
二、引入微信js文件
引入方法:在需要調(diào)用JS接口的頁(yè)面引入JS文件,用script標(biāo)簽引入即可
JS文件路徑:http://res.wx.qq.com/open/js/jweixin-1.2.0.js(支持https)
三、通過(guò)wx.config接口注入權(quán)限驗(yàn)證
1、每個(gè)需要使用jssdk的頁(yè)面都要使用config接口注入配置信息,wx.config調(diào)用方法如下:
wx.config({
debug: true, // 開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。
appId: '', // 必填,公眾號(hào)的唯一標(biāo)識(shí)
timestamp: , // 必填,生成簽名的時(shí)間戳,精確到秒
nonceStr: '', // 必填,生成簽名的隨機(jī)串
signature: '',// 必填,簽名
jsApiList: [] // 必填,需要使用的JS接口列表,例如:['chooseImage','previewImage','uploadImage']
})
其中appId,timestamp,nonceStr,signature必須從后臺(tái)獲取
四、后臺(tái)生成并返回前端所需參數(shù)
1、jsapi_ticket
jsapi_ticket是公眾號(hào)用于調(diào)用js接口的臨時(shí)票據(jù)。有效期7200秒,跟公眾號(hào)普通access_token一樣,必須全局緩存起來(lái),因?yàn)檫@個(gè)ticket獲取次數(shù)有限,超過(guò)次數(shù)將無(wú)法使用。建議設(shè)置緩存時(shí)間為7198秒,因?yàn)楫?dāng)請(qǐng)求微信端生成jsapi_ticket返回給后臺(tái)保存這個(gè)動(dòng)作需要時(shí)間,如果設(shè)置7200秒,實(shí)際上最后一兩秒時(shí),緩存里面還存在,但實(shí)際在微信那邊已經(jīng)過(guò)期了,再拿這個(gè)ticket會(huì)出錯(cuò)。生成jsapi_ticket如下:
(1)獲取普通access_token(GET請(qǐng)求):
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
(2)用第一步獲取的access_token使用GET請(qǐng)求獲取jsapi_ticket
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
正確獲取信息如下:
{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}
2、生成簽名(signature)
簽名規(guī)則:
1、參與簽名的字段包括noncestr(隨機(jī)字符串), 有效的jsapi_ticket, timestamp(時(shí)間戳), url(當(dāng)前網(wǎng)頁(yè)的URL,不包含#及其后面部分)。
2、對(duì)所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序,sort()即可)后,使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串(string)。
3、使用sha1加密拼接成的字符串string。
注意:字段名和字段值都要使用原值,不要進(jìn)行url轉(zhuǎn)義
參與的字段示例:
noncestr=Wm3WZYTPz0wzccnW jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg timestamp=1414587457 url=http://mp.weixin.qq.com?params=value
拼接完成的字符串:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
使用sha1加密后的signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
3、簽名生成完后將appId、timestamp、nonceStr、signature一起返回到前端。格式示例:
{
appId:appId,
timestamp:timestamp,
nonceStr: noncestr,
signature: signature
}
前端拿到值后,寫入到wx.config中相應(yīng)字段即可
注意:
1、前端wx.config配置中的nonceStr字段名稱的's'是大寫。但是后臺(tái)生成簽名的noncestr字段的‘s'是小寫,千萬(wàn)要注意,博主在這里浪費(fèi)了不少時(shí)間。囧囧
2、時(shí)間戳(timestamp)值要記住精確到秒,不是毫秒。
3、生成簽名的url(使用jssdk的頁(yè)面地址,這個(gè)頁(yè)面地址可以在瀏覽器訪問(wèn)),包含“?”號(hào)后面的所有參數(shù),不包含“#”號(hào)后面的值。
如果是靜默授權(quán)或者授權(quán)頁(yè)面同意授權(quán)后跳轉(zhuǎn)到的頁(yè)面,頁(yè)面路徑會(huì)添加兩個(gè)參數(shù):code和state。
即授權(quán)后跳轉(zhuǎn)頁(yè)面為http://redirect.page.com,則完整路徑為
http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE。
那么生成簽名的url必須為授權(quán)后跳轉(zhuǎn)頁(yè)面的完整路徑。前端獲取這個(gè)路徑:location.href.split('#')[0]
注意注意:這里有個(gè)大坑。。如果前端使用ajax(使用jquery)獲取wx.config配置所需的幾個(gè)參數(shù)的值,可以這樣做:
$.ajax({
url: 'http://backend.com?fullUrl=' + location.href.split('#')[0], //這里的參數(shù)fullUrl是當(dāng)前頁(yè)面的完整url(除去#后面部分)
type: 'GET',
success: function(res) {
//操作后臺(tái)返回值
}
})
后臺(tái)要怎么操作前端傳過(guò)來(lái)的query值呢?大家肯定一眼看出來(lái) 獲取query中的fullUrl字段不就行了。
博主也是這么做的,請(qǐng)看博主后臺(tái)代碼(使用nodejs的koa框架)
let query = this.request.query;//獲取查詢字符串 let fullUrl = query.fullUrl;//獲取查詢字符串中的fullUrl字段
怎么樣,有沒有看出什么不對(duì)勁的地方?沒有?
博主把所有后續(xù)的獲取access_token、jsapi_ticket、計(jì)算簽名、返回值到前端、前端wx.config配置好這些所有操作做完,信心滿滿的開始用測(cè)試號(hào)訪問(wèn)頁(yè)面。結(jié)果直接彈出config: invalid signature(開啟debug模式)。WTF ???
當(dāng)然,搞這一行早就做好了遇到問(wèn)題的心理準(zhǔn)備。。。。開始排錯(cuò)唄。。
首先在后臺(tái)將獲取access_token、jsapi_ticket、計(jì)算簽名的參數(shù)字典序排序后的字符串、sha1加密后的字符串全部console.log出來(lái)。
發(fā)現(xiàn),沒有錯(cuò)誤的地方。那行,看來(lái)有可能是我代碼那個(gè)地方寫錯(cuò)了,或者簽名算錯(cuò)了?
到微信在線接口調(diào)試把剛剛打印的計(jì)算簽名的幾個(gè)參數(shù)分別填好。生成。。。發(fā)現(xiàn)跟我的代碼生成的是一樣的。
結(jié)果博主是各種排錯(cuò),各種百度,各種google。結(jié)果還是config: invalid signature...................................此處省略博主心里一萬(wàn)句話
又這樣過(guò)了一個(gè)多小時(shí),無(wú)果。。。。。。博主一臉頹廢的到茶水間泡了杯咖啡。。提提神。。又回到了崗位,準(zhǔn)備從頭開始跑一遍再仔細(xì)看看。
從前端請(qǐng)求獲取簽名接口開始,博主打印了query的值。。也就是let query = this.request.query的值。。結(jié)果發(fā)現(xiàn)。query值為:
{
fullUrl: 'http://redirect.page.com?code=kdijafdhjaikeiu20kaiela',
state: 'STATE'
}
好吧,問(wèn)題在這里,有沒有人早就看出來(lái)的?前面說(shuō)過(guò),微信網(wǎng)頁(yè)授權(quán)后跳轉(zhuǎn)的頁(yè)面完整路徑為
http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE
有沒有注意路徑最后面的'&state=STATE'。當(dāng)我們把這個(gè)完整路徑當(dāng)做查詢字符串傳到后臺(tái)的時(shí)候,因?yàn)闆]有對(duì)這個(gè)路徑進(jìn)行encodeURIComponent.所以后臺(tái)將'&state=STATE'單獨(dú)看成了一個(gè)查詢字符串參數(shù),問(wèn)題點(diǎn)在這里。。
后來(lái)查看公眾號(hào)文檔發(fā)現(xiàn)'附錄5-常見錯(cuò)誤及解決方法'第六條有說(shuō)明
問(wèn)題解決
使用encodeURIComponent(location.href.split('#')[0])即可
五、調(diào)用接口
wx.config配置完成后會(huì)執(zhí)行wx.ready方法,所有接口必須要在config返回結(jié)果之后操作。config是一個(gè)客戶端的異步操作,所以如果需要在頁(yè)面加載時(shí)就調(diào)用相關(guān)接口,則須把相關(guān)接口放在ready函數(shù)中調(diào)用來(lái)確保正確執(zhí)行。對(duì)于用戶觸發(fā)時(shí)才調(diào)用的接口,則可以直接調(diào)用,不需要放在ready函數(shù)中。當(dāng)前頁(yè)面要使用的接口,要寫入到config配置中的jsApiList中
1、拍照或從手機(jī)相冊(cè)中選圖接口
document.getElementById('chooseImage').onclick = function(){
wx.chooseImage({
count: 1, // 默認(rèn)9
sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,默認(rèn)二者都有
sourceType: ['album', 'camera'], // 可以指定來(lái)源是相冊(cè)還是相機(jī),默認(rèn)二者都有
success: function (res) {
var localIds = res.localIds; // 返回選定照片的本地ID列表,localId可以作為img標(biāo)簽的src屬性顯示圖片
}
});
}
六、常見問(wèn)題
1、invalid url domain:
js接口安全域名錯(cuò)誤。可以看看第一項(xiàng)
2、invalid signature:
要么是jsapi_ticket錯(cuò)誤,要么是簽名算法問(wèn)題,要么是算法的參數(shù)有問(wèn)題,注意noncestr中的's'是小寫的。如果都是對(duì)的。那就是前端傳的url有問(wèn)題了。。。好好檢查一下,不要像博主一樣啊。。。。
3、permission denied:
這個(gè)問(wèn)題一般是沒有接口權(quán)限的問(wèn)題,有的接口是要認(rèn)證之后才可以使用,當(dāng)然,測(cè)試號(hào)不會(huì)有這個(gè)問(wèn)題
總結(jié)
到此這篇關(guān)于微信公眾號(hào)中的JSSDK接入及invalid signature等常見錯(cuò)誤問(wèn)題分析(全面解析)的文章就介紹到這了,更多相關(guān)微信公眾號(hào)JSSDK接入invalid signature錯(cuò)誤內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js隨機(jī)顏色代碼的多種實(shí)現(xiàn)方式
本篇文章小編為大家介紹,js隨機(jī)顏色代碼的多種實(shí)現(xiàn)方式。需要的朋友參考下2013-04-04
JS實(shí)現(xiàn)簡(jiǎn)單抖動(dòng)效果
這篇文章給大家結(jié)束了通過(guò)js實(shí)現(xiàn)抖動(dòng)效果,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友參考下吧2017-06-06
js實(shí)現(xiàn)表格的隔行變色和上下移動(dòng)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)表格的隔行變色和上下移動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
typescript中 declare global 關(guān)鍵字用法示例小結(jié)
在TypeScript中,declare global 用于在模塊內(nèi)部擴(kuò)展全局作用域,本文重點(diǎn)介紹typescript中 declare global 關(guān)鍵字用法示例小結(jié),感興趣的朋友跟隨小編一起看看吧2024-04-04
同時(shí)使用n個(gè)window onload加載實(shí)例介紹
window onload加載多個(gè)同時(shí)使用,想必有很多人沒有用過(guò)吧,接下來(lái)為大家詳細(xì)介紹下具體的使用方法,感興趣的朋友可以參考下2013-04-04
JavaScript時(shí)間轉(zhuǎn)換處理函數(shù)
這篇文章主要介紹了JavaScript時(shí)間轉(zhuǎn)換處理函數(shù)的方法的相關(guān)資料,需要的朋友可以參考下2015-04-04
javascript實(shí)現(xiàn)table選中的行以指定顏色高亮顯示的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)table選中的行以指定顏色高亮顯示的方法,實(shí)例分析了javascript操作table表格元素與相關(guān)樣式的技巧,需要的朋友可以參考下2015-05-05

