摘要:主要用于封裝開(kāi)發(fā)微信公眾平臺(tái)的所有方法。剩下的就是去微信公眾平臺(tái)接入驗(yàn)證了,在上一篇文章中有詳細(xì)的教程,這里我就不再演示了三的獲取存儲(chǔ)及更新微信文檔步驟在開(kāi)始碼代碼之前,我們依然是先理清實(shí)現(xiàn)的思路,在開(kāi)始編寫(xiě)實(shí)現(xiàn)代碼。
一、寫(xiě)在前面的話
??上一篇文章中,我們使用 Node.js 成功的實(shí)現(xiàn)了接入微信公眾平臺(tái)功能。在這篇文章中,我們將實(shí)現(xiàn)微信公眾平臺(tái)一個(gè)非常重要的參數(shù) access_token ,它是公眾號(hào)的全局唯一接口調(diào)用憑據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用 access_token。
??在開(kāi)始之前,讓我們先按捺住自己激動(dòng)的心情、調(diào)整好呼吸,因?yàn)槲覀円獙⑸弦黄恼碌拇a重新整理一下。一個(gè)好的項(xiàng)目結(jié)構(gòu),更能有助于我們理清業(yè)務(wù)邏輯以及將來(lái)維護(hù)代碼的便捷。OK!
1.打開(kāi)我們的項(xiàng)目,并在項(xiàng)目中添加文件夾,命名為 wechat ,如圖:
2.在 wechat 文件夾中添加文件并命名為 wechat.js。wechat.js 主要用于封裝開(kāi)發(fā)微信公眾平臺(tái)的所有方法。首先我們構(gòu)建這個(gè)模塊的結(jié)構(gòu),代碼如下:
"use strict" //設(shè)置為嚴(yán)格模式 //構(gòu)建 WeChat 對(duì)象 即 js中 函數(shù)就是對(duì)象 var WeChat = function(config){ //設(shè)置 WeChat 對(duì)象屬性 config this.config = config; //設(shè)置 WeChat 對(duì)象屬性 token this.token = config.token; } //暴露可供外部訪問(wèn)的接口 module.exports = WeChat;
?嚴(yán)格模式:是在 ECMAScript 5 中引入的概念。嚴(yán)格模式是為 Javascript 定義了一種解析與執(zhí)行模型。
?module.exports :暴露接口用于外部操作。實(shí)際上我們定義模塊后,使用 node.js 的 require 引用時(shí),node.js 會(huì)自動(dòng)在我們定義的模塊外層加入以下代碼
/** * exports module.exports 的一個(gè)簡(jiǎn)短的引用 * require 用于引入模塊 * module 當(dāng)前模塊的引用 * __filename 當(dāng)前模塊的文件名 * __dirname 當(dāng)前模塊的目錄名 */ (function (exports, require, module, __filename, __dirname) { //自定義模塊的代碼塊 })();
相信對(duì)于有過(guò) javascript 開(kāi)發(fā)經(jīng)驗(yàn)的同學(xué),上面的代碼并不陌生。我們可以將它理解為一個(gè)閉包,是一個(gè)匿名方法的調(diào)用,避免污染全局變量。
小知識(shí):??在上面的代碼中,除了我們所使用的 module.exports 對(duì)象,還有另一個(gè)用于暴露接口的 變量 exports (官方文檔將 module.exports 稱(chēng)為對(duì)象,exports 稱(chēng)為 屬性,我在這里也就這樣稱(chēng)呼了),那么 module.exports 與 exports 有什么區(qū)別呢?
??module.exports 對(duì)象是由模塊系統(tǒng)創(chuàng)建的,exports 變量是在模塊的文件級(jí)別作用域內(nèi)有效的,它在模塊被執(zhí)行前被賦于 module.exports 的值。——來(lái)自Node.js官方文檔
??也就是說(shuō) exports 是 module.exports 的引用,而 module.exports 才是真正用于暴露接口的對(duì)象。 exports 賦值的所有屬性與方法都賦值給了 module.exports 對(duì)象。
??如果 module.exports 與 exports 將值賦值給了相同的屬性,則按照賦值的先后順序,取最后一個(gè)賦值;如果我們給 module.exports 賦值的是一個(gè)對(duì)象,則會(huì)覆蓋 exports 的所有方法與屬性。
??因此我們?cè)诒┞督涌诘氖褂蒙希绻皇菃我粚傩曰蚍椒ǖ脑挘ㄗh使用exports.屬性/方法,要是導(dǎo)出多個(gè)屬性或方法或使用對(duì)象構(gòu)造方法,建議使用 module.exports。
??具體詳解可以點(diǎn)擊查看該文章 -> Module.exports和exports的區(qū)別
3.為 WeChat 對(duì)象添加一個(gè)方法 auth,并將 app.js 中的驗(yàn)證方法粘貼進(jìn)去
"use strict" //設(shè)置為嚴(yán)格模式 const crypto = require("crypto"); //引入加密模塊 //構(gòu)建 WeChat 對(duì)象 即 js中 函數(shù)就是對(duì)象 var WeChat = function(config){ //設(shè)置 WeChat 對(duì)象屬性 config this.config = config; //設(shè)置 WeChat 對(duì)象屬性 token this.token = config.token; } /** * 微信接入驗(yàn)證 */ WeChat.prototype.auth = function(req,res){ //1.獲取微信服務(wù)器Get請(qǐng)求的參數(shù) signature、timestamp、nonce、echostr var signature = req.query.signature,//微信加密簽名 timestamp = req.query.timestamp,//時(shí)間戳 nonce = req.query.nonce,//隨機(jī)數(shù) echostr = req.query.echostr;//隨機(jī)字符串 //2.將token、timestamp、nonce三個(gè)參數(shù)進(jìn)行字典序排序 var array = [this.token,timestamp,nonce]; array.sort(); //3.將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密 var tempStr = array.join(""); const hashCode = crypto.createHash("sha1"); //創(chuàng)建加密類(lèi)型 var resultCode = hashCode.update(tempStr,"utf8").digest("hex"); //對(duì)傳入的字符串進(jìn)行加密 //4.開(kāi)發(fā)者獲得加密后的字符串可與signature對(duì)比,標(biāo)識(shí)該請(qǐng)求來(lái)源于微信 if(resultCode === signature){ res.send(echostr); }else{ res.send("mismatch"); } } //暴露可供外部訪問(wèn)的接口 module.exports = WeChat;
4.整理 app.js 文件的中的代碼,如下:
const express = require("express"), //express 框架 wechat = require("./wechat/wechat"), config = require("./config");//引入配置文件 var app = express();//實(shí)例express框架 var wechatApp = new wechat(config); //實(shí)例wechat 模塊 //用于處理所有進(jìn)入 3000 端口 get 的連接請(qǐng)求 app.get("/",function(req,res){ wechatApp.auth(req,res); }); //監(jiān)聽(tīng)3000端口 app.listen(3000);
嗯!這樣代碼看著是不是舒服多了呢。
剩下的就是去微信公眾平臺(tái)接入驗(yàn)證了,在上一篇文章中有詳細(xì)的教程,這里我就不再演示了
三、access_token的獲取、存儲(chǔ)及更新1.微信文檔步驟
??在開(kāi)始碼代碼之前,我們依然是先理清實(shí)現(xiàn)的思路,在開(kāi)始編寫(xiě)實(shí)現(xiàn)代碼。打開(kāi) 微信幫助文檔 ,點(diǎn)擊左側(cè)菜單中的開(kāi)始開(kāi)發(fā),點(diǎn)擊其子菜單獲取access_token,如圖:
通過(guò)上面的 API 的描述,我們總結(jié)出以下步驟:
實(shí)現(xiàn) https Get 請(qǐng)求
獲取 access_token 并存儲(chǔ) 如果 當(dāng)前 access_token 過(guò)期則更新
2.access_token的獲取、存儲(chǔ)及更新 代碼實(shí)現(xiàn)
??整理好思路后我們就按照上一節(jié)的步驟去實(shí)現(xiàn)。通過(guò)幫助文檔我們將用于請(qǐng)求微信API 的請(qǐng)求地址與參數(shù),存放到 config.json 文件。
??其中 appid 與 secret 兩個(gè)參數(shù) 位于 微信公眾平臺(tái) 左側(cè)菜單的基本配置中,如圖:
開(kāi)發(fā)者密碼 點(diǎn)擊重置,用手機(jī)微信掃面二維碼后便可得到。config.json 代碼如下
{ "token":"wechat", "appID":"wx154f********764da", "appScrect":"59de4266*******8dbe9de4b798cd372", "apiDomain":"https://api.weixin.qq.com/", "apiURL":{ "accessTokenApi":"%scgi-bin/token?grant_type=client_credential&appid=%s&secret=%s" } }
由于微信 API 請(qǐng)求連接的域名是公用的,我們將它提出來(lái),在請(qǐng)求地址中使用 %s(字符串) 占位符占位。
??微信所有請(qǐng)求連接都是 https 協(xié)議,很幸運(yùn)的是 Node.js 系統(tǒng)包中為我們提供了 https 的包,由于后面的請(qǐng)求會(huì)多次用到 https ,因此我們將它封裝為一個(gè)公用的方法,以便以后的使用,再次打開(kāi) wechat.js 在構(gòu)造方法中,引入 https 模塊,并在構(gòu)造函數(shù)內(nèi)部添加 requestGet 方法
//用于處理 https Get請(qǐng)求方法 this.requestGet = function(url){ return new Promise(function(resolve,reject){ https.get(url,function(res){ var buffer = [],result = ""; //監(jiān)聽(tīng) data 事件 res.on("data",function(data){ buffer.push(data); }); //監(jiān)聽(tīng) 數(shù)據(jù)傳輸完成事件 res.on("end",function(){ result = Buffer.concat(buffer,buffer.length).toString("utf-8"); //將最后結(jié)果返回 resolve(result); }); }).on("error",function(err){ reject(err); }); }); }
提示:????npm 提供了很多用于請(qǐng)求的工具包,比如 request ( 安裝命令 npm install request ) 等。這里我只是用系統(tǒng)包去做請(qǐng)求處理。
??由于 https 是異步請(qǐng)求的,我在這里面使用了 ES6 的 Promise 對(duì)象 。
??完成了 requestGet方法后,我們的第1步驟也就完成了。下面開(kāi)始第2步,獲取 access_token 并存儲(chǔ) 如果 當(dāng)前 access_token 過(guò)期則更新。
??在這之前我是想將 access_token 的存儲(chǔ)位置依然放在 config.json 文件中,由于 access_token 在更新后 需要將文件重寫(xiě),可能容易造成 config.json 文件的格式的紊亂,因此在 wechat 中重新創(chuàng)建一個(gè) accessToken.json 文件用于存儲(chǔ) access_token
{ "access_token":"", "expires_time":0 }
?? 其中 access_token 用于存儲(chǔ) 我們 GET 請(qǐng)求后access_token 的值,expires_time 用于存儲(chǔ) access_token 的過(guò)期時(shí)間,保存為時(shí)間戳。
??在 wechat.js 引入 fs 模塊用于操作文件、util 工具模塊用于處理占位符、 accessToken.json 文件
"use strict" //設(shè)置為嚴(yán)格模式 const crypto = require("crypto"), //引入加密模塊 https = require("https"), //引入 htts 模塊 util = require("util"), //引入 util 工具包 accessTokenJson = require("./access_token"); //引入本地存儲(chǔ)的 access_token //構(gòu)建 WeChat 對(duì)象 即 js中 函數(shù)就是對(duì)象 var WeChat = function(config){ //設(shè)置 WeChat 對(duì)象屬性 config this.config = config; //設(shè)置 WeChat 對(duì)象屬性 token this.token = config.token; //設(shè)置 WeChat 對(duì)象屬性 appID this.appID = config.appID; //設(shè)置 WeChat 對(duì)象屬性 appScrect this.appScrect = config.appScrect; //設(shè)置 WeChat 對(duì)象屬性 apiDomain this.apiDomain = config.apiDomain; //設(shè)置 WeChat 對(duì)象屬性 apiURL this.apiDomain = config.apiURL; //用于處理 https Get請(qǐng)求方法 this.requestGet = function(url){ return new Promise(function(resolve,reject){ https.get(url,function(res){ var buffer = [],result = ""; //監(jiān)聽(tīng) data 事件 res.on("data",function(data){ buffer.push(data); }); //監(jiān)聽(tīng) 數(shù)據(jù)傳輸完成事件 res.on("end",function(){ result = Buffer.concat(buffer,buffer.length).toString("utf-8"); //將最后結(jié)果返回 resolve(result); }); }).on("error",function(err){ reject(err); }); }); } }
??在 wechat.js 添加獲取 access_token 的方法 getAccessToken
/** * 獲取微信 access_token */ WeChat.prototype.getAccessToken = function(){ var that = this; return new Promise(function(resolve,reject){ //獲取當(dāng)前時(shí)間 var currentTime = new Date().getTime(); //格式化請(qǐng)求地址 var url = util.format(that.apiURL.accessTokenApi,that.apiDomain,that.appID,that.appScrect); //判斷 本地存儲(chǔ)的 access_token 是否有效 if(accessTokenJson.access_token === "" || accessTokenJson.expires_time < currentTime){ that.requestGet(url).then(function(data){ var result = JSON.parse(data); if(data.indexOf("errcode") < 0){ accessTokenJson.access_token = result.access_token; accessTokenJson.expires_time = new Date().getTime() + (parseInt(result.expires_in) - 200) * 1000; //更新本地存儲(chǔ)的 fs.writeFile("./wechat/access_token.json",JSON.stringify(accessTokenJson)); //將獲取后的 access_token 返回 resolve(accessTokenJson.access_token); }else{ //將錯(cuò)誤返回 resolve(result); } }); }else{ //將本地存儲(chǔ)的 access_token 返回 resolve(accessTokenJson.access_token); } }); }
??在 app.js 中添加新的監(jiān)聽(tīng)鏈接用于測(cè)試 我們獲取的token
//用于請(qǐng)求獲取 access_token app.get("/getAccessToken",function(req,res){ wechatApp.getAccessToken().then(function(data){ res.send(data); }); });
??這樣我們就大功告成了!
??文章源代碼:https://github.com/SilenceHVK... 。對(duì)文章有不正確之處,請(qǐng)給予糾正。github源代碼請(qǐng)順手給個(gè) Star,最后感謝您的閱讀。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92121.html
摘要:消息推送也是微信公眾號(hào)開(kāi)發(fā)更為有趣的功能,涉及到文本消息圖片消息語(yǔ)音消息視頻消息音樂(lè)消息以及圖文消息。在文件中創(chuàng)建文件用于消息的管理。 一、寫(xiě)在前面的話 ??當(dāng)用戶(hù)發(fā)送消息給公眾號(hào)時(shí)(或某些特定的用戶(hù)操作引發(fā)的事件推送時(shí)),會(huì)產(chǎn)生一個(gè)POST請(qǐng)求,開(kāi)發(fā)者可以在響應(yīng)包(Get)中返回特定XML結(jié)構(gòu),來(lái)對(duì)該消息進(jìn)行響應(yīng)。 ??消息推送也是微信公眾號(hào)開(kāi)發(fā)更為有趣的功能,涉及到文本消息、圖片消...
摘要:一寫(xiě)在前面的話上一篇文章中,我們使用成功的實(shí)現(xiàn)了的獲取存儲(chǔ)以及更新,這篇文章我們來(lái)實(shí)現(xiàn)微信的自定義菜單功能。二自定義微信菜單微信文檔步驟在開(kāi)始碼代碼之前,我們依然是先理清實(shí)現(xiàn)的思路,再開(kāi)始編寫(xiě)實(shí)現(xiàn)代碼。 一、寫(xiě)在前面的話 ??上一篇文章中,我們使用 Node.js 成功的實(shí)現(xiàn)了access_token 的獲取、存儲(chǔ)以及更新,這篇文章我們來(lái)實(shí)現(xiàn)微信的自定義菜單功能。showImg(htt...
摘要:在微信開(kāi)發(fā)者工具中調(diào)試和一定要正確域名一定是備案的綁定域名需要的放在服務(wù)器上的位置一定要正確參考微信公眾號(hào)開(kāi)發(fā)文檔 node微信公眾號(hào)開(kāi)發(fā) 概覽 key value 項(xiàng)目名稱(chēng) node微信公眾號(hào)開(kāi)發(fā) 項(xiàng)目描述 使用node編寫(xiě)接口,前后端分離獲取簽名數(shù)據(jù) 開(kāi)發(fā)者 leinov 發(fā)布日期 2018-11-07 倉(cāng)庫(kù) github地址 安裝&使用 下載 gi...
摘要:方案二通過(guò)微信公眾號(hào)平臺(tái)提供的接口定時(shí)獲取數(shù)據(jù),然后插入到小程序數(shù)據(jù)庫(kù)中。和可在微信公眾平臺(tái)開(kāi)發(fā)基本配置頁(yè)中獲得需要已經(jīng)成為開(kāi)發(fā)者,且?guī)ぬ?hào)沒(méi)有異常狀態(tài)。 0、介紹 本文源碼:https://github.com/Jameswain/... ? showImg(https://segmentfault.com/img/remote/1460000015441409?w=660&h...
閱讀 709·2021-11-18 10:02
閱讀 3585·2021-09-02 10:21
閱讀 1744·2021-08-27 16:16
閱讀 2061·2019-08-30 15:56
閱讀 2389·2019-08-29 16:53
閱讀 1376·2019-08-29 11:18
閱讀 2959·2019-08-26 10:33
閱讀 2645·2019-08-23 18:34