access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
接口调用请求说明
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数说明
参数 | 是否必须 | 是否必须 |
---|---|---|
grant_type | 是 | 获取access_token填写client_credential |
appid | 是 | 第三方用户唯一凭证 |
secret | 是 | 第三方用户唯一凭证密钥,即appsecret |
返回说明
正常情况下,微信会返回下述JSON数据包给公众号:
{“access_token”:“ACCESS_TOKEN”,“expires_in”:7200}
参数 | 说明 |
---|---|
access_token | 获取到的凭证 |
expires_in | 凭证有效时间,单位:秒 |
错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
{“errcode”:40013,“errmsg”:“invalid appid”}
我们先来看获取access_token的代码:
Weixin weixin = new Weixin();
String access_token = weixin.getToken().getAccess_token();
我相信大家获取access_token大部分原因还是因为多个项目需要用到。
虽然可以获取了,但是我们不推荐大家去获取,更不建议大家这么去保存或使用。
理由如下:
1.大部分接口Weixin4j已经提供,无须你再次封装调用。
2.access_token在你获取的时候可能已经快要过期
那我们改如何去保存access_token呢?
其实,我们已经考虑到大家会有好几个项目公用同一个access_token的情况了。
现在的你们是不是这样处理的呢?
由一个服务获取access_token,把它存到一个公共能读取的地方比如:redis、数据库。或者有一个专门的服务来提供access_token呢?
如果你们已经这么做了,那我恭喜你,思路还是很正确的!
大家应该或多或少的遇到过下面这几种场景吧:
场景一:
项目已经在运行了,可是由于之前的微信开发是自己按照官方文档自己封装了部分调用接口,现在需要调用新的接口,还需要去新封装,太累,而且还需要测试,接口不全,怎么办?
场景二
原来公司已有一个项目把公众号已经占用了,我们新开发的项目也要使用这个公众号去调用,怎么公用?
场景三
有一个临时功能,这个功能需要调用微信1-2个接口,access_token已经有了,但是还得自己封装接口,太麻烦!
这在我们Weixin4j这,都不是问题
我们Weixin4j为大家提供了一个接口,可以方便大家去和自身的access_token进行对接。
ITokenLoader:一个专门解决access_token获取和保存的接口
我们看看接口源码
package org.weixin4j.loader;
import org.weixin4j.model.base.Token;
/**
* AccessToken加载接口
*
* @author yangqisheng
* @since 0.1.0
*/
public interface ITokenLoader {
/**
* 获取access_token
*
* @return 包含access_token数据的对象
*/
public Token get();
/**
* 刷新access_token
*
* @param accessToken 包含access_token数据的对象
*/
public void refresh(Token accessToken);
}
没错,这个接口是我们在weixin4j-0.1.0版本上加的。
get()方法为我们提供了获取操作
这也是我们weixin.token()的底层数据来源。
我们看一下weixin.getToken()代码
/**
* AccessToken加载器
*/
protected ITokenLoader tokenLoader = new DefaultTokenLoader();
...省略部分代码
/**
* 获取Token对象
*
* @return Token对象
* @throws org.weixin4j.WeixinException 微信操作异常
* @since 0.1.0
*/
public Token getToken() throws WeixinException {
Token token = tokenLoader.get();
if (token == null) {
synchronized (LOCK) {
token = tokenLoader.get();
if (token == null) {
token = base().token();
tokenLoader.refresh(token);
}
}
}
return token;
}
大家已经看到了,对,我们就是用ITokenLoader的get()方法进行获取access_token的。
也就是说大家只需要实现ITokenLoader接口,就可以在实现类里去获取其他位置存放的access_token了
当然,如果我们就是自己用,没有其他地方的access_token可获取,怎么办?
这时我们的refresh方法登场了
refresh()方法就是我们刷新access_token的地方,weixin4j内部实现了一套access_token过期的算法,如果access_token过期,则会重新向微信服务获取一个新的access_token,然后调用refresh()方法,交给我们实现类去保存。
当然我们Weixin4j也内置了一个默认的DefaultTokenLoader,是基于内存保存access_token。
我们来看一下默认的TokenLoader是怎么实现的:
package org.weixin4j.loader;
import org.weixin4j.model.base.Token;
import org.apache.commons.lang.StringUtils;
/**
* 内存式AccessToken存储器
*
* 单项目时使用(生产环境不推荐)
*
* @author yangqisheng
* @since 0.1.0
*/
public class DefaultTokenLoader implements ITokenLoader {
/**
* AccessToken对象
*/
private Token token = null;
@Override
public Token get() {
return (token == null
|| StringUtils.isEmpty(token.getAccess_token())
|| token.isExprexpired()) ? null : token;
}
@Override
public void refresh(Token token) {
if (null == token || StringUtils.isEmpty(token.getAccess_token())) {
throw new IllegalStateException("access_token is null or empty");
}
if (token.getCreate_time() <= 0) {
throw new IllegalStateException("createtime can not be zero");
}
if (token.isExprexpired()) {
throw new IllegalStateException("access_token is exprexpired");
}
this.token = token;
}
}
其实很简单,就是放在内存变量里而已。
关于access_token的过期算法,我们可以看一下Token对象,我们提供了一个方法isExprexpired()来验证access_token是否过期。
/**
* 判断用户凭证是否过期
*
* @return 过期返回 true,否则返回false
*/
public boolean isExprexpired() {
Date now = new Date();
long nowLong = now.getTime();
return nowLong >= exprexpired_time;
}
看源码就知道了,我们就是拿access_token的过期时间与当前时间进行对比。
还没完,access_token的过期时间怎么设的呢?
/**
* 设置 凭证有效时间,单位:秒
*
*
* 为了与微信服务器保存同步,误差设置为提前1分钟,即:将创建时间提早1分钟
*
*
* @param expires_in 凭证有效时间,单位:秒
* @param create_time 凭证创建时间
*/
public void setExpires_in(int expires_in, long create_time) {
this.expires_in = expires_in;
//获取当前时间毫秒数
this.create_time = create_time - 60000;
//设置下次过期时间 = 当前时间 + (凭证有效时间(秒) * 1000)
this.exprexpired_time = this.create_time + (expires_in * 1000);
}
expires_in 剩余过期时间,微信默认是2小时,也就是7200秒
create_time 创建access_token的时间,这也是过期的重要因素
有了这2个值,我们就可以计算出access_token的过期时间了,我们在这里还做了一个容错,提前1分钟过期,防止微信服务时间与本地服务器时间不一致导致出错。
看到这里大家对Weixin4j的获取access_token机制和如何使用了解了吗?
如果还有不会不懂的地方,欢迎加我们的QQ群:943339644
或者添加作者微信,备注:学习微信开发。
拉你入群,与众多开发者共同学习,一起进步。