Blame view

src/main/java/com/jfinal/wxaapp/api/WxaAccessTokenApi.java 3.98 KB
e80df919   atao   init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  /**
   * Copyright (c) 2011-2014, L.cm 卢春梦 (qq596392912@gmail.com).
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   */
  
  package com.jfinal.wxaapp.api;
  
  import com.jfinal.kit.StrKit;
  import com.jfinal.weixin.sdk.api.ApiConfigKit;
  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 com.jfinal.wxaapp.WxaConfig;
  import com.jfinal.wxaapp.WxaConfigKit;
  
  import java.util.Map;
  import java.util.concurrent.Callable;
  
  /**
   * 小程序access_token
   * @author L.cm
   *
   */
  public class WxaAccessTokenApi {
      // "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";
  
      private static final String cachePrefix = "wxa:";
  
      /**
       * 从缓存中获取 access token,如果未取到或者 access token 不可用则先更新再获取
       * @return WxaAccessToken accessToken
       */
      public static WxaAccessToken getAccessToken() {
          WxaConfig wc = WxaConfigKit.getWxaConfig();
          WxaAccessToken result = getAvailableAccessToken(wc);
          if (result != null) {
              return result;
          }
  
          return refreshAccessTokenIfNecessary(wc);
      }
  
      private static WxaAccessToken getAvailableAccessToken(WxaConfig wc) {
          // 利用 appId 与 accessToken 建立关联,支持多账户
          IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache();
          String accessTokenJson = accessTokenCache.get(cachePrefix + wc.getAppId());
          if (StrKit.notBlank(accessTokenJson)) {
              WxaAccessToken result = new WxaAccessToken(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 WxaAccessToken refreshAccessTokenIfNecessary(WxaConfig wc) {
          WxaAccessToken result = getAvailableAccessToken(wc);
          if (result != null) {
              return result;
          }
          return refreshAccessToken(wc);
      }
  
      /**
       * 无条件强制更新 access token 值,不再对 cache 中的 token 进行判断
       * @return WxaAccessToken
       */
      public static WxaAccessToken refreshAccessToken() {
          return refreshAccessToken(WxaConfigKit.getWxaConfig());
      }
  
      /**
       * 无条件强制更新 access token 值,不再对 cache 中的 token 进行判断
       * @param wc WxaConfig
       * @return WxaAccessToken
       */
      public static WxaAccessToken refreshAccessToken(WxaConfig wc) {
          String appId = wc.getAppId();
          String appSecret = wc.getAppSecret();
          final Map<String, String> queryParas = ParaMap.create("appid", appId).put("secret", appSecret).getData();
  
          // 最多三次请求
          WxaAccessToken result = RetryUtils.retryOnException(3, new Callable<WxaAccessToken>() {
  
              @Override
              public WxaAccessToken call() throws Exception {
                  String json = HttpUtils.get(url, queryParas);
                  return new WxaAccessToken(json);
              }
          });
  
          // 三次请求如果仍然返回了不可用的 access token 仍然 put 进去,便于上层通过 WxaAccessToken 中的属性判断底层的情况
          if (null != result) {
              // 利用 appId 与 accessToken 建立关联,支持多账户
              IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache();
              accessTokenCache.set(cachePrefix + wc.getAppId(), result.getCacheJson());
          }
          return result;
      }
  
  }