教你如何用node.js開發微信公眾號(二)
在前一篇文章中,已經介紹瞭如何去配置微信公眾平臺以及如何用 node.js
去處理一些使用者發起的主動行為。有需要了解的點我去上一篇
那麼在這篇文章將繼續講解如何用 node.js
去開發微信公眾號,主要內容包括 access_token
的生成,各種 api
的呼叫,還有前端如何去呼叫微信提供的 jsapi
。
呼叫微信介面
呼叫微信介面,最重要的就是要先獲取 access_token
,沒有 access_token
的話,就無法調通任何微信提供的介面。那麼如何獲取 access_token
呢?來看一段程式碼:

下面來解釋一下這段程式碼做了什麼事情:
- 定義了
appid和secret
,這兩個是由微信公眾平臺提供的,不明白的轉到上一篇; - 微信會提供一個獲取
access_token
介面:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}
,就是圖中用request呼叫的介面,該請求是一個GET
請求,該有三個引數,其中grant_type
是固定的填寫client_credential
,appid和secret
分別是微信公眾平臺配置的appid和secret
; - 呼叫後會返回一個
json
,如果獲取成功的話json
中會有一個access_token
,我這邊是存在一個全域性的變數wechat_access_token
裡面(當然這樣的話會存在很多問題,能力有限,輕噴);然後存了一個獲取access_token
的時間戳,用於判斷access_token
是否過期(官方文件給的access_token
是7200秒),我這裡設定了6000秒就重新獲取access_token
;
說明: 獲取access_token
的介面的呼叫次數是有限制的,不能每次進來就呼叫介面去拿access_token
,特別是測試公眾號,次數很快就用完了;具體的可以看官方文件,文件地址點我!
用獲取使用者列表來說明如何根據 access_token
來呼叫其他的微信介面
來看一下官方給出的獲取使用者列表介面文件:

介面文件的說明已經特別很明白了,這裡不做過多說明,直接看下我這邊是如何呼叫的吧!

就是這麼簡單,相信大家都能看懂,這裡就不做過多的解釋了!
呼叫微信其他介面的方式也大同小異,基本上就是引數和呼叫方式的區別。更多的資料查詢相關的官方文件吧!
提示:呼叫失敗的時候的錯誤提示如下:

前端JS-SDK的使用
最最最最最重要的一點,生成JS-SDK使用許可權簽名。
1. 獲取jsapi_ticket
看如下程式碼:

根據 ACCESS_TOKEN
呼叫 https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${ACCESS_TOKEN}&type=jsapi
獲取 ACCESS_TOKEN
,由於該介面也有次數限制,所以把結果的 ticket
存到全域性變數中(有效2個小時);
2. 生成簽名signature
話不多說,上圖:

生成簽名4要素: jsapiTicket,nonceStr,timestamp,url
;按照順序拼接成一個字串(必須按照順序),官方文件也有說明;
簽名演算法規則(官方文件原文):參與簽名的欄位包括 noncestr(隨機字串)
,有效的 jsapi_ticket, timestamp(時間戳),url(當前網頁的URL,不包含#及其後面部分)
。對所有待簽名引數按照欄位名的 ASCII
碼從小到大排序(字典序)後,使用 URL
鍵值對的格式( 即key1=value1&key2=value2…
)拼接成字串 string1
。這裡需要注意的是所有引數名均為小寫字元。對string1作sha1加密,欄位名和欄位值都採用原始值,不進行 URL
轉義。
即 signature=sha1(string1)
。
3. 返回資料給前端
上圖程式碼中有一段:
res.send({ signture,//生成的簽名 timestamp: timestamp,//定義的時間戳 nonceStr: nonceStr,//定義的隨機字串 appid:"xxxxxxxxx"//公眾號的appid }); 複製程式碼
前端通過 ajax
呼叫 /signture
這個介面,介面會按照以上資料格式返回給前端,前端可以做相應的配置(前端怎麼配置待會說);
到這裡,服務端的工作基本上就差不多了,來看看前端吧!
文件地址點我(文件開啟以後拉到附錄部分才是生成JS-SDK使用許可權簽名的內容);
配置JS-SDK
1.域名繫結
需要在公眾平臺配置 JS
介面安全域名,只有在該域名下的頁面才能正常使用 JS-SDK
;

2.引入JS檔案
在需要呼叫JS介面的頁面引入如下JS檔案,(支援https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js
3.通過config介面注入許可權驗證配置
來看一下官方給出的配置:
wx.config({ debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。 appId: '', // 必填,公眾號的唯一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名 jsApiList: [] // 必填,需要使用的JS介面列表 }); wx.ready(function(){ // config資訊驗證後會執行ready方法,所有介面呼叫都必須在config介面獲得結果之後,config是一個客戶端的非同步操作,所以如果需要在頁面載入時就呼叫相關介面,則須把相關介面放在ready函式中呼叫來確保正確執行。對於使用者觸發時才呼叫的介面,則可以直接呼叫,不需要放在ready函式中。 }); wx.error(function(res){ // config資訊驗證失敗會執行error函式,如簽名過期導致驗證失敗,具體錯誤資訊可以開啟config的debug模式檢視,也可以在返回的res引數中檢視,對於SPA可以在這裡更新簽名。 }); 複製程式碼
這個文件中有,不做解釋了,給大家看一段我自己做測試的時候跑通的程式碼吧:
<script> $.ajax({ url: "http://www.example.com/signture", success: function (res) { wx.config({ debug: true, appId: res.appid,//公眾號的唯一標識 timestamp: res.timestamp,//必須與後端生成的一致 nonceStr: res.nonceStr,//必須與後端生成的一致 signature: res.signture,//必須與後端生成的一致 jsApiList: [ 'checkJsApi', "scanQRCode", "chooseImage" ] }); wx.ready(function () { wx.chooseImage({ count: 1, // 預設9 sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,預設二者都有 sourceType: ['album', 'camera'], // 可以指定來源是相簿還是相機,預設二者都有 success: function (res) { //alert(JSON.stringify(res)) var localIds = res.localIds; // 返回選定照片的本地ID列表,localId可以作為img標籤的src屬性顯示圖片 var img = document.createElement("img"); img.src = localIds[0]; document.querySelector("body").append(img); } }); }); } }); </script> 複製程式碼
首先看一下 wx.config
的配置,由於 timestamp,nonceStr,signature
必須與後端的保持一致,所以我這個地方都是通過 /signture
介面拿到這些資料,保持前後端資料的一致性(上文提到說通過 /signture
介面把資料返回給前端,在這裡就用到啦!)。 jsApiList
是所要呼叫的 jsapi
介面列表,有很多,需要用到哪些就配哪些。
對於 wx.ready
,官方文件做了很明確的說明,不做過多解釋,上面的案例就是在頁面初始化的時候去呼叫拍照或從手機相簿中選圖介面,然後上傳圖片,並展示在介面中,相信大家都能夠看懂吧!
微信官方文件有一系列 jsapi
列表,包括分享,搖一搖,支付,影象處理......
總結
後面前端配置部分講的有點籠統,主要官方文件這部分也寫的特別詳細,然後相信大家都是優秀的小夥伴,都能看懂,所以偷懶了點;這裡主要給大家列一下坑點:
- 獲取
access_token和jsapiTicket
介面的呼叫次數是有限的,所以獲取了access_token和jsapiTicket
之後要快取起來(不管用那種快取技術),每次獲取的有效期2小時; - 生成
JS-SDK
使用許可權簽名時,用sha1()
加密的字串一定要嚴格按照官方文件的格式拼接; - 前端配置
wx.config
的時候,timestamp,nonceStr,signature
三個值必須和服務端的保持一致,所以這裡我建議通過介面去獲取;