Access Token是做什么的
我们在访问很多大公司的开放 api 的时候,都会发现这些 api 要求传递一个 access token 参数。这个参数是什么呢?需要去哪里获取这个 access token 呢?
access token 是在 Oauth2.0 协议中,客户端访问资源服务器时需要带上的令牌(其实就是一段全局唯一的随机字符串)。拥有这个令牌代表着得到用户的授权。令牌里面包含哪些信息呢?
答案是:
哪个用户在什么时候授权给哪个app去做什么事情
当然这些信息是不能直接从 access token 看出来的,而是存在平台方的数据库中,平台可以用 access token 作为 key 去查询出这些信息,然后验证调用方是否有权限。
所以,在调用这些 api 之前,需要先获取到 access token。
access_token简介
为了使第三方开发者能够为用户提供更多更有价值的个性化服务,微信公众平台 开放了许多接口,包括自定义菜单接口、客服接口、获取用户信息接口、用户分组接口、群发接口等,
开发者在调用这些接口时,都需要传入一个相同的参数 access_token,它是公众账号的全局唯一票据,它是接口访问凭证。
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。
access_token的存储至少要保留512个字符空间。
access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的 access_token失效。
如果第三方不使用中控服务器,而是选择各个业务逻辑点各自去刷新access_token,那么就可能会产生冲突,导致服务不稳定。
公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台官网-开发者中心页中获得(需要已经成为开发者,且帐号没有异常状态)。注意调用所有微信接口时均需使用https协议。
access_token的有效期是7200秒(两小时),在有效期内,可以一直使用,只有当access_token过期时,才需要再次调用接口 获取access_token。在理想情况下,一个7x24小时运行的系统,每天只需要获取12次access_token,即每2小时获取一次。如果在 有效期内,再次获取access_token,那么上一次获取的access_token将失效。
目前,获取access_token接口的调用频率限制为2000次/天,如果每次发送客服消息、获取用户信息、群发消息之前都要先调用获取 access_token接口得到接口访问凭证,这显然是不合理的,一方面会更耗时(多了一次接口调用操作),另一方面2000次/天的调用限制恐怕也不 够用。因此,在实际应用中,我们需要将获取到的access_token存储起来,然后定期调用access_token接口更新它,以保证随时取出的 access_token都是有效的。
获取access_token
微信官方文档 https://developers.weixin.qq.com/doc/官方文档
采用hutool工具包发http请求
依赖:
<!--Hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.16</version>
</dependency>
yaml文件的配置
#微信支付
wechat-payment:
#微信小程序设置
wechat-mini-app:
#微信小程序APP ID
app-id: "xxx"
#微信小程序APP SECRET
app-secret: "xxx"
获取access_token的代码实现:
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.sdyspx.stateartexam.manage.pojo.CommonResult;
import org.sdyspx.stateartexam.manage.pojo.WechatMessageData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.Map;
@Slf4j
public class AccessTokenUtils{
/**
* 微信支付小程序APP ID
*/
@Value("${wechat-payment.wechat-mini-app.app-id}")
String WECHAT_MINI_APP_APP_ID;
/**
* 微信支付小程序APP SECRET
*/
@Value("${wechat-payment.wechat-mini-app.app-secret}")
String WECHAT_MINI_APP_APP_SECRET;
/**
* 微信AccessToken过期时间
*/
Integer WECHAT_ACCESS_TOKEN_EXPIRE_SECOND = 7000;
/**
* 微信AccessToken
*/
String wechatAccessToken;
/**
* 微信AccessToken生成时间
*/
Date wechatAccessTokenRequestTime = new Date();
/**
* @return 获取AccessToken
*/
private String getAccessToken() {
//初始化情况
Date currentData = new Date();
//比较时间大小
long betweenSeconds = DateUtil.between(wechatAccessTokenRequestTime, currentData, DateUnit.SECOND);
if (wechatAccessToken == null || betweenSeconds > WECHAT_ACCESS_TOKEN_EXPIRE_SECOND) {
//更新AccessToken
updateAccessToken();
//更新获取时间
wechatAccessTokenRequestTime = new Date();
}
return wechatAccessToken;
}
/**
* 更新AccessToken
*/
private void updateAccessToken() {
JSONObject jsonObject = new JSONObject();
try {
String result = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token" +
"?grant_type=client_credential" +
"&appid=" + WECHAT_MINI_APP_APP_ID
+ "&secret=" + WECHAT_MINI_APP_APP_SECRET);
jsonObject = JSON.parseObject(result);
wechatAccessToken = jsonObject.getString("access_token");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}