access_token简介
为了使第三方开发者能够为用户提供更多有价值的个性化服务,微信公众台开放了许多接口,包括自定义菜单接口、客服接口、获取用户信息接口、用户分组接口、群发接口等,开发者调用这些接口是,都需要传入一个相同的参数access_token,他是公众号的全局唯一票据,发是接口的访问凭证。
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。
access_token的存储至少要保留512个字符空间。
access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的 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都是有效的。
我们先看看官方的说明:
接口调用请求说明
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”}
spring boot 编写java代码
1、封装基本类
public class AccessToken
{
private String accessToken;
// 凭证有效期,单位:秒
private int expiresIn;
public String getAccessToken()
{
return accessToken;
}
public void setAccessToken(String accessToken)
{
this.accessToken = accessToken;
}
public int getExpiresIn()
{
return expiresIn;
}
public void setExpiresIn(int expiresIn)
{
this.expiresIn = expiresIn;
}
}
public class MyX509TrustManager implements X509TrustManager {
// 检查客户端证书
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 检查服务器端证书
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509证书数组
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
2、常量类
@Component
@ConfigurationProperties(prefix = "basicsyscodeservice")
public class BasicSysCodeService
{
/**
* 获取access_token请求的url
*/
private static String accessTokenUrl;
private static String appId;
private static String secret;
public static String getAccessTokenUrl()
{
return accessTokenUrl;
}
@Value("${basicsyscodeservice.accessTokenUrl}")
public void setAccessTokenUrl(String accessTokenUrl)
{
this.accessTokenUrl = accessTokenUrl;
}
public static String getAppId()
{
return appId;
}
@Value("${basicsyscodeservice.appId}")
public void setAppId(String appId)
{
this.appId = appId;
}
public static String getSecret()
{
return secret;
}
@Value("${basicsyscodeservice.secret}")
public void setSecret(String secret)
{
this.secret = secret;
}
}
4、配置文件
application-config.yml
basicsyscodeservice:
accessTokenUrl: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
appId: wxb30f7903610be618
secret: a6ccb1547321187572f2e8c66b8140a7
application.yml
server:
port: 80
servlet:
context-path: /weixin
spring:
profiles:
include: config
4、定时获取access_token的公共方法
@Component
public class CommonUtil
{
private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
public static AccessToken accessToken = null;
/**
* 获取接口访问凭证
*
* @return
*/
@Scheduled(fixedRate = 1000*7200)
private static AccessToken getAccessToken()
{
String requestUrl = String.format(BasicSysCodeService.getAccessTokenUrl(),
BasicSysCodeService.getAppId(),
BasicSysCodeService.getSecret());
// 发起GET请求获取凭证
JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
if (null != jsonObject)
{
try
{
accessToken = new AccessToken();
accessToken.setAccessToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
}
catch (Exception e)
{
accessToken = null;
// 获取token失败
log.error(e.getMessage());
}
}
return accessToken;
}
/**
* 发送https请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
private static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr)
{
JSONObject jsonObject = null;
try
{
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 当outputStr不为null时向输出流写数据
if (null != outputStr)
{
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null)
{
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
}
catch (ConnectException ce)
{
log.error("连接超时:{}", ce);
}
catch (Exception e)
{
log.error("https请求异常:{}", e);
}
return jsonObject;
}
}
5、SpringbootApplication
@SpringBootApplication
@EnableScheduling
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
每个两个小时CommonUtil.accessToken中的access_token将会刷新一次