微信的網頁受權指的是在微信公衆號中訪問第三方網頁時獲取用戶地理、我的等信息的權限。對於開發了本身的網頁app應用時,獲取我的的信息很是重要。上篇博客講到了註冊時能夠獲取用戶的信息,不少人會問爲何還須要網頁受權這種方式去獲取呢,直接從數據庫中讀取不就能夠了嗎?這樣的作的緣由是服務器會話時間終究是有限的,關注後咱們設置的會話通常在半個月左右,半個月後就須要從新生成會話,而這時就須要網頁受權的openid幫忙了。何況,用戶的信息也是會刷新的,雖然這種狀況不多發生,可是咱們至少應該確保信息是有必定的更新機制的。綜上所述,因爲會話機制和更新機制,咱們須要用到網頁受權。網頁受權機制比較繁瑣,步驟頗多,開發者在開發以前須要仔細閱讀開發文檔,否則會走不少彎路,滷煮也是吃了這方面的虧。本篇文章就來談一談微信的網頁受權過程。javascript
不少接口須要用到這個access_token(1),之因此在後面加個(1)是爲了區分另一個網頁受權access_token(2),他們之間的概念是不同的,這裏講普通的access_token(1)。access_token(1)是你調用其餘接口的憑證,它是經過如下接口生成的:html
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工具。java
/*啓動時 定時獲取刷新微信的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); }); }); })();
建立網頁菜單使用以下接口:node
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
須要注意,菜單建立的接口只支持post發送的格式,所以,你的接口必須發送post請求。因爲菜單不是一個常常須要變更的東西,滷煮建立菜單使用的是人工手動的方式進行建立。用的是postman發送特定數據到接口建立菜單。git
發送的數據如圖所示,多級菜單隻須要數據嵌套就行了。有個key值,我在上一篇文章中提到過,點擊該菜單時發送的xml包中接收到這個值。github
因爲在關注的時候咱們已經獲取到用戶的openid和用戶信息(見前一篇張),所以,須要只須要用戶的會話結束,咱們才須要中心獲取openid來創建會話。獲取openid第一步,會話過時後服務器後臺跳轉到下面地址web
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指的是是否須要顯示一個須要用戶確認的界面以下所示:sql
若是是不須要直接填寫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。json
{ "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_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。