一、微信公众号获取 access_token
-
access_token
是微信调用接口全局唯一的凭据。它的特点是唯一的,有效期为2
小时,提前5
分钟请求,接口权限,每天2000
次。它的请求地址是https
请求方式:GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
,请求方式是GET
方式。 -
对于获取
access_token
,可以分析一下设计思路:
- 首次本地没有,发送请求获取
access_token
,保存下来,本地文件 - 第二次或以后,先去本地读取文件,判断它是否过期。过期了, 重新请求获取
access_token
,保存下来覆盖之前的文件,保证文件是唯一的。没有过期,直接使用。
- 对此,我们可以整理一下思路:
- 读取本地文件 (
readAccessToken
) - 本地有文件,判断它是否过期 (
isValidAccessToken
)。过期了, 重新请求获取access_token
(getAccessToken
),保存下来覆盖之前的文件,保证文件是唯一的, (saveAccessToken
)。没有过期,直接使用。 - 本地没有文件,发送请求获取
access_token
(getAccessToken
),保存下来 (saveAccessToken
),本地文件,直接使用。
- 引入
config.js
文件,里面包括token
、appID
和appsecret
。引入request-promise-native
,通过npm i request-promise-native
命令进行下载。引入fs
文件模块,代码如下所示:
const { appID, appsecret } = require('../config')
const rp = require('request-promise-native')
const { writeFile, readFile} = require('fs')
- 定义一个类
WeChat
,获取access_token
,在里面可以定义一些方法。定义getAccessToken
方法,用来获取access_token
。定义请求的地址,发送请求,得到的res
结果包括两个值,access_token
微信调用接口全局唯一的凭据 和expires_in
过期时间。设置access_token
的过期时间,将promise
对象状态修改为成功的状态,代码如下所示:
// 用来获取 access_token
getAccessToken () {
const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`
return new Promise((resolve, reject) => {
rp({method: 'GET', url, json: true}).then(res => {
console.log(res)
res.expires_in = Date.now() + (res.expires_in - 300) * 1000
resolve(res)
}).catch(err => {
console.log(err)
reject('getAccessToken方法出了问题:'+ err)
})
})
}
- 在这个类
WeChat
中,定义saveAccessToken
方法,用来保存access_token
,access_token
是保存的凭据。将对象转化json
字符串,将access_token
保存为一个文件,代码如下所示:
// 用来保存 access_token, access_token 是保存的凭据
saveAccessToken (accessToken) {
accessToken = JSON.stringify(accessToken)
return new Promise((resolve, reject) => {
writeFile('./accessToken.txt', accessToken, err => {
if (!err) {
console.log('文件保存成功')
resolve()
} else {
reject('saveAccessToken方法出了问题:' + err)
}
})
})
}
- 在这个类
WeChat
中,定义readAccessToken
方法,用来读取access_token
。读取本地文件中的access_token
,通过readFile
方法,将json
字符串转化为js
对象,代码如下所示:
// 用来读取 access_token
readAccessToken () {
return new Promise((resolve, reject) => {
readFile('./accessToken.txt', (err, data) => {
if (!err) {
console.log('文件读取成功')
data = JSON.parse(data)
resolve(data)
} else {
reject('readAccessToken方法出了问题:' + err)
}
})
})
}
- 在这个类
WeChat
中,定义isValidAccessToken
方法,用来检测access_token
是否是有效的,检测传入的参数是否是有效的。如果没有data
,没有access_token
以及没有expires_in
,说明传入的access_token
是无效的。 过期时间大于当前时间,说明没有过期,返回true
,代码如下所示:
// 用来检测 access_token 是否是有效的
isValidAccessToken (accessToken) {
if (!data && !data.access_token && data.expires_in) {
return false
}
return data.expires_in > Data.now()
}
- 在这个类
WeChat
中,定义fetchAccessToken
方法,用来获取没有过期的access_token
,传递参数就是Promise
对象。先判断有没有access_token
、expires_in
以及
是否有效。如果有效,说明之前保存过access_token
,并且没有过期,可以直接使用。读取本地有文件,判断它是否过期。如果有效的,直接返回access_token
。如果无效的,发送请求获取access_token
,保存下来 ,本地文件,直接使用,将请求回来的access_token
返回出去。如果本地无文件,发送请求获取access_token
,保存下来 ,本地文件,直接使用,将请求回来的access_token
返回出去。最后,将access_token
和expires_in
挂载到this
上,返回res
包装了一层promise
对象,此对象为成功后的状态,是this.readAccessToken
最终的返回值,代码如下所示:
// 用来获取没有过期的 access_token,
fetchAccessToken () {
if (this.access_token && this.expires_in && this.isValidAccessToken(res)) {
return Promise.resolve({
access_token: this.access_token,
expires_in: this.expires_in
})
}
return this.readAccessToken().then(async res => {
if (this.isValidAccessToken(res)) {
return Promise.resolve(res)
} else {
const res = await this.getAccessToken()
await this.saveAccessToken(res)
return Promise.resolve(res)
}
}).catch(async err => {
const res = await this.getAccessToken()
await this.saveAccessToken(res)
return Promise.resolve(res)
}).then(res => {
this.access_token = res.access_token
this.expires_in = res.expires_in
return Promise.resolve(res)
})
}