shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package com.walker.wxtools;
 
import com.walker.infrastructure.utils.StringUtils;
import com.walker.wxtools.util.AccessTokenUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public abstract class AbstractOfficialAccountEngine implements OfficialAccountEngine{
 
    protected final transient Logger logger = LoggerFactory.getLogger(this.getClass());
 
    @Override
    public WxUserInfo getUserInfoSub(String openId) throws AccessTokenNotFoundException{
        String basicAccessToken = null;
        try {
            basicAccessToken = this.getBasicAccessToken();
            if(StringUtils.isEmpty(basicAccessToken)){
                throw new Exception("basicAccessToken为空", null);
            }
 
        } catch (Exception ex){
            throw new AccessTokenNotFoundException(ex.getMessage(), ex);
        }
 
        try {
            return this.acquireRemoteUserInfoSub(openId, basicAccessToken);
        } catch (WxRemoteException e) {
            throw new RuntimeException("远程调用'获取微信用户接口'失败:" + e.getError(), e);
        }
    }
 
    @Override
    public WxUserInfo getUserInfo(String openId) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public String getAuthAccessToken(String code) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public String getJsApiTicket() {
        String basicAccessToken = this.getBasicAccessToken();
        if(StringUtils.isEmpty(basicAccessToken)){
            logger.error("getJsApiTicket:获取'basicAccessToken'为空!");
            return null;
        }
        return this.getJsApiTicket(basicAccessToken);
    }
 
    @Override
    public String getJsApiTicket(String basicAccessToken) {
        JsTicket jsTicket = this.acquireCachedJsTicket(Constants.CACHE_PREFIX_JS_TICKET + this.getAppId());
        if(jsTicket != null){
            if(!AccessTokenUtils.isExpiredCache(jsTicket.getCreateTime(), this.maxCachedAccessTokenSeconds)){
                return jsTicket.getTicket();
            }
        }
 
        // 重新获取:jsTicket
        try {
            jsTicket = this.acquireRemoteJsTicket(basicAccessToken);
            logger.debug("远程获取'jsTicket'..........{}", jsTicket);
            this.writeJsTicketToCache(Constants.CACHE_PREFIX_JS_TICKET + this.getAppId(), jsTicket);
            return jsTicket.getTicket();
        } catch (WxRemoteException e) {
            throw new RuntimeException(e.getError(), e);
        }
    }
 
    @Override
    public String getJsApiTicket4Card(String basicAccessToken) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public String getBasicAccessToken() {
        BasicAccessToken accessToken = this.acquireCachedBasicAccessToken(Constants.CACHE_PREFIX_ACCESS_TOKEN + this.getAppId());
        if(accessToken != null){
            if(!AccessTokenUtils.isExpiredCache(accessToken.getCreateTime(), this.maxCachedAccessTokenSeconds)){
                // 缓存未过期,直接返回
                return accessToken.getAccessToken();
            }
        }
 
        // 重新获取:access_token
        try {
            accessToken = this.acquireRemoteBasicAccessToken(this.getAppId(), this.getSecret());
            logger.debug("远程获取'access_token'..........{}", accessToken);
            this.writeBasicAccessTokenToCache(Constants.CACHE_PREFIX_ACCESS_TOKEN + this.getAppId(), accessToken);
            return accessToken.getAccessToken();
        } catch (WxRemoteException e) {
            throw new RuntimeException(e.getError(), e);
        }
    }
 
    protected abstract JsTicket acquireCachedJsTicket(String cacheKey);
    protected abstract void writeJsTicketToCache(String cacheKey, JsTicket jsTicket);
    protected abstract JsTicket acquireRemoteJsTicket(String basicAccessToken) throws WxRemoteException;
 
    /**
     * 从缓存中获取appId对应的基础'access_token'对象。
     * @param cacheKey
     * @return
     * @date 2023-04-20
     */
    protected abstract BasicAccessToken acquireCachedBasicAccessToken(String cacheKey);
 
    /**
     * 把基础'access_token'写入缓存中。<p>默认基于内存,业务可以重写方法,写入redis中</p>
     * @param cacheKey 缓存的key = access_token:appId
     * @param basicAccessToken 缓存的对象
     * @date 2023-04-20
     */
    protected abstract void writeBasicAccessTokenToCache(String cacheKey, BasicAccessToken basicAccessToken);
 
    /**
     * 远程调用微信,获取一个新的基础'access_token'数据。
     * @param appId
     * @param secret
     * @return
     * @throws WxRemoteException
     * @date 2023-04-20
     */
    protected abstract BasicAccessToken acquireRemoteBasicAccessToken(String appId, String secret) throws WxRemoteException;
 
    protected abstract WxUserInfo acquireRemoteUserInfoSub(String openId, String basicAccessToken) throws WxRemoteException;
 
    @Override
    public void setAppId(String appId) {
        if(StringUtils.isEmpty(appId)){
            throw new IllegalArgumentException("'appId'必须提供");
        }
        this.appId = appId;
    }
 
    @Override
    public void setSecret(String secret) {
        if(StringUtils.isEmpty(secret)){
            throw new IllegalArgumentException("'secret'必须提供");
        }
        this.secret = secret;
    }
 
    @Override
    public String getAppId() {
        return appId;
    }
 
    protected String getSecret() {
        return secret;
    }
 
    public long getMaxCachedAccessTokenSeconds() {
        return maxCachedAccessTokenSeconds;
    }
 
    /**
     * 设置:access_token 缓存最大时间(秒),默认:5400秒
     * @param maxCachedAccessTokenSeconds
     * @date 2023-04-20
     */
    public void setMaxCachedAccessTokenSeconds(long maxCachedAccessTokenSeconds) {
        this.maxCachedAccessTokenSeconds = maxCachedAccessTokenSeconds;
    }
 
    private long maxCachedAccessTokenSeconds = 5400;
    private String appId;
    private String secret;
}