微信官网wiki:http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token
以下摘自官网:
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效(self:微信端应该是运用了Memcached或者Redis处理access_token的timeout)。由于获取access_token的api调用次数非常有限,建议开发者全局存储与更新access_token,频繁刷新access_token会导致api调用受限,影响自身业务。
公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在开发模式中获得(需要已经成为开发者,且帐号没有异常状态)。注意调用所有微信接口时均需使用https协议。
以下是单次获得access_token的代码实现。注意,是单次获得,勿频繁调用,获得全局access_token请使用封装的AccessTokenScheduled#accessTokenScheduled(),该类的设计思想参考http://blog.csdn.net/will_awoke/article/details/27084907 ,这里就不贴了,请看官们自己动手。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.ruhuicloud.constant.SystemConfig;
import com.ruhuicloud.https.HttpsAccessUtil;
import com.ruhuicloud.mail.MailUtil;
/**
* 获取微信公众号的全局唯一票据access_token工具类
*
* @author will_awoke
* @version 2014-6-25
* @see AccessTokenUtil
* @since
*/
public class AccessTokenUtil
{
/**
* 日志
*/
private static final Logger log = Logger.getLogger(AccessTokenUtil.class);
/**
* 第三方用户唯一凭证
*/
private static final String appid = SystemConfig.wechatAppid;
/**
* 第三方用户唯一凭证密钥,即appsecret
*/
private static final String appsecret = SystemConfig.wechatAppsecret;
/**
* 获取access_token(单次请求)
* 注:请勿频繁调用该方法,
* 获得全局access_token务必使用AccessTokenScheduled#accessTokenScheduled()
*
* @return 获取成功则返回access_token,不成功则返回""
* @see
*/
public static String accessToken()
{
String result = "";
//增加闭锁,确保at获得成功,如果获得失败则retry 5次,达到最大重试次数仍无法获得at,则邮件告警。
final CountDownLatch gate = new CountDownLatch(1);
//reties counter
final AtomicInteger retries = new AtomicInteger(0);
//微信请求httpsURL
final String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
+ appid + "&secret=" + appsecret;
//global warnings
StringBuilder warnings = new StringBuilder("");
//如果获得失败则retry 5次,达到最大重试次数仍无法获得at,则邮件告警
while (true)
{
int currentRetries = retries.incrementAndGet();
// retry times
if (currentRetries == 6)
{
// need to countDown, otherwise, will be blocking
gate.countDown();
break;
}
//GET请求微信AT获得服务
String httpsRsp = HttpsAccessUtil.httpsRequest(requestUrl, "GET", "");
String warning = "!! Call remote AccessTokenCGI !! Retries: " + currentRetries
+ ", return rsp is " + httpsRsp;
log.info(warning);
warnings.append(warning).append("\n");//append to warnings
//获取成功则返回access_token
AccessTokenBean rsp = JSON.parseObject(httpsRsp, AccessTokenBean.class);
if (rsp != null && !StringUtils.isBlank(rsp.getAccess_token()))
{
result = rsp.getAccess_token();
gate.countDown();//countDown
break;
}
}
//warnings , send warnings to CPIS mail
if (StringUtils.equals("", result))
{
MailUtil.sendMailDefault("xx@qq.com", "微信公众平台告警", "获取Access_Token失败!\n" + warnings);
log.warn("!! Warning !! access_token getting from remote is blank... ");
}
try
{
//阻塞等待
gate.await();
}
catch (InterruptedException e)
{
MailUtil.sendMailDefault("xx@qq.com", "微信公众平台告警", "获取Access_Token失败!\n" + warnings);
}
return result;
}
/**
* 微信access_token接口 rsp解析类
*
* 正常情况下,微信会返回下述JSON数据包给公众号:
* {"access_token":"ACCESS_TOKEN","expires_in":7200}
* 错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
* {"errcode":40013,"errmsg":"invalid appid"}
* @author will_awoke
* @version 2014-6-26
* @see AccessTokenBean
* @since
*/
public static class AccessTokenBean
{
private String access_token;
private Long expires_in;
public AccessTokenBean()
{}
@Override
public String toString()
{
return JSON.toJSONString(this);
}
public String getAccess_token()
{
return access_token;
}
public void setAccess_token(String access_token)
{
this.access_token = access_token;
}
public Long getExpires_in()
{
return expires_in;
}
public void setExpires_in(Long expires_in)
{
this.expires_in = expires_in;
}
}
/**
* for test
* @param args
* @see
*/
public static void main(String[] args)
{
log.info("result = " + accessToken());
}
}
上述代码有两点需要提一下,第一点是retry 5次,因为微信平台存在未知原因,有的时候莫名会无法获得AT,需要重试,这里retry 5次,如果依旧无法获得,则邮件告警运维人员;第二点,用到了CountDownLatch闭锁,阻塞return直到获得正确的AT或者retey已经到达了最大重试次数。
update 有朋友发私信求MailUtil的代码,我用的是Apache commons 家族的 mail 组件:
mvn地址:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.3.3</version>
</dependency>