微信公眾號中的JSSDK接入及invalid signature等常見錯誤問題分析(全面解析)
最近在搞微信公眾號開發,進行到網頁開發部分被坑了一天,最坑的問題就是invalid signature,而網上大部分解答這個問題的都沒有說清楚,都直接丟文件。博主認為這樣很不好。本文是博主結合自身遇到的問題所寫,整個流程跟問題都很詳細,雖然排版可能有點不好。但是絕對對遇到類似問題的朋友有所幫助。請認真看下去
一、繫結JS介面安全域名
生產號繫結方法:登入微信公眾平臺進入“公眾號設定”的“功能設定”裡填寫“JS介面安全域名”。
測試號繫結方法:進入測試號管理頁面,找到JS介面安全域名項繫結
JS介面安全域名官方說法是:開發者可在該域名下呼叫微信開放的JS介面
域名格式:如果你的專案域名是http://test.domain.com,那麼JS介面安全域名為test.domain.com。切記!
二、引入微信js檔案
引入方法:在需要呼叫JS介面的頁面引入JS檔案,用script標籤引入即可
JS檔案路徑:http://res.wx.qq.com/open/js/jweixin-1.2.0.js(支援https)
三、通過wx.config介面注入許可權驗證
1、每個需要使用jssdk的頁面都要使用config介面注入配置資訊,wx.config呼叫方法如下:
wx.config({ debug: true,// 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。 appId: '',// 必填,公眾號的唯一標識 timestamp:,// 必填,生成簽名的時間戳,精確到秒 nonceStr: '',// 必填,生成簽名的隨機串 signature: '',// 必填,簽名 jsApiList: [] // 必填,需要使用的JS介面列表,例如:['chooseImage','previewImage','uploadImage'] })
其中appId,timestamp,nonceStr,signature
必須從後臺獲取
四、後臺生成並返回前端所需引數
1、jsapi_ticket
jsapi_ticket是公眾號用於呼叫js介面的臨時票據。有效期7200秒,跟公眾號普通access_token一樣,必須全域性快取起來,因為這個ticket獲取次數有限,超過次數將無法使用。建議設定快取時間為7198秒,因為當請求微信端生成jsapi_ticket返回給後臺儲存這個動作需要時間,如果設定7200秒,實際上最後一兩秒時,快取裡面還存在,但實際在微信那邊已經過期了,再拿這個ticket會出錯。生成jsapi_ticket如下:
(1)獲取普通access_token(GET請求):
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
(2)用第一步獲取的access_token使用GET請求獲取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)
簽名規則:
1、參與簽名的欄位包括noncestr(隨機字串),有效的jsapi_ticket,timestamp(時間戳),url(當前網頁的URL,不包含#及其後面部分)。
2、對所有待簽名引數按照欄位名的ASCII 碼從小到大排序(字典序,sort()即可)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字串(string)。
3、使用sha1加密拼接成的字串string。
注意:欄位名和欄位值都要使用原值,不要進行url轉義
參與的欄位示例:
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中相應欄位即可
注意:
1、前端wx.config配置中的nonceStr欄位名稱的's'是大寫。但是後臺生成簽名的noncestr欄位的‘s'是小寫,千萬要注意,博主在這裡浪費了不少時間。囧囧
2、時間戳(timestamp)值要記住精確到秒,不是毫秒。
3、生成簽名的url(使用jssdk的頁面地址,這個頁面地址可以在瀏覽器訪問),包含“?”號後面的所有引數,不包含“#”號後面的值。
如果是靜默授權或者授權頁面同意授權後跳轉到的頁面,頁面路徑會新增兩個引數:code和state。
即授權後跳轉頁面為http://redirect.page.com,則完整路徑為
http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE。
那麼生成簽名的url必須為授權後跳轉頁面的完整路徑。前端獲取這個路徑:location.href.split('#')[0]
注意注意:這裡有個大坑。。如果前端使用ajax(使用jquery)獲取wx.config配置所需的幾個引數的值,可以這樣做:
$.ajax({ url: 'http://backend.com?fullUrl=' + location.href.split('#')[0], //這裡的引數fullUrl是當前頁面的完整url(除去#後面部分) type: 'GET',success: function(res) { //操作後臺返回值 } })
後臺要怎麼操作前端傳過來的query值呢?大家肯定一眼看出來 獲取query中的fullUrl欄位不就行了。
博主也是這麼做的,請看博主後臺程式碼(使用nodejs的koa框架)
let query = this.request.query;//獲取查詢字串 let fullUrl = query.fullUrl;//獲取查詢字串中的fullUrl欄位
怎麼樣,有沒有看出什麼不對勁的地方?沒有?
博主把所有後續的獲取access_token、jsapi_ticket、計算簽名、返回值到前端、前端wx.config配置好這些所有操作做完,信心滿滿的開始用測試號訪問頁面。結果直接彈出config: invalid signature(開啟debug模式)。WTF ???
當然,搞這一行早就做好了遇到問題的心理準備。。。。開始排錯唄。。
首先在後臺將獲取access_token、jsapi_ticket、計算簽名的引數字典序排序後的字串、sha1加密後的字串全部console.log出來。
發現,沒有錯誤的地方。那行,看來有可能是我程式碼那個地方寫錯了,或者簽名算錯了?
到微信線上介面除錯把剛剛列印的計算簽名的幾個引數分別填好。生成。。。發現跟我的程式碼生成的是一樣的。
結果博主是各種排錯,各種百度,各種google。結果還是config: invalid signature...................................此處省略博主心裡一萬句話
又這樣過了一個多小時,無果。。。。。。博主一臉頹廢的到茶水間泡了杯咖啡。。提提神。。又回到了崗位,準備從頭開始跑一遍再仔細看看。
從前端請求獲取簽名介面開始,博主列印了query的值。。也就是let query = this.request.query的值。。結果發現。query值為:
{ fullUrl: 'http://redirect.page.com?code=kdijafdhjaikeiu20kaiela',state: 'STATE' }
好吧,問題在這裡,有沒有人早就看出來的?前面說過,微信網頁授權後跳轉的頁面完整路徑為
http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE
有沒有注意路徑最後面的'&state=STATE'。當我們把這個完整路徑當做查詢字串傳到後臺的時候,因為沒有對這個路徑進行encodeURIComponent.所以後臺將'&state=STATE'單獨看成了一個查詢字串引數,問題點在這裡。。
後來檢視公眾號文件發現'附錄5-常見錯誤及解決方法'第六條有說明
問題解決
使用encodeURIComponent(location.href.split('#')[0])
即可
五、呼叫介面
wx.config配置完成後會執行wx.ready方法,所有介面必須要在config返回結果之後操作。config是一個客戶端的非同步操作,所以如果需要在頁面載入時就呼叫相關介面,則須把相關介面放在ready函式中呼叫來確保正確執行。對於使用者觸發時才呼叫的介面,則可以直接呼叫,不需要放在ready函式中。當前頁面要使用的介面,要寫入到config配置中的jsApiList中
1、拍照或從手機相簿中選圖介面
document.getElementById('chooseImage').onclick = function(){ wx.chooseImage({ count: 1,// 預設9 sizeType: ['original','compressed'],// 可以指定是原圖還是壓縮圖,預設二者都有 sourceType: ['album','camera'],// 可以指定來源是相簿還是相機,預設二者都有 success: function (res) { var localIds = res.localIds; // 返回選定照片的本地ID列表,localId可以作為img標籤的src屬性顯示圖片 } }); }
六、常見問題
1、invalid url domain:
js介面安全域名錯誤。可以看看第一項
2、invalid signature:
要麼是jsapi_ticket錯誤,要麼是簽名演算法問題,要麼是演算法的引數有問題,注意noncestr中的's'是小寫的。如果都是對的。那就是前端傳的url有問題了。。。好好檢查一下,不要像博主一樣啊。。。。
3、permission denied:
這個問題一般是沒有介面許可權的問題,有的介面是要認證之後才可以使用,當然,測試號不會有這個問題
總結
到此這篇關於微信公眾號中的JSSDK接入及invalid signature等常見錯誤問題分析(全面解析)的文章就介紹到這了,更多相關微信公眾號JSSDK接入invalid signature錯誤內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!