一、写在前面的话

上一篇文章中,我们使用 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);
  });  
});

这样我们就大功告成了!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持Devmax。

详解Node.js access_token的获取、存储及更新的更多相关文章

  1. 如何使用iOS SDK保存LinkedIn访问令牌?

    我在我的iOS应用程序中使用LinkedIn.我想保存访问令牌以供将来使用.令牌属于非属性类型,无法直接保存在NSUserDefaults中.我尝试使用NSKeyedArchiver,但我得到了输出:令牌中的文本即将到来,但值将为空.代码段1:我也尝试像这样保存,但结果是一样的:代码段2:我的编码或访问令牌有什么问题需要一些特殊技术来保存吗?请建议.解决方法这就是我拯救的方式.它对我有用.希望它有所帮助以这种方式使用保存的responseBody我希望这次我很清楚

  2. IOS Facebook身份验证使用node.js passport-facebook-token

    我正在尝试使用来自IOS应用程序的passport-facebook-token对node.jsapi进行身份验证.我有用户名和密码验证设置,并通过护照和护照-facebook-token设置正常工作.我只是无法弄清楚将访问令牌发送到API所需的HTTP请求语法.任何帮助都将受到大力赞赏.谢谢.解决方法确定设法从passport-facebook-token的策略文件中找出答案这个需要:http://URL?access_token=[访问令牌]从IOS我只是用以下方法测试:希望这有助于其他人.

  3. 解析条纹iOS main.js

    我真的很难让ParseStripe在我的项目中工作.此时,我想要最简单的工作版本,允许我向用户收费.我找到答案的最接近的事情如下:SimplestExampleI’veFound当我使用上面链接中的更正代码时,我的秘密得到以下错误:请帮助=**(这太令人沮丧了.————-更新—————-其他一些帖子也有类似的错误,看起来最新版本的ParseCloud代码应该归咎于:1.6.0.在控制台视图中使用以

  4. 尝试更改Bool属性时,ios – EXC_BAD_ACCESS错误

    我正在尝试更改Bool属性并且收到一个EXC_BAD_ACCESS错误.我正在使用XCode6和Swift.note属性保存不错,但已完成的属性会抛出EXC_BAD_ACCESS错误改变属性程序解决方法有同样的问题,解决方案确实是在@NSManaged属性中使用NSNumber.此外,您可以定义一个计算的Bool属性,以便您可以使用业务逻辑中的标量布尔值,而不能使用NSNumber.

  5. 基于Swift语言开发微信、QQ和微博的SSO授权登录代码分析

    一,总体架构1,引入第三方库除了必须引入对应的登录SDK外,额外引入了SDWebImage,SVProgressHUD,看名字大家都明白吧,引入登录SDK请各自看官方的开发文档,需要加入什么系统库文件,需要配置OtherLinkerFlags等,请参考各自官方文档即可;2,配置连接桥文件因为创建的工程是基于Swift语言,目前官方SDK和其它三方库都是用OC写的,所以为了在swift中调用oc代码

  6. 基于Swift语言开发微信、QQ跟微博的SSO授权登录代码分析

    转自:http://www.myexception.cn/swift/1991018.html前言Swift语言,怎么说呢,有一种先接受后排斥,又欢迎的感觉,纵观国外大牛开源框架或项目演示,Swift几乎占据了多半,而国内虽然出现很多相关技术介绍和教程,但是在真正项目开发中使用的占据很少部分,原因一是目前熟练它的开发者并不多,二是版本不太稳定,还需要更成熟可靠的版本支持,但总之未来还是很有前景的,

  7. Swift3 单例模式

    常见的有这么几种方法第一种最简单也是最常用的,这里的所有单例init方法一定要定义成private的,不然外部依然可以使用init方法初始化变量。final关键字的作用是这个类或方法不希望被继承和重写第二种第二种完全是OC风格的单例,但是由于Swift3中废弃了原来的dispatch_once_t,所以需要先给dispatchQueue添加一个extension,实现原先的dispatch_once_t效果第三种第四种在方法内定义静态变量

  8. 微信三方登录相关(Swift)

    微信登录条件1.微信开放平台注册并认证成功2.相关应用的微信的APPID和secret3.遵循微信代理WXApiDelegate使用处编写相关登录代码WXApi.registerappletreq=SendAuthReq.init()req.scope="snsapi_userinfo"req.state="wulianwang"WXApi.send在回调方法中处理相关业务funconResp(_resp:BaseResp!,options:.mutableContainers)/**正确时返回的JSON

  9. 如何替换位置代码使Swift 3兼容?

    我有以下类,它有方法getNextToken迭代数组项:但我有一个来自编译器的警告消息,将在Swift3中弃用我应该如何重写我的代码让方法在当前位置返回数组项并在此之后增加位置?添加一个行位置=1的标准建议不适合这里,因为我在评估令牌时正在退出范围[位置]延迟可用于增加位置变量在计算返回值之后:

  10. 如何使用Swift检查iOS设备是否被锁定/解锁?

    如何使用Swift检测锁定/解锁的iOS设备(如Android中的SCRENON/SCREENOFF)我使用以下来创建相同的想法.您需要使用桥接器将目标c代码用于swift.HereistheLinkforcreatethebridgebetweentheObjectivectoSwift.完成后,您可以将以下.h文件添加到您的项目–桥接–标题中.文件添加yourcontroller.h然后将No

随机推荐

  1. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  2. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  3. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  4. nodejs模块学习之connect解析

    这篇文章主要介绍了nodejs模块学习之connect解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. nodejs npm package.json中文文档

    这篇文章主要介绍了nodejs npm package.json中文文档,本文档中描述的很多行为都受npm-config(7)的影响,需要的朋友可以参考下

  6. 详解koa2学习中使用 async 、await、promise解决异步的问题

    这篇文章主要介绍了详解koa2学习中使用 async 、await、promise解决异步的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. Node.js编写爬虫的基本思路及抓取百度图片的实例分享

    这篇文章主要介绍了Node.js编写爬虫的基本思路及抓取百度图片的实例分享,其中作者提到了需要特别注意GBK转码的转码问题,需要的朋友可以参考下

  8. CentOS 8.2服务器上安装最新版Node.js的方法

    这篇文章主要介绍了CentOS 8.2服务器上安装最新版Node.js的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  10. node下使用UglifyJS压缩合并JS文件的方法

    下面小编就为大家分享一篇node下使用UglifyJS压缩合并JS文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

返回
顶部