按照上一篇的说明,我们现在已经做好了和微信公众平台的对接工作,接下来我计划首先实现请求 access_token 的功能。
在开发过程中并非照搬教程内容,自己有所修改,主要的修改内容是在文件结构以及数据传输上。
原教程目录结构:
- material(素材文件夹)
- wechat(核心文件夹)
- access_token.json(用于请求 access_token )
- menu.json (自定义菜单目录文件)
- msg.js (涉及所有的被动回复种类)
- wechat.js (核心文件,其中包括调用自定义菜单、自定义回复等功能)
- app.js(入口文件)
- config.json(基础配置数据,其中包括 appid、appScrect 以及各种的请求地址)
我的目录结构:
- material(素材文件夹)
- app.js(入口文件)
- config.json(基础配置数据以及动态存储的 access_token 数据)
- request.js(封装的 post 和 get 方法)
- accessToken.js(用于请求 access_token )
- createMenu.js(用于生成自定义菜单)
- replyType.js(涉及所有的被动回复种类)
- reply.js(自定义回复)
个人认为,至少我的目录结构拆的更细化,至于好坏我不敢说。
封装 request 方法
其实 Node.js
开发微信公众号,无非就是按照文档去请求官方接口地址。所以在真正开发前,我们需要封装一套请求方法(自己尝试过利用 aoxis
,但是没有处理好对于 formData
的处理,只能未果),这里使用 request
模块实现请求。
var request = require('request') // 引入 request 组件
// 封装一个get请求方法
exports.get = (url) => {
return new Promise((resolve, reject) => {
request(url, (error, response, body) => {
if (!error && response.statusCode == 200) {
console.log('get request success')
resolve(body)
} else {
console.log('get request fail')
reject(error)
}
})
})
}
// 封装一个post请求方法
exports.post = (url, data) => {
// 这里需要判断 data 数据类型,因为自定义菜单和图片上传的数据格式有异,会导致报错
return new Promise((resolve, reject) => {
var form = {
url: url
}
if (typeof data == 'string') {
form.body = data // 如果数据格式为字符,则菜单数据通过 body 提交给接口
} else {
form.formData = data // 否则数据通过 formData 提交给接口(这里指的是上传图片接口)
}
request.post(form, (error, response, body) => {
if (!error && response.statusCode == 200) {
console.log('post request success')
resolve(body)
} else {
console.log('post request fail', error)
}
})
})
}
通过 Promise
我们可以在后期调用时更方便的处理请求结果。
这里需要特别注意一下,就是需要对 post 数据类型进行判断,因为按照目前的代码涉及 post 请求的地方有两个,分别是回复图片素材以及创建自定义菜单,自定义菜单的数据为 json 格式可以直接通过 body,而在回复素材则数据格式为 object 需要提交 formData。
这个区别曾经困扰了一段时间。
获取 access_token
了解一下 access_token
是什么?
- 它是公众号的全局唯一接口调用凭据;
- 有效期目前为2个小时,需定时刷新;
- 重复获取将导致上次获取的 access_token 失效;
- 它的请求方式为
get
- 它的请求地址是
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
我们可以使用 [微信公众平台测试账号] 提供的测试 appid
和 appsecret
将地址拼接成正确请求地址,之后之前前文封装好的 get 方法请求。
这里我是用了 fs 模块将请求到的 access_token 写入 config.json ,这样做我认为可以保证所有相关配置信息都在一起,方便调用。
var fs = require('fs') // 引入核心模块
var request = require('./request') // 引入封装好的 request 模块
module.exports = (config) => {
return new Promise((resolve, reject) => {
var currentTime = new Date().getTime() // 获取当前时间戳
// 拼接请求地址
var url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + config.appId + '&secret=' + config.appScrect
// 若 config 中 accesstoken 为空或者过期则需要重新请求
if (config.setAccessToken.accessToken === '' || config.setAccessToken.time < currentTime) {
request.get(url).then((response) => {
var result = JSON.parse(response)
// 修改 config 数据
config.setAccessToken.accessToken = result.access_token
config.setAccessToken.time = new Date().getTime() + (parseInt(result.expires_in) - 200) * 1000 // accesstoken 过期时间
// 将更新后的 config 写入文件
fs.writeFileSync
fs.writeFile('./config.json', JSON.stringify(config), (error) => {
if (error) {
console.log('update accessToken fail')
reject(error)
}
console.log('update accessToken success')
resolve(response.access_token) // 将 accesstoken 导出
})
}).catch((error) => {
// 请求失败
console.log('request accessToken fail', error)
reject(error)
})
} else {
// 若本地 access_token 未失效则直接导出
console.log('get accessToken success')
resolve(config.setAccessToken.accessToken)
}
})
}
到此为止我们前期工作都已告结,我会在后两篇日志中更新自定义菜单以及自定义回复,还望各位客观莅临。
文章已同步我的个人博客:《Node微信公众号开发 封装request和获取access_token》
相关文章:
资料参考:
- [微信公众号官方文档]
- [微信公众平台接口调试工具]
- [微信公众平台测试账号]
- [Node开发微信公众号(1)——微信公众号接入]
- [Node开发微信公众号(2)——微信回复]
- [Node开发微信公众号(3)——微信菜单]
- [Node开发微信公众号(4)——素材上传]
本文由博客一文多发平台 OpenWrite 发布!
来源:oschina
链接:https://my.oschina.net/sfatpaper/blog/3164788