wechat-0011,微信公众号,access_token的获取与管理

demo:https://github.com/wenrongyao/wechat-demo

摘要:access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

公众平台的API调用所需的access_token的使用及生成方式说明:

01、建议公众号开发者使用中控服务器统一获取和刷新Access_token,其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务;

02、目前Access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器可对外继续输出的老access_token,此时公众平台后台会保证在5分钟内,新老access_token都可用,这保证了第三方业务的平滑过渡;

03、Access_token的有效时间可能会在未来有调整,所以中控服务器不仅需要内部定时主动刷新,还需要提供被动刷新access_token的接口,这样便于业务服务器在API调用获知access_token已超时的情况下,可以触发access_token的刷新流程。

2、基本流程

注:在项目启动的时候获取access_token(任何在项目启动时会触发的都可以,例如监听器),获取逻辑:根据appid和appSecret获取accessToken,判断是否为空,为空3秒重新获取一次(以防网络问题,获取三次),不空则90分钟获取一次,每次获取的access_token,放在一次整个项目都可以访问的池子中,可以使用静态变量,也可以使用缓存,根据自己的实际需求选择就可以。

2.1 具体实现

获取accessToken:AccessTokenThread,这个类主要是用于获取access_token,其中实际获取acctoken的部分单独拎出来,以便其它地方手动调用。

import com.wechat.constant.Constant;
import com.wechat.util.DateUtil;
import com.wechat.util.GsonUtil;
import com.wechat.util.HttpRequest;
import com.wechat.util.LogUtil;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Map;

/**
 * accessToken线程类
 *
 * @author WRY
 */
public class AccessTokenThread implements Runnable {
    // 微信获取accessToken接口
    private static final String ACCESSTOKENURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={appSecret}";
    // 当accessToken获取不成功时重试次数
    private static Integer RETRY_TIMES = 3;

    public void run() {
        int retryTimes = 0;
        while (true) {
            String accessToken = getAccessToken();
            if (!StringUtils.isEmpty(accessToken)) {
                Constant.ACCESS_TOKEN = accessToken;
                try {
                    // 90分钟
                    Thread.sleep(90 * 60 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                retryTimes = 0;
            } else {
                if (retryTimes >= RETRY_TIMES) {
                    break;
                }
                retryTimes += 1;
                try {
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取access_Token
     *
     * @return
     */
    public static String getAccessToken() {
        String url = ACCESSTOKENURL.replace("{appId}", Constant.WechatAccount.APPID).replace("{appSecret}", Constant.WechatAccount.APPSECRET);
        String accessTokenJsonStr = HttpRequest.get(url, null, false);
        Map<String, String> accessTokenMap = GsonUtil.fromJson(accessTokenJsonStr, Map.class);
        String accessToken = null;
        if (null != accessTokenMap && !accessTokenMap.isEmpty()) {
            accessToken = accessTokenMap.get("access_token");
            if (!StringUtils.isEmpty(accessToken)) {
                LogUtil.info("时间:" + DateUtil.getDateStr(new Date()) + ";成功获取accessToken;值为:" + accessToken);
            }
        }
        if (StringUtils.isEmpty(accessToken)) {
            String errCode = null;
            String errMsg = null;
            try {
                errCode = accessTokenMap.get("errcode");
                errMsg = accessTokenMap.get("errmsg");
            } catch (Exception e) {
            }
            LogUtil.info("时间:" + DateUtil.getDateStr(new Date()) + ";获取accessToken失败;errCode为:" + errCode + ";errMsg" + errMsg);
        }
        return accessToken;
    }

}

其中appid和appsercret是自己公众号的两个参数替换一下即可。我是用静态的变量存放数据的,这个静态的数据在整个工程中是有效的(注:自己用junit普通单元测试或main方法测试是取不到这个值的,应为静态变量的作用域的原因)。

2.2、有了上面的工具,就可以获取access_token了,接下来就是找个合适时机启动这个线程即可。这边使用监听器,在servlet容器创建的时候获取。代码如下:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * 监听器
 * @author WRY
 *
 */
public class AccessTokenlistener implements ServletContextListener {

	public void contextInitialized(ServletContextEvent sce) {
		// 启动accessToken获取线程
		new Thread(new AccessTokenThread()).start();
	}

	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("监听器销毁ֹ");
	}

}

2.3 配置监听器

在web.xml中配置监听器

<!-- 获取accessToken的监听器  -->
	<listener>
		<listener-class>com.wechat.common.accesstoken.AccessTokenlistener</listener-class>
	</listener>

springboot配置参考:https://blog.csdn.net/wrongyao/article/details/85702188

好了上述就可以实现在项目启动的时候,获取access_token的值,并且每个90分钟自动获取。确保每次获取的值都是有效的。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值