微信获取access_token的有效期是7200秒,该接口每天每个公众号调用次数只有2000次,需要缓存起来,失效了再更新。
思路:将access_token保存在redis中。
1:获取时检查redis中是否存在,不存在则向微信请求获取到access_token保存到redis
2:redis中存在时,我这里加了个access_token有效性校验,由于微信并没有提供access_token有效性校验的接 口,这里调用了获取微信服务器ip地址的接口,该接口并没有次数限制。https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN。正常情况下,该接口返回json数据包格式为:
{"ip_list":["101.226.62.77","101.226.62.78"]}
否则返回error,token不正确信息。
3:如果有效,返回access_token;否则重新获取向微信获取,更新到redis并设置过期时间后再返回。
注:这里获取access_token的方法加了synchronized 来同步,在多线程下也是ok的。
code:去掉了一些日志类的代码和http请求工具类,需要的话稍微改造下就可以直接用了。
public synchronized ConResult uniteGetAccessToken() {
String logPath = this.logFilePath + File.separator + "accessToken操作记录.txt";
ConResult conResult = new ConResult();
String acstoken = (String) this.redisTemplate.opsForValue().get(Constant.PUB_ACTOKEN_KEY);
if (acstoken == null) {
acstoken = getAccessTokenFromWechat(Constant.PUBAPPID, Constant.PUBSECRET);//向微信请求access_token
this.redisTemplate.opsForValue().set(Constant.PUB_ACTOKEN_KEY, acstoken, 120L, TimeUnit.MINUTES);
conResult.getMap().put("msg", "刷新" + acstoken);
} else {
String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=" + acstoken;
if (isEffective(url, conResult)) {//判断redis中的token是否有效
conResult.getMap().put("msg", "未刷新" + acstoken);
} else {
acstoken = getAccessTokenFromWechat(Constant.PUBAPPID, Constant.PUBSECRET);
this.redisTemplate.opsForValue().set(Constant.PUB_ACTOKEN_KEY, acstoken, 120L, TimeUnit.MINUTES);
conResult.getMap().put("msg", "刷新" + acstoken);
}
}
return conResult;
}
Boolean isEffective(String url, ConResult conResult) {
for (int i = 1; i <= 5; i++) {
String result = HttpRequestUtils.getRequest(url);
if (result.contains("ip_list")) {
conResult.getMap().put("times", Integer.valueOf(i));
return Boolean.valueOf(true);
}
}
return Boolean.valueOf(false);
}
//从服务器获取AccessToken
public static String getAccessTokenFromWechat(String appId, String appSecret) {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
"&appid=" + appId +
"&secret=" + appSecret;
String result = HttpRequestUtils.getRequest(url);
String accessToken = null;
if (result.contains("errcode")) {
if(accessTokenWarn){//失败时给管理员发送邮件
EmailUtils.sendTextEmail("12345678@qq.com","从微信服务器获取acToken失败:"+result);
accessTokenWarn = false;
}
}else {
JSONObject json = JSON.parseObject(result);
accessToken = json.getString("access_token");
}
return accessToken;
}