详解Node.js access_token的获取、存储及更新
一、写在前面的话
上一篇文章中,我们使用 Node.js 成功的实现了接入微信公众平台功能。在这篇文章中,我们将实现微信公众平台一个非常重要的参数 aess_token ,它是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用 aess_token。
在开始之前,让我们先按捺住自己激动的心情、调整好呼吸,因为我们要将上一篇文章的代码重新整理一下。一个好的项目结构,更能有助于我们理清业务逻辑以及将来维护代码的便捷。OK?
二、整理项目结构
1.打开我们的项目,并在项目中添加文件夹,命名为 wechat ,如图:
2.在 wechat 文件夹中添加文件并命名为 wechat.js。wechat.js 主要用于封装开发微信公众平台的所有方法。我们构建这个模块的结构,代码如下
'use strict' //设置为严格模式 //构建 WeChat 对象 即 js中 函数就是对象 var WeChat = function(config){ //设置 WeChat 对象属性 config this.config = config; //设置 WeChat 对象属性 token this.token = config.token; } //暴露可供外部访问的接口 module.exports = WeChat;
严格模式是在 ECMAScript 5 中引入的概念。严格模式是为 Javascript 定义了一种解析与执行模型。
module.exports 暴露接口用于外部操作。实际上我们定义模块后,使用 node.js 的 require 引用时,node.js 会自动在我们定义的模块外层加入以下代码
/ exports module.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 的值。——
也就是说 exports 是 module.exports 的引用,而 module.exports 才是真正用于暴露接口的对象。 exports 赋值的所有属性与方法都赋值给了 module.exports 对象。
如果 module.exports 与 exports 将值赋值给了相同的属性,则按照赋值的先后顺序,取一个赋值;如果我们给 module.exports 赋值的是一个对象,则会覆盖 exports 的所有方法与属性。
我们在暴露接口的使用上,如果只是单一属性或方法的话,建议使用exports.属性/方法,要是导出多个属性或方法或使用对象构造方法,建议使用 module.exports。
3.为 WeChat 对象添加一个方法 auth,并将 app.js 中的验证方法粘贴进去
'use strict' //设置为严格模式 const crypto = require('crypto'); //引入加密模块 //构建 WeChat 对象 即 js中 函数就是对象 var WeChat = function(config){ //设置 WeChat 对象属性 config this.config = config; //设置 WeChat 对象属性 token this.token = config.token; } / 微信接入验证 / WeChat.prototype.auth = function(req,res){ //1.获取微信服务器Get请求的参数 signature、timestamp、nonce、echostr var signature = req.query.signature,//微信加密签名 timestamp = req.query.timestamp,//时间戳 nonce = req.query.nonce,//随机数 echostr = req.query.echostr;//随机字符串 //2.将token、timestamp、nonce三个参数进行字典序排序 var array = [this.token,timestamp,nonce]; array.sort(); //3.将三个参数字符串拼接成一个字符串进行sha1加密 var tempStr = array.join(''); const hashCode = crypto.createHash('sha1'); //创建加密类型 var resultCode = hashCode.update(tempStr,'utf8').digest('hex'); //对传入的字符串进行加密 //4.开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 if(resultCode === signature){ res.send(echostr); }else{ res.send('mismatch'); } } //暴露可供外部访问的接口 module.exports = WeChat;
4.整理 app.js 文件的中的代码,如下
const express = require('express'), //express 框架 wechat = require('./wechat/wechat'), config = require('./config');//引入配置文件 var app = express();//实例express框架 var wechatApp = new wechat(config); //实例wechat 模块 //用于处理所有进入 3000 端口 get 的连接请求 app.get('/',function(req,res){ wechatApp.auth(req,res); }); //监听3000端口 app.listen(3000);
嗯!这样代码看着是不是舒服多了呢。机智如我
剩下的就是去微信公众平台接入验证了,在上一篇文章中有详细的教程,这里我就不再演示了
就是这么懒
三、aess_token的获取、存储及更新
1.微信文档步骤
在开始码代码之前,我们依然是先理清实现的思路,在开始编写实现代码。打开 微信帮助文档 ,点击左侧菜单中的开始开发,点击其子菜单获取aess_token,如图
通过上面的 API 的描述,我们出以下步骤
1.实现 https Get 请求
2.获取 aess_token 并存储 如果 当前 aess_token 过期则更新
2.aess_token的获取、存储及更新 代码实现
整理好思路后我们就按照上一节的步骤去实现。通过帮助文档我们将用于请求微信API 的请求地址与参数,存放到 config.json 文件。
其中 appid 与 secret 两个参数 位于 微信公众平台 左侧菜单的基本配置中,如图
开发者密码 点击重置,用手机微信扫面二维码后便可得到。config.json 代码如下
{ "token":"wechat", "appID":"wx154f764da", "appScrect":"59de42668dbe9de4b798cd372", "apiDomain":"https://api.weixin.qq./", "apiURL":{ "aessTokenApi":"%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){ return new Promise(function(resolve,reject){ https.get(url,function(res){ var buffer = [],result = ""; //监听 data 事件 res.on('data',function(data){ buffer.push(data); }); //监听 数据传输完成事件 res.on('end',function(){ result = Buffer.concat(buffer,buffer.length).toString('utf-8'); //将结果返回 resolve(result); }); }).on('error',function(err){ reject(err); }); }); }
提示
npm 提供了很多用于请求的工具包,比如 request ( 安装命令 npm install request ) 等。这里我只是用系统包去做请求处理。
由于 https 是异步请求的,我在这里面使用了 ES6 的 Promise 对象 。
完成了 requestGet方法后,我们的第1步骤也就完成了。狼蚁网站SEO优化开始第2步,获取 aess_token 并存储 如果 当前 aess_token 过期则更新。
在这之前我是想将 aess_token 的存储位置依然放在 config.json 文件中,由于 aess_token 在更新后 需要将文件重写,可能容易造成 config.json 文件的格式的紊乱,在 wechat 中重新创建一个 aessToken.json 文件用于存储 aess_token
{ "aess_token":"", "expires_time":0 }
其中 aess_token 用于存储 我们 GET 请求后aess_token 的值,expires_time 用于存储 aess_token 的过期时间,保存为时间戳。
在 wechat.js 引入 fs 模块用于操作文件、util 工具模块用于处理占位符、 aessToken.json 文件
'use strict' //设置为严格模式 const crypto = require('crypto'), //引入加密模块 https = require('https'), //引入 htts 模块 util = require('util'), //引入 util 工具包 aessTokenJson = require('./aess_token'); //引入本地存储的 aess_token //构建 WeChat 对象 即 js中 函数就是对象 var WeChat = function(config){ //设置 WeChat 对象属性 config this.config = config; //设置 WeChat 对象属性 token this.token = config.token; //设置 WeChat 对象属性 appID this.appID = config.appID; //设置 WeChat 对象属性 appScrect this.appScrect = config.appScrect; //设置 WeChat 对象属性 apiDomain this.apiDomain = config.apiDomain; //设置 WeChat 对象属性 apiURL this.apiDomain = config.apiURL; //用于处理 https Get请求方法 this.requestGet = function(url){ return new Promise(function(resolve,reject){ https.get(url,function(res){ var buffer = [],result = ""; //监听 data 事件 res.on('data',function(data){ buffer.push(data); }); //监听 数据传输完成事件 res.on('end',function(){ result = Buffer.concat(buffer,buffer.length).toString('utf-8'); //将结果返回 resolve(result); }); }).on('error',function(err){ reject(err); }); }); } }
在 wechat.js 添加获取 aess_token 的方法 getAessToken
/ 获取微信 aess_token / WeChat.prototype.getAessToken = function(){ var that = this; return new Promise(function(resolve,reject){ //获取当前时间 var currentTime = new Date().getTime(); //格式化请求地址 var url = util.format(that.apiURL.aessTokenApi,that.apiDomain,that.appID,that.appScrect); //判断 本地存储的 aess_token 是否有效 if(aessTokenJson.aess_token === "" || aessTokenJson.expires_time < currentTime){ that.requestGet(url).then(function(data){ var result = JSON.parse(data); if(data.indexOf("errcode") < 0){ aessTokenJson.aess_token = result.aess_token; aessTokenJson.expires_time = new Date().getTime() + (parseInt(result.expires_in) - 200) 1000; //更新本地存储的 fs.writeFile('./wechat/aess_token.json',JSON.stringify(aessTokenJson)); //将获取后的 aess_token 返回 resolve(aessTokenJson.aess_token); }else{ //将错误返回 resolve(result); } }); }else{ //将本地存储的 aess_token 返回 resolve(aessTokenJson.aess_token); } }); }
在 app.js 中添加新的监听链接用于测试 我们获取的token
//用于请求获取 aess_token app.get('/getAessToken',function(req,res){ wechatApp.getAessToken().then(function(data){ res.send(data); }); });
这样我们就大功告成了!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持狼蚁SEO。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程