/** * Copyright (c) 2011-2014, James Zhan 詹波 (jfinal@126.com). * * Licensed under the Apache License, Version 2.0 (the "License"); */ package com.jfinal.weixin.sdk.api; import com.jfinal.kit.PropKit; import com.jfinal.kit.StrKit; import com.jfinal.weixin.sdk.cache.IAccessTokenCache; import com.jfinal.weixin.sdk.kit.ParaMap; import com.jfinal.weixin.sdk.utils.HttpUtils; import com.jfinal.weixin.sdk.utils.RetryUtils; import java.util.Map; import java.util.concurrent.Callable; /** * 认证并获取 access_token API * http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token * * AccessToken默认存储于内存中,可设置存储于redis或者实现IAccessTokenCache到数据库中实现分布式可用 * * 具体配置: *
 * ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache());
 * 
*/ public class AccessTokenApi { // "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; private static String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"; /** * 从缓存中获取 access token,如果未取到或者 access token 不可用则先更新再获取 * @return AccessToken accessToken */ public static AccessToken getAccessToken() { ApiConfig ac = ApiConfigKit.getApiConfig(); AccessToken result = getAvailableAccessToken(ac); if (result != null) { return result; } return refreshAccessTokenIfNecessary(ac); } private static AccessToken getAvailableAccessToken(ApiConfig ac) { // 利用 appId 与 accessToken 建立关联,支持多账户 IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache(); String accessTokenJson = accessTokenCache.get(ac.getAppId()); if (StrKit.notBlank(accessTokenJson)) { AccessToken result = new AccessToken(accessTokenJson); if (result != null && result.isAvailable()) { return result; } } return null; } /** * 直接获取 accessToken 字符串,方便使用 * @return String accessToken */ public static String getAccessTokenStr() { return getAccessToken().getAccessToken(); } /** * synchronized 配合再次获取 token 并检测可用性,防止多线程重复刷新 token 值 */ private static synchronized AccessToken refreshAccessTokenIfNecessary(ApiConfig ac) { AccessToken result = getAvailableAccessToken(ac); if (result != null) { return result; } return refreshAccessToken(ac); } /** * 无条件强制更新 access token 值,不再对 cache 中的 token 进行判断 * @return AccessToken */ public static AccessToken refreshAccessToken() { return refreshAccessToken(ApiConfigKit.getApiConfig()); } /** * 无条件强制更新 access token 值,不再对 cache 中的 token 进行判断 * @param ac ApiConfig * @return AccessToken */ public static AccessToken refreshAccessToken(ApiConfig ac) { String appId = ac.getAppId(); String appSecret = ac.getAppSecret(); final Map queryParas = ParaMap.create("appid", appId).put("secret", appSecret).getData(); // 最多三次请求 AccessToken result = RetryUtils.retryOnException(3, new Callable() { @Override public AccessToken call() throws Exception { String json = HttpUtils.get(url, queryParas); return new AccessToken(json); } }); // 三次请求如果仍然返回了不可用的 access token 仍然 put 进去,便于上层通过 AccessToken 中的属性判断底层的情况 if (null != result) { // 利用 appId 与 accessToken 建立关联,支持多账户 IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache(); accessTokenCache.set(ac.getAppId(), result.getCacheJson()); } return result; } public static void main(String[] args) { PropKit.use("a_little_config.txt"); ApiConfig apiConfig = new ApiConfig(); apiConfig.setAppId(PropKit.get("appId")); apiConfig.setAppSecret(PropKit.get("appSecret")); ApiConfigKit.putApiConfig(apiConfig); AccessToken accessToken = AccessTokenApi.getAccessToken(); System.out.println(accessToken.getAccessToken()); System.out.println(AccessTokenApi.getAccessTokenStr()); } }