微信公众平台 OAuth Access_Token获得
微信官网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 == 5) { // 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); Thread.currentThread().interrupt(); } 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已经到达了最大重试次数。