如何高效率存储微信中的 access_token
一、access_token 的使用规则
在微信开发中,最常用到的就是 access_token
,access_token 的使用规则是:
每次请求的 access_token
可以在接下来的 2 个小时内都有效,直到你又获取了新的 access_token
。
每次跟微信服务器交互都需要用到,但它的请求限制是每天 2000 次,这就要求我们不能每次与微信服务器交互都要重新获取。
二、解决思路
解决思路就是将 access_token
存储起来,并标记它的失效时间。
至于如何存储它,就看你自己的喜好了,你可以将它存储到临时文件中,可以它将存储到数据库中,也可以将它存储到运行内存中。
我之前是将它存到数据库中的,但完全没有必要,其实将它存到运存中就可以。原因是:你后台是一直运行的,那么这个 access_token 的变量就会一直存在,直到下次你重启你的后台。
所以思路是这样的:
- 新建一个对象变量,记录
access_token
的内容和超时时间
// 临时 access token
let access_token = {
expires: new Date().getTime(),
access_token: ''
}
- 新建一个方法,用于获取
access_token
1. 先判断超时时间是否已到。
2. 如果已经到了超时时间,就重新获取access_token
并更新expires
过期时间。
3. 如果未到,说明已经存在access_token
直接取值用就可以了。
三、例子 nodejs
我有一个后台是 nodejs
写的,它的获取 access_token
的过程是这样的
// 临时 access token
let access_token = {
expires: new Date().getTime(),
access_token: ''
}
// 获取 ACCESS TOKEN
function getAccessToken(){
return new Promise((resolve, reject) => {
if (access_token.expires < new Date().getTime()){ // 已超时
axios({
method: 'get',
url: 'https://api.weixin.qq.com/cgi-bin/token',
params: {
grant_type: 'client_credential',
appid: configProject.wxPublicAppId,
secret: configProject.wxPublicSecret
},
})
.then(response => {
if (response.data.errcode){
reject(response.data)
} else {
resolve(response.data.access_token)
// 更新 access_token 数据
access_token = {
access_token : response.data.access_token,
expires: new Date().getTime() + response.data.expires_in * 1000
}
}
})
.catch(err => {
reject(err)
})
} else {
resolve(access_token.access_token)
}
})
}
四、很早很早之前写的,数据库形式的存储,不推荐哈。
以下是
2016-10-26 14:54:06
发布的内容
众所周知,在微信开发中,获取
access_token
的接口每天的调用次数是有限制的,2000
次应该是。
不过其实这些完全够用了,除非你不小心写了个循环,在1秒中内用完了。
每个access_token
的生效时间是2小时内
,2小时过后就需要重新申请一下。其实每天只需要申请12次就可以了。
不管你怎么申请,当前申请了access_token
,以前的就都不能用了。
所以解决办法就是:
在数据库中新建一个表token
盛放申请来的access_token
,字段有三个
access_token #存放access_token
expires #存放毫秒数
update_time #更新时间戳
##逻辑是这样的:(表中只有一条数据)
查询表中数据
如果有数据,用 时间戳+更新时间 跟 现在时间比较,计算是否已过期:
如果已过期,重新申请,并更新数据库中数据,并返回access_token
如果没有过期,直接返回查询出的access_token
如果没数据:
申请数据并,插入数据库,返回access_tooken
/*
---------------------
获取access_token:
查询数据库中是否有数据,
如果有 取出数据
如果已经过期,查询,更新记录
如果没过期,直接返回数据
如果没有 查询并添加数据,返回数据
---------------------
*/
function get_token(){
$access_url= 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.AppID.'&secret='.AppScret;
//AppID AppScret 已经定义为常量
//数据库参数
$host= "1.1.1.1";
$port = '3306';
$database = "wx";
$user = "mysql";
$passwd = "mysql";
$db = new mysqli($host,$user,$passwd,$database,$port);
$sql = "select * from token"; //查询wx表数据
$exist = $db->query($sql);
global $access_token;
if($exist->num_rows)
//如果存在数据
{
$row = $exist->fetch_array();
//如果数据已过期
if($row['expires']+$row['update_time']<time()){
$token = json_decode(file_get_contents($access_url));
$sql = "update token set access_token = '{$token->access_token}' where access_token = '{$row['access_token']}'";
$db->query($sql);
$access_token = $token->access_token; //返回更新的token
} else {
$access_token = $row['access_token']; //返回查询的token
}
}
//如果没有数据
else {
$token = json_decode(file_get_contents($access_url));
$sql = "insert into token values('{$token->access_token}',{$token->expires_in},".time().")";
$db->query($sql);
$access_token = $token->access_token; //返回新建的token
}
$db->close();
return $access_token; //返回access_token
}