1.上一篇文章写的是什么?上一篇我们使用Node.js成功实现了微信公众平台能力的接入。在本文中,我们将实现微信公众平台的一个非常重要的参数access_token,它是公众号的全球唯一接口调用凭证,公众号调用各个接口时都需要access_token。在开始之前,让我们先压抑一下兴奋,调整一下呼吸,因为我们要重新整理上一篇文章的代码。一个好的项目结构可以帮助我们理清业务逻辑,方便以后的代码维护。好的!二、整理项目结构1、打开我们的项目,在项目中添加一个文件夹,命名为wechat,如图:2、在wechat文件夹中添加一个文件,命名为wechat.js。wechat.js主要用于封装开发微信公众平台的所有方法。首先我们构建这个模块的结构,代码如下:'usestrict'//设置为严格模式//构建微信对象,即js中的函数就是对象varWeChat=function(config){//设置微信对象属性configthis.config=config;//设置微信对象属性tokenthis.token=config.token;}//对外暴露接口module.exports=WeChat;严格模式:是ECMAScript5引入的概念,严格模式为Javascript定义了一个解析和执行模型。module.exports:暴露外部操作的接口。其实我们定义模块后,当我们使用node.js的require引用时,node.js会自动在我们定义的模块外添加如下代码/***使用了exportsmodule.exports*require的简短引用引入模块*module当前模块的引用*__filename当前模块的文件名*__dirname当前模块的目录名*/(function(exports,require,module,__filename,__dirname){//代码块自定义模块})();相信对于有javascript开发经验的同学来说,上面的代码并不陌生。我们可以理解为闭包,匿名方法调用,避免污染全局变量。小知识:??上面代码中,除了我们用到的module.exports对象外,还有一个变量exports用来暴露接口(官方文档说module.exports是对象,exports是属性,我也是这么叫的),那么module.exports和exports有什么区别呢?module.exports对象由模块系统创建,exports变量在模块的文件级范围内有效,在模块执行前被赋值为module.exports的值。——摘自Node.js官方文档?也就是说,exports是对module.exports的引用,而module.exports是真正用来暴露接口的对象。exports分配的所有属性和方法都分配给module.exports对象。如果module.exports和exports给同一个属性赋值,则按照赋值顺序取最后一次赋值;如果我们将对象分配给module.exports,exports的所有方法和属性都将被覆盖。所以在暴露接口的使用上,如果只有一个属性或方法,建议使用exports。属性/方法。如果要导出多个属性或方法或者使用对象构造方法,推荐使用module.exports。详情请点击查看这篇文章->Module.exports和exports的区别3.在微信对象中添加一个方法auth,将app.js中的认证方法粘贴进去'usestrict'//设置为严格模式constcrypto=require('crypto');//引入加密模块//构造微信对象,即js中的函数为对象varWeChat=function(config){//设置微信对象属性configthis.config=config;//设置微信对象属性tokenthis.token=config.token;}/***微信访问验证*/WeChat.prototype.auth=function(req,res){//1.获取参数signature,timestamp,nonce,echostrvarsignature=req.query.signature,//微信加密签名timestamp=req.query.timestamp,//时间戳nonce=req.query.nonce,//随机数echostr=req.query.echostr;//随机字符串//2.按字典顺序对令牌、时间戳和随机数进行排序vararray=[this.token,timestamp,nonce];array.sort();//3。将三个参数字符串拼接成一个字符串用sha1加密vartempStr=array.join('');consthashCode=crypto.createHash('sha1');//创建加密类型varresultCode=hashCode.update(tempStr,'utf8').digest('hex');//对于传入的字符串加密//4。开发者获取到的加密字符串,可以与签名进行比对,判断请求来自微信if(resultCode===signature){res.send(echostr);}else{res.send('不匹配');}}//对外暴露接口module.exports=WeChat;4.在app.js文件中组织代码,如下:constexpress=require('express'),//expressframeworkwechat=require('./wechat/wechat'),config=require('./config');//引入配置文件varapp=express();//实例express框架varwechatApp=newwechat(config);//示例微信模块//用于处理所有进入3000端口的连接请求getapp.get('/',function(req,res){wechatApp.auth(req,res);});//在端口3000上监控应用程序。listen(3000);啊!代码看起来更舒服吗?剩下的就是去微信公众平台访问验证了。上一篇文章有??详细教程,这里不再演示。三、access_token的获取、存储和更新1、微信文档步骤在开始写代码之前,我们还是要先梳理一下实现思路,开始编写实现代码。打开微信帮助文档,点击左侧菜单中的开始开发,点击其子菜单获取access_token,如图:通过上面的API描述,我们总结出以下步骤:实现httpsGet请求获取access_token并存储ifthecurrentaccess_tokenexpiresUpdate2.access_token的获取、存储和更新代码实现理清思路后,我们就按照上一节的步骤来实现。通过帮助文档,我们将请求微信API的请求地址和参数保存在config.json文件中。其中appid和secret这两个参数位于微信公众平台左侧菜单的基础配置中,如图:开发者密码点击reset,手机扫描二维码即可获取电话微信。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请求连接的域名是公开的,我们建议,在请求地址中使用%s(字符串)占位符。所有微信请求连接都是https协议。幸运的是,Node.js系统包为我们提供了https包。由于后续请求会多次使用https,所以我们将其封装为一个公共方法,以便以后使用,再次打开wechat.js。在构造方法中,引入https模块,在构造函数中添加requestGet方法//用于处理https的Get请求方法this.requestGet=function(url){returnnewPromise(function(resolve,reject){https.get(url,function(res){varbuffer=[],result="";//监听数据事件res.on('data',function(data){buffer.push(data);});//监听到数据传输完成事件res.on('end',function(){result=Buffer.concat(buffer,buffer.length).toString('utf-8');//添加最后一个Resultreturnsresolve(result);});}).on('错误',function(err){reject(err);});});}Tips:npm提供了很多请求的工具包,比如request(安装命令npminstallrequest)等,这里我只是使用系统包来处理请求。因为https是异步请求,所以我这里使用了ES6的Promise对象。完成requestGet方法后,我们的第一步就完成了。下面开始第二步,获取access_token并存储。如果当前的access_token过期,它将被更新。在此之前,我想将access_token存储在config.json文件中。由于更新后需要重写access_token,容易造成config.json文件格式错乱,所以在微信中新建一个accessToken.json文件,用于存放access_token{"access_token":"","expires_time":0}其中access_token用于存放我们GET请求后access_token的值,expires_time用于存放access_token的过期时间,保存为时间戳。wechat.js中引入fs模块用于操作文件,util工具模块用于处理占位符,accessToken.json文件'usestrict'//设置为严格模式constcrypto=require('crypto'),//引入加密模块https=require('https'),//引入htts模块util=require('util'),//引入util工具包accessTokenJson=require('./access_token');//引入本地存储access_token//构建微信对象,即js中的函数为对象varWeChat=function(config){//设置微信对象属性configthis.config=config;//设置微信对象属性tokenthis.token=config.token;//设置微信对象属性appIDthis.appID=config.appID;//设置微信对象属性appScrectthis.appScrect=config.appScret;//设置微信对象属性apiDomainthis.apiDomain=config.apiDomain;//设置微信对象属性apiURLthis.apiDomain=config.apiURL;//用于处理httpsGet请求方法this.requestGet=function(url){returnnewPromise(function(resolve,reject){https.get(url,function(res){varbuffer=[],result="";//监听数据事件res.on('data',函数(数据){缓冲区.推送(数据);});//监听数据传输完成事件res.on('end',function(){result=Buffer.concat(buffer,buffer.length).toString('utf-8');//返回最终结果resolve(result);});}).on('error',function(err){reject(err);});});}}在微信.js中添加获取access_token的方法getAccessToken/***获取微信access_token*/WeChat.prototype.getAccessToken=function(){varthat=this;returnnewPromise(function(resolve,reject){//获取当前时间varcurrentTime=newDate().getTime();//格式化请求地址varurl=util.format(that.apiURL.accessTokenApi,that.apiDomain,that.appID,that.appScrect);//判断本地存储的access_token是否有效data){varresult=JSON.parse(数据);if(data.indexOf("errcode")<0){accessTokenJson.access_token=result.access_token;accessTokenJson.expires_time=newDate().getTime()+(parseInt(result.expires_in)-200)*1000;//更新本地存储fs.writeFile('./wechat/access_token.json',JSON.stringify(accessTokenJson));//返回获取的access_tokenresolve(accessTokenJson.access_token);}else{//返回错误resolve(result);}});}else{//返回本地存储的access_tokenresolve(accessTokenJson.access_token);}});}在app.js中添加新的监听链接,用于测试我们获取的token//用于请求access_tokenapp.get('/getAccessToken',function(req,res){wechatApp.getAccessToken().then(函数(数据){res.send(数据);});});我们完成了!文章来源代码:https://github.com/SilenceHVK...文中如有不准确之处,敬请指正。请给github源码一个Star,最后感谢阅读。
