写在最前
关于获取Access token这部分内容建议仔细阅读官方文档,本文章对于重点内容进行了摘录,有利于大家把握重点部分。
最后文章中会给出这一部分的程序设计思路及示例代码。
一、关于Access token的说明:
access_token是公众号的全局唯一接口调用凭据;
公众号调用接口时都必须带上access_token,开发者需要进行妥善保存;
access_token有效期为2个小时,重复获取将导致上次获取的access_token失效;
access_token的存储至少要保留512个字符空间。
二、access_token的使用及生成方式说明:
access_token应该由中控服务器统一获取和刷新,其他业务逻辑服务只需要读取;
access_token的有效期通过返回的expire_in来传达,有效期是7200秒(两个小时);
access_token刷新过程中,公众平台后台会保证在5分钟内,新老access_token都可用;
三、接口调用请求说明
接口请求方式:GET
接口请求地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
四、接口调用参数说明
五、返回值示例
/*
* 正确返回
* access_token 获取到的凭证
* expires_in 凭证有效时间,单位:秒
*/
{"access_token":"ACCESS_TOKEN","expires_in":7200}
/*
*错误返回
*/
{"errcode":40013,"errmsg":"invalid appid"}
六、程序设计思路
由于所有的接口调用都需要携带access_token,为了方便读取access_token,我们可以将其存储在本地(access_token.txt)文件中,每次调用接口前先尝试读取文件中保存的access_token。
本地没有文件:则直接发起接口请求,将请求结果及失效时间(expires_in)保存在新建的(access_token.txt)文件中并返回给需要使用的接口请求。
本地有文件:则读取access_token及失效时间(expires_in)并判断access_token是否已经失效,如果失效则发起接口请求,并更新(access_token.txt)文件中的请求结果及失效时间并返回给需要使用的接口请求的地方,否则直接将读取到的结果返回给需要使用的接口请求。
七、程序示例代码
在实现工具类之前,新建两个文件:
一个config.js配置文件,用来存储appid、appsecret等配置信息
一个apiurl.js文件统一存储微信后台的请求接口地址,防止微信服务器网络链路发生故障时,可迅速切换。
定义一个工具类(wechatTools)
// 请求access_token接口
const getAccessToken = () => {};
// 保存access_token
const saveAccessToken = () => {};
// 读取access_token.txt
const readAccessToken = () => {};
// 验证access_token的有效性
const validateExpiresIn = () => {};
// 封装获取access_token工具
const fetchAccessToken = () => {};
// 最后只需要导出fetchAccessToken就行
module.exports = { fetchAccessToken };
实现getAccessToken()函数
getAccessToken() {
return new Promise(async (resolve, reject) => {
const url = `${token}&appid=${appid}&secret=${appsecret}`;
try {
const response = await axios.get(url);
const expires_in = new Date().getTime() + (response.data.expires_in - 300) * 1000;
response.data.expires_in = expires_in;
resolve(response.data);
} catch (error) {
reject("获取access_token失败" + error);
}
});
}
实现saveAccessToken()函数
async saveAccessToken(data) {
return new Promise((resolve, reject) => {
writeFile(path.join(__dirname, `../text/access_token.txt`), JSON.stringify(data), error => {
if (error) {
reject("保存access_token失败" + error);
} else {
resolve(true);
}
});
});
}
实现readAccessToken()函数
readAccessToken() {
return new Promise((resolve, reject) => {
readFile(path.join(__dirname, `../text/access_token.txt`), {}, (error, data) => {
if (error) {
reject(`读取access_token.txt失败` + error);
} else {
let dataType = typeof data == "string";
let resData = dataType ? data : JSON.parse(data);
resolve(resData);
}
});
});
}
实现validateExpiresIn()函数
validateExpiresIn(data) {
if (!data && !data.expires_in) return false;
return data.expires_in > new Date().getTime();
}
实现fetchAccessToken()函数
fetchAccessToken() {
return (
this.readAccessToken()
// 本地有文件
.then(async res => {
if (this.validateExpiresIn(res)) {
return Promise.resolve(res);
} else {
const data = await this.getAccessToken();
await this.saveAccessToken(data);
return Promise.resolve(data);
}
})
// 本地没有文件
.catch(async error => {
const data = await this.getAccessToken();
await this.saveAccessToken(data);
return Promise.resolve(data);
})
// 最终返回的结果
.then(res => {
return Promise.resolve(res);
})
);
}
至此所有的代码已经实现,如果想要获取access_token只需要调用fetchAccessToken方法。
fetchAccessToken().then(res => {
console.log(res);
});