NodeJs 開發微信公眾號(四)微信網頁授權


微信的網頁授權指的是在微信公眾號中訪問第三方網頁時獲取用戶地理、個人等信息的權限。對於開發了自己的網頁app應用時,獲取個人的信息非常重要。上篇博客講到了注冊時可以獲取用戶的信息,很多人會問為什么還需要網頁授權這種方式去獲取呢,直接從數據庫中讀取不就可以了嗎?這樣的做的原因是服務器會話時間終究是有限的,關注后我們設置的會話一般在半個月左右,半個月后就需要重新生成會話,而這時就需要網頁授權的openid幫忙了。況且,用戶的信息也是會刷新的,雖然這種情況很少發生,但是我們至少應該確保信息是有一定的更新機制的。綜上所述,由於會話機制和更新機制,我們需要用到網頁授權。網頁授權機制比較繁瑣,步驟頗多,開發者在開發之前需要仔細閱讀開發文檔,不然會走很多彎路,鹵煮也是吃了這方面的虧。本篇文章就來談一談微信的網頁授權過程。

access_token(1)更新機制

很多接口需要用到這個access_token(1),之所以在后面加個(1)是為了區分另外一個網頁授權access_token(2),他們之間的概念是不一樣的,這里講普通的access_token(1)。access_token(1)是你調用其他接口的憑證,它是通過以下接口生成的:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxxxxxx&secret=xxxxxxxxx

請求以上接口會給你返回一個access_toke(1), 它有個有效時間,為7200s,一旦過了這個時間,再去使用它會報錯。因此,必須建立一個刷新機制。我的辦法是在服務器啟動的時候去生成一次token,把它存入數據庫,然后建立一個定時器,每隔7200s就再次請求接口獲取新的token存入數據庫,這樣可以保證服務器運行的階段,數據庫中的表最后一條記錄的是最新的token。每次需要用到這個token時候就先去表中查最后一條記錄。如果只是臨時使用,完全可以手動在瀏覽器調用接口生成toke,或者用postman工具。

/*啟動時 定時獲取刷新微信的token 並且存入數據庫*/
(function() {
  request(config('wechat').refreshUrl, function(err, res, body) {
    body = JSON.parse(body);
    var accessSql = 'INSERT INTO `access_token` (token) VALUES ("' + body.access_token + '")';
    Query.call(res, accessSql, function() {
      setTimeout(arguments.callee, config('wechat').refreshTime * 1000);
    });
  });
})();

創建網頁菜單

創建網頁菜單使用如下接口:

 https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

需要注意,菜單創建的接口只支持post發送的格式,因此,你的接口必須發送post請求。由於菜單不是一個經常需要變動的東西,鹵煮創建菜單使用的是人工手動的方式進行創建。用的是postman發送特定數據到接口創建菜單。

發送的數據如圖所示,多級菜單只需要數據嵌套就好了。有個key值,我在上一篇文章中提到過,點擊該菜單時發送的xml包中接收到這個值。

網頁授權獲取用戶openid

由於在關注的時候我們已經獲取到用戶的openid和用戶信息(見前一篇張),因此,需要只需要用戶的會話結束,我們才需要中心獲取openid來建立會話。獲取openid第一步,會話過期后服務器后台跳轉到下面地址

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

appid不解釋,redirect_uri即重定向后回掉的地址,一般寫自己后台的接口地址。response_type寫”code“就好了,scope指的是是否需要顯示一個需要用戶確認的界面如下所示:

如果是不需要直接填寫snsapi_base獲取openid,需要用戶確認則獲取所有信息請填寫snsapi_userinfo,我們這里只需要openid,其他信息都在關注的時候存到數據庫里面了。最后一個寫死來“wechat_redirect”。用戶點擊確認登錄或者在不需要點擊確認的情況下過個幾秒鍾,微信會將地址重定向到你填寫的url上,並且附帶了兩個參數redirect_uri?code=CODE&state=STATE。code是你換取access_toke(2)的票據,state表述狀態,不需要關注。在你的回掉接口里面獲取到code,然后將code作為參數post或者get請求以下連接,獲取access_token(2):

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

該請求會返回一段json數據,里面就包含了我們需要的openid。

{
   "access_token":"ACCESS_TOKEN",
   "expires_in":7200,
   "refresh_token":"REFRESH_TOKEN",
   "openid":"OPENID",
   "scope":"SCOPE",
   "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

接下來,以此openid為憑據,調用以下接口獲取用戶最新的信息:

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

access_token指的是access_toke(2),openid是上面的獲取的openid,lang指的是數據的語言。默認為中文。你會獲得以下json數據:

將它們更新到原有的表中(視情況而定,如果你覺得用戶不經常更改自己的信息可以設置更新時間一個月或者半年),然后建立新的會話,至此,一個網頁授權過程就結束了。

access_token(2)更新機制

在網頁授權的過程中,也會遇到access_token(2)過期的問題,因此,我們也必須為它建立一個刷新機制。(微信搞得真的是很麻煩)。

首先,在使用access_toke(2)之前,我們先驗證這個toke是否有效,請求以下接口進行驗證:

https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

錯誤的時候會返回如下數據

{ "errcode":40003,"errmsg":"invalid openid"}

這時候,我們就需要刷新這個token了,以下是刷新的接口:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

這里有一個refresh_toke指的是你去請求access_token(2)的接口返回的數據中的一個值。grant_tyoe直接填寫為”refresh_token“。這樣就刷新了一個token(2)。該token只是在網頁授權時使用,可以不需要儲存在表中,臨時使用即可。

代碼實現

我在這里使用的是一個第三方開發的模塊,來處理一整套的token維護流程,它叫wechat-oauth。使用起來比較方便,源碼也很好調試,自己稍微改了改。后面會貼出github的地址來,這個系列有很多,包括自動回復,圖文消息等,大家有興趣自己下載使用。當然,不嫌麻煩可以自己寫。

var user = req.session['user'] || req.query._user;
//未登錄的情況或者登錄失效 網頁調試無需走微信通道
if (user === undefined && !config('app').webDebug) {
var wxconfig = config('wechat');
//使用模塊 var client = new OAuth(wxconfig.appId, wxconfig.appSecret); var url = client.getAuthorizeURL(config('app').url + wxconfig.callbackUrl, 'snsapi_userinfo');
//后台跳轉 res.redirect(url); return; } fn.call(null, req, res, next);

獲取code然后發送請求獲取opeind

var client = new OAuth(wxConfig.appId, wxConfig.appSecret);
//................
//獲取微信返回的網頁TOKEN 該接口為回掉接口 app.get('/login/getpagetokenkey', function(req, res, next) { var code = req.query.code; //微信返回的code值,作為下一步的票券 //獲取票券 client.getAccessToken(code, function(err, result) { var openid = result.data.openid; //查詢數據庫有沒有該用戶 var sql = 'SELECT * FROM `wechat` WHERE openid= "' + openid + '"'; Query.call(res, sql, function(err, rows, filed) { if(rows.length) {
//重新建立會話跳轉到主界面 setSession(openid, res, req); } }); }); return; });

注意

在獲取用戶信息的時候的時候千萬不要調試斷點nodejs,因為微信會在發送給你的接口后設置一個等待時限,大概是6s,一旦過了這時限沒有返回數據,而此時你如果在調試代碼的話,很容易就會超過等待時間,接着微信就會再次發送一次請求給你的接口,這樣會導致程序報錯或者至少讓你處理兩次信息。鹵煮吃了大虧,調了一個下午,接近奔潰的邊緣。希望諸位要牢記此點,切記在獲取授權的時候不要調試nodejs。

參考資料

 wechat-oauth NodeJS開發微信交互模塊

 微信公眾號開發官方文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM