尚硅谷公众号开发
登录后可以看到右侧有下面的这些功能(功能有点多,自行登录查看)
点击右上角头像,选择账号信息。点击打开,可以看到如图:
我关注了一波我自己,确实自动回复了
开发者工具 -> 开发者文档 -> 开始开发 -> 接口测试号申请
具体流程参照:测试服务器的搭建
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
获取access_token每天最多调用2000次
官方文档
在测试服务器的搭建这一文章所用项目基础上继续开发。
在wechat目录下创建accessToken.js
来获取token
基本框架
//获取acess token
/**
* 特点:1、唯一 2、有效时间2小时,为防止过期提前5分钟请求 3、每天最多请求2000次
* get请求:请求地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
*/
/**
* 设计思路:
* 1、首次本地没有,发起请求获取acess token,并保存下来(本地文件)
* 2、第二次及以后:
* a、从本地读取文件,判断是否过期
* b、没有过期,直接使用
* c、过期了,重新请求,保存并覆盖之前的文件
*
* 整理思路:
* 读取本地文件(readAccessToken)
* a、没有文件,发送请求获取(getAccessToken) 保存(saveAccessToken)
* b、有文件,判断是否过期(isValidAccessToken)
*/
//只需要引入request-promise-native即可
const rq = require("request-promise-native");
//引入fs模块
const fs = require("fs");
//引入配置文件
const { appID, appsecret } = require("../config/index");
const { json } = require("express/lib/response");
class Wechat {
//构造器
constructor() {}
/**
* 获取accessToken
*/
getAccessToken() {
//请求地址,从config配置文件中获取
const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
//发送请求,需要使用request和request-promise-native两个库。
//用promise进行包装,确保返回数据
return new Promise((resolve, reject) => {
rq({ methods: "GET", url, json: true })
.then((res) => {
// console.log(res);
//设置access token过期时间,提前5分钟,乘1000是秒变毫秒
res.expires_in = Date.now() + (res.expires_in - 5 * 60) * 1000;
resolve(res);
})
.catch((err) => {
// console.log(err);
reject("getAccessToken执行失败:" + err);
});
});
}
/**
* 保存accessToken的方法
* @param {*} accessToken 要保存的数据
*/
saveAccessToken(accessToken) {
let data = JSON.stringify(accessToken);
return new Promise((resolve, reject) => {
fs.writeFile("./accessToken.txt", data, (err) => {
if (!err) {
console.log("accessToken保存成功");
resolve();
} else {
reject("accessToken保存失败:" + err);
}
});
});
}
/**
* 读取accessToken
*/
readAccessToken() {
return new Promise((resolve, reject) => {
fs.readFile("./accessToken.txt", (err, data) => {
if (!err) {
resolve(JSON.parse(data));
} else {
reject("读取accessToken失败:" + err);
}
});
});
}
/**
* 判断accessToken是否是有效的
* @param {*} accessToken :凭证
*/
isValidAccessToken(data) {
if (!data && !data.access_token && !data.expires_in) {
//无效
return false;
}
//判断是否在有效期内
return data.expires_in > Date.now();
}
}
//模拟测试
const w = new Wechat();
new Promise((resolve, reject) => {
w.readAccessToken()
.then((res) => {
//本地有文件,判断是否过期
if (w.isValidAccessToken(res)) {
//有效的
resolve(res);
} else {
//过期了重新请求
w.getAccessToken().then((res) => {
//保存
w.saveAccessToken(res).then(() => {
resolve(res);
});
});
}
})
.catch((err) => {
//本地没有文件,发起请求
w.getAccessToken().then((res) => {
//保存
w.saveAccessToken(res).then(() => {
resolve(res);
});
});
});
}).then((res) => {
console.log("token:", res);
});
获取accessToken
在模拟测试的基础上进行封装
//获取acess token
/**
* 特点:1、唯一 2、有效时间2小时,为防止过期提前5分钟请求 3、每天最多请求2000次
* get请求:请求地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
*/
/**
* 设计思路:
* 1、首次本地没有,发起请求获取acess token,并保存下来(本地文件)
* 2、第二次及以后:
* a、从本地读取文件,判断是否过期
* b、没有过期,直接使用
* c、过期了,重新请求,保存并覆盖之前的文件
*
* 整理思路:
* 读取本地文件(readAccessToken)
* a、没有文件,发送请求获取(getAccessToken) 保存(saveAccessToken)
* b、有文件,判断是否过期(isValidAccessToken)
*/
//只需要引入request-promise-native即可
const rq = require("request-promise-native");
//引入fs模块
const fs = require("fs");
//引入配置文件
const { appID, appsecret } = require("../config/index");
const { json } = require("express/lib/response");
class Wechat {
//构造器
constructor() {}
/**
* 获取accessToken
*/
getAccessToken() {
//请求地址,从config配置文件中获取
const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
//发送请求,需要使用request和request-promise-native两个库。
//用promise进行包装,确保返回数据
return new Promise((resolve, reject) => {
rq({ methods: "GET", url, json: true })
.then((res) => {
// console.log(res);
//设置access token过期时间,提前5分钟,乘1000是秒变毫秒
res.expires_in = Date.now() + (res.expires_in - 5 * 60) * 1000;
resolve(res);
})
.catch((err) => {
// console.log(err);
reject("getAccessToken执行失败:" + err);
});
});
}
/**
* 保存accessToken的方法
* @param {*} accessToken 要保存的数据
*/
saveAccessToken(accessToken) {
let data = JSON.stringify(accessToken);
return new Promise((resolve, reject) => {
fs.writeFile("./accessToken.txt", data, (err) => {
if (!err) {
console.log("accessToken保存成功");
resolve();
} else {
reject("accessToken保存失败:" + err);
}
});
});
}
/**
* 读取accessToken
*/
readAccessToken() {
return new Promise((resolve, reject) => {
fs.readFile("./accessToken.txt", (err, data) => {
if (!err) {
resolve(JSON.parse(data));
} else {
reject("读取accessToken失败:" + err);
}
});
});
}
/**
* 判断accessToken是否是有效的
* @param {*} accessToken :凭证
*/
isValidAccessToken(data) {
if (!data && !data.access_token && !data.expires_in) {
//无效
return false;
}
//判断是否在有效期内
return data.expires_in > Date.now();
}
/**
* 用来获取没有过期的accessToken
*/
fetchAccessToken() {
if(this.access_token && this.expires_in && this.isValidAccessToken(this)){
//说明之前保存过,并且是有效的
return Promise.resolve({
access_token:this.access_token,
expires_in:this.expires_in
})
}
//读取accessToken
return this.readAccessToken()
.then(async (res) => {
//本地有文件判断是否过期
if (this.isValidAccessToken(res)) {
resolve(res);
} else {
//重新请求
const res = await this.getAccessToken();
await this.saveAccessToken(res);
//将请求回来的token返回出去
return Promise.resolve(res);
// resolve(res);
}
})
.catch(async (err) => {
//本地没有文件
//重新请求
const res = await this.getAccessToken();
await this.saveAccessToken(res);
//将请求回来的token返回出去
return Promise.resolve(res);
// resolve(res);
})
.then((res) => {
//将accessToken挂在到this上
this.access_token = res.access_token;
this.expires_in = res.expires_in;
return Promise.resolve(res);
});
}
}
//模拟测试
const w = new Wechat();
new Promise((resolve, reject) => {
w.readAccessToken()
.then((res) => {
//本地有文件,判断是否过期
if (w.isValidAccessToken(res)) {
//有效的
resolve(res);
} else {
//过期了重新请求
w.getAccessToken().then((res) => {
//保存
w.saveAccessToken(res).then(() => {
resolve(res);
});
});
}
})
.catch((err) => {
//本地没有文件,发起请求
w.getAccessToken().then((res) => {
//保存
w.saveAccessToken(res).then(() => {
resolve(res);
});
});
});
}).then((res) => {
console.log("token:", res);
});