一、写在前面的话

上一篇文章中,我们使用 Node.js 成功的实现了接入微信公众平台功能。在这篇文章中,我们将实现微信公众平台一个非常重要的参数 access_token ,它是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用 access_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 的值。——来自Node.js官方文档
也就是说 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);
嗯!这样代码看着是不是舒服多了呢。机智如我
剩下的就是去微信公众平台接入验证了,在上一篇文章中有详细的教程,这里我就不再演示了
就是这么懒
三、access_token的获取、存储及更新
1.微信文档步骤
在开始码代码之前,我们依然是先理清实现的思路,在开始编写实现代码。打开 微信帮助文档 ,点击左侧菜单中的开始开发,点击其子菜单获取access_token,如图:
通过上面的 API 的描述,我们总结出以下步骤:
1.实现 https Get 请求
2.获取 access_token 并存储 如果 当前 access_token 过期则更新
2.access_token的获取、存储及更新 代码实现
整理好思路后我们就按照上一节的步骤去实现。通过帮助文档我们将用于请求微信API 的请求地址与参数,存放到 config.json 文件。
其中 appid 与 secret 两个参数 位于 微信公众平台 左侧菜单的基本配置中,如图:
开发者密码 点击重置,用手机微信扫面二维码后便可得到。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){
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步骤也就完成了。下面开始第2步,获取 access_token 并存储 如果 当前 access_token 过期则更新。
在这之前我是想将 access_token 的存储位置依然放在 config.json 文件中,由于 access_token 在更新后 需要将文件重写,可能容易造成 config.json 文件的格式的紊乱,因此在 wechat 中重新创建一个 accessToken.json 文件用于存储 access_token
{
"access_token":"",
"expires_time":0
}
其中 access_token 用于存储 我们 GET 请求后access_token 的值,expires_time 用于存储 access_token 的过期时间,保存为时间戳。
在 wechat.js 引入 fs 模块用于操作文件、util 工具模块用于处理占位符、 accessToken.json 文件
'use strict' //设置为严格模式
const crypto = require('crypto'), //引入加密模块
https = require('https'), //引入 htts 模块
util = require('util'), //引入 util 工具包
accessTokenJson = require('./access_token'); //引入本地存储的 access_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 添加获取 access_token 的方法 getAccessToken
/**
* 获取微信 access_token
*/
WeChat.prototype.getAccessToken = function(){
var that = this;
return new Promise(function(resolve,reject){
//获取当前时间
var currentTime = new Date().getTime();
//格式化请求地址
var url = util.format(that.apiURL.accessTokenApi,that.apiDomain,that.appID,that.appScrect);
//判断 本地存储的 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;
//更新本地存储的
fs.writeFile('./wechat/access_token.json',JSON.stringify(accessTokenJson));
//将获取后的 access_token 返回
resolve(accessTokenJson.access_token);
}else{
//将错误返回
resolve(result);
}
});
}else{
//将本地存储的 access_token 返回
resolve(accessTokenJson.access_token);
}
});
}
在 app.js 中添加新的监听链接用于测试 我们获取的token
//用于请求获取 access_token
app.get('/getAccessToken',function(req,res){
wechatApp.getAccessToken().then(function(data){
res.send(data);
});
});
这样我们就大功告成了!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# nodejs
# access
# token
# Node.js
# access_token存储
# node实现基于token的身份验证
# 详解Node.js使用token进行认证的简单示例
# node脚手架搭建服务器实现token验证的方法
# node.js实现token身份验证的示例代码
# 如何在node.js中使用JsonWebToken模块进行token加密
# 的是
# 如图
# 将它
# 设置为
# 是在
# 也就
# 在这
# 并在
# 上一
# 工具包
# 给了
# 可供
# 文档
# 命名为
# 则更
# 都是
# 是一个
# 完成了
# 我是
# 帮助文档
相关文章:
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
建站之星后台管理如何实现高效配置?
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
如何在IIS管理器中快速创建并配置网站?
怀化网站制作公司,怀化新生儿上户网上办理流程?
网站制作软件免费下载安装,有哪些免费下载的软件网站?
如何在云主机上快速搭建多站点网站?
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
建站之星图片链接生成指南:自助建站与智能设计教程
*服务器网站为何频现安全漏洞?
教学论文网站制作软件有哪些,写论文用什么软件
?
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
如何在IIS中新建站点并配置端口与IP地址?
存储型VPS适合搭建中小型网站吗?
如何获取开源自助建站系统免费下载链接?
专业网站制作服务公司,有哪些网站可以免费发布招聘信息?
如何选择适配移动端的WAP自助建站平台?
利用JavaScript实现拖拽改变元素大小
如何通过VPS建站实现广告与增值服务盈利?
网站微信制作软件,如何制作微信链接?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
如何在IIS中新建站点并配置端口与物理路径?
建站之星×万网:智能建站系统+自助建站平台一键生成
建站之星安装步骤有哪些常见问题?
建站DNS解析失败?如何正确配置域名服务器?
如何彻底删除建站之星生成的Banner?
建站主机选购指南与交易推荐:核心配置解析
小型网站建站如何选择虚拟主机?
建站之星伪静态规则如何设置?
,怎么用自己头像做动态表情包?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
建站之星代理如何获取技术支持?
,想在网上投简历,哪几个网站比较好?
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
,网页ppt怎么弄成自己的ppt?
建站之星客服服务时间及联系方式如何?
宿州网站制作公司兴策,安徽省低保查询网站?
昆明高端网站制作公司,昆明公租房申请网上登录入口?
c# Task.ConfigureAwait(true) 在什么场景下是必须的
如何快速生成ASP一键建站模板并优化安全性?
如何在阿里云通过域名搭建网站?
c# 在ASP.NET Core中管理和取消后台任务
建站主机如何安装配置?新手必看操作指南
建站之星2.7模板:企业网站建设与h5定制设计专题
香港服务器部署网站为何提示未备案?
高端云建站费用究竟需要多少预算?
图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?
寿县云建站:智能SEO优化与多行业模板快速上线指南
网站制作难吗安全吗,做一个网站需要多久时间?
如何在宝塔面板中创建新站点?
*请认真填写需求信息,我们会在24小时内与您取得联系。