微信公衆號之:JSSDK接入以及invalid signature等常見錯誤問題

最近在搞微信公衆號開發,進行到網頁開發部分被坑了一天,最坑的問題就是invalid signature,而網上大部分解答這個問題的都沒有說清楚,都直接丟文檔。博主認爲這樣很很差。本文是博主結合自身遇到的問題所寫,整個流程跟問題都很詳細,雖然排版可能有點很差。可是絕對對遇到相似問題的朋友有所幫助。請認真看下去javascript

1、綁定JS接口安全域名

生產號綁定方法:登陸微信公衆平臺進入「公衆號設置」的「功能設置」裏填寫「JS接口安全域名」。
測試號綁定方法:進入測試號管理頁面,找到JS接口安全域名項綁定
JS接口安全域名官方說法是:開發者可在該域名下調用微信開放的JS接口
域名格式:若是你的項目域名是http://test.domain.com,那麼JS接口安全域名爲test.domain.com。切記!
域名綁定失敗或者域名不存在會報錯誤:invalid url domain前端

2、引入微信js文件

引入方法:在須要調用JS接口的頁面引入JS文件,用script標籤引入便可
JS文件路徑:http://res.wx.qq.com/open/js/jweixin-1.2.0.js(支持https)java

3、經過wx.config接口注入權限驗證

一、每一個須要使用jssdk的頁面都要使用config接口注入配置信息,wx.config調用方法以下:node

 

  1.  
    wx.config({
  2.  
    debug: true, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。
  3.  
    appId: '', // 必填,公衆號的惟一標識
  4.  
    timestamp: , // 必填,生成簽名的時間戳,精確到秒
  5.  
    nonceStr: '', // 必填,生成簽名的隨機串
  6.  
    signature: '',// 必填,簽名
  7.  
    jsApiList: [] // 必填,須要使用的JS接口列表,例如:['chooseImage','previewImage','uploadImage']
  8.  
    })

其中appId,timestamp,nonceStr,signature必須從後臺獲取jquery

 

4、後臺生成並返回前端所需參數

一、jsapi_ticketajax

jsapi_ticket是公衆號用於調用js接口的臨時票據。有效期7200秒,跟公衆號普通access_token同樣,必須全局緩存起來,由於這個ticket獲取次數有限,超過次數將沒法使用。建議設置緩存時間爲7198秒,由於當請求微信端生成jsapi_ticket返回給後臺保存這個動做須要時間,若是設置7200秒,實際上最後一兩秒時,緩存裏面還存在,但實際在微信那邊已通過期了,再拿這個ticket會出錯。生成jsapi_ticket以下:算法

(1)獲取普通access_token(GET請求): api

 

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 

正確獲取信息以下:緩存

  1.  
    {
  2.  
    "errcode":0,
  3.  
    "errmsg":"ok",
  4.  
    "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  5.  
    "expires_in":7200
  6.  
    }

二、生成簽名(signature)

 

簽名規則:一、參與簽名的字段包括noncestr(隨機字符串), 有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其後面部分)。二、對全部待簽名參數按照字段名的ASCII 碼從小到大排序(字典序,sort()便可)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串(string)。三、使用sha1加密拼接成的字符串string。注意:字段名和字段值都要使用原值,不要進行url轉義

參與的字段示例:

  1.  
    noncestr=Wm3WZYTPz0wzccnW
  2.  
    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
  3.  
    timestamp= 1414587457
  4.  
    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

三、簽名生成完後將appId、timestamp、nonceStr、signature一塊兒返回到前端。格式示例:

 

  1.  
    {
  2.  
    appId:appId,
  3.  
    timestamp:timestamp,
  4.  
    nonceStr: noncestr,
  5.  
    signature: signature
  6.  
    }

前端拿到值後,寫入到wx.config中相應字段便可

注意:

一、前端wx.config配置中的nonceStr字段名稱的's'是大寫。可是後臺生成簽名的noncestr字段的‘s’是小寫,千萬要注意,博主在這裏浪費了很多時間。囧囧

二、時間戳(timestamp)值要記住精確到秒,不是毫秒。

三、生成簽名的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配置所需的幾個參數的值,能夠這樣作:

  1.  
    $.ajax({
  2.  
    url: 'http://backend.com?fullUrl=' + location.href.split('#')[0], //這裏的參數fullUrl是當前頁面的完整url(除去#後面部分)
  3.  
    type: 'GET',
  4.  
    success: function(res) {
  5.  
    //操做後臺返回值
  6.  
    }
  7.  
    })

 

後臺要怎麼操做前端傳過來的query值呢?你們確定一眼看出來 獲取query中的fullUrl字段不就好了。

博主也是這麼作的,請看博主後臺代碼(使用nodejs的koa框架)

  1.  
    let query = this.request.query;//獲取查詢字符串
  2.  
    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值爲:

  1.  
    {
  2.  
    fullUrl: 'http://redirect.page.com?code=kdijafdhjaikeiu20kaiela',
  3.  
    state: 'STATE'
  4.  
    }

 

好吧,問題在這裏,有沒有人早就看出來的?前面說過,微信網頁受權後跳轉的頁面完整路徑爲

http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE

有沒有注意路徑最後面的'&state=STATE'。當咱們把這個完整路徑當作查詢字符串傳到後臺的時候,由於沒有對這個路徑進行encodeURIComponent.因此後臺將'&state=STATE'單獨當作了一個查詢字符串參數,問題點在這裏。。

後來查看公衆號文檔發現'附錄5-常見錯誤及解決方法'第六條有說明

問題解決

使用encodeURIComponent(location.href.split('#')[0])便可

5、調用接口

wx.config配置完成後會執行wx.ready方法,全部接口必需要在config返回結果以後操做。config是一個客戶端的異步操做,因此若是須要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。對於用戶觸發時才調用的接口,則能夠直接調用,不須要放在ready函數中。當前頁面要使用的接口,要寫入到config配置中的jsApiList中

一、拍照或從手機相冊中選圖接口

  1.  
    document.getElementById('chooseImage').onclick = function(){
  2.  
    wx.chooseImage({
  3.  
    count: 1, // 默認9
  4.  
    sizeType: [ 'original', 'compressed'], // 能夠指定是原圖仍是壓縮圖,默認兩者都有
  5.  
    sourceType: [ 'album', 'camera'], // 能夠指定來源是相冊仍是相機,默認兩者都有
  6.  
    success: function (res) {
  7.  
    var localIds = res.localIds; // 返回選定照片的本地ID列表,localId能夠做爲img標籤的src屬性顯示圖片
  8.  
    }
  9.  
    });
  10.  
    }

 

6、常見問題

一、invalid url domain:

js接口安全域名錯誤。能夠看看第一項

二、invalid signature:

要麼是jsapi_ticket錯誤,要麼是簽名算法問題,要麼是算法的參數有問題,注意noncestr中的's'是小寫的。若是都是對的。那就是前端傳的url有問題了。。。好好檢查一下,不要像博主同樣啊。。。。

三、permission denied:

這個問題通常是沒有接口權限的問題,有的接口是要認證以後纔可使用,固然,測試號不會有這個問題

 

轉:

https://blog.csdn.net/u011225099/article/details/76460197

相關文章
相關標籤/搜索