微信公众平台 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());
    }
}


这里省略了HttpsAccessUtilMailUtil这两个工具类的代码,因为这两个代码网上随处可见。 :)

上述代码有两点需要提一下,第一点是retry 5次,因为微信平台存在未知原因,有的时候莫名会无法获得AT,需要重试,这里retry 5次,如果依旧无法获得,则邮件告警运维人员;第二点,用到了CountDownLatch闭锁,阻塞return直到获得正确的AT或者retey已经到达了最大重试次数。




微信公众平台 OAuth Access_Token获得,布布扣,bubuko.com

微信公众平台 OAuth Access_Token获得

上一篇:疑难杂症--SQL SERVER 18056的错误


下一篇:infoq 微信后台存储架构