Skip to content

Commit 1daf3a6

Browse files
committed
refactor: CP 调整access token刷新策略
1 parent 1bca854 commit 1daf3a6

File tree

6 files changed

+69
-64
lines changed

6 files changed

+69
-64
lines changed

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,20 @@
99
*/
1010
public interface WxCpConfigStorage {
1111

12+
public String getAccessToken();
13+
14+
public boolean isAccessTokenExpired();
15+
16+
/**
17+
* 强制将access token过期掉
18+
*/
19+
public void expireAccessToken();
20+
1221
public void updateAccessToken(WxAccessToken accessToken);
13-
22+
1423
public void updateAccessToken(String accessToken, int expiresIn);
15-
16-
public String getAccessToken();
17-
24+
25+
1826
public String getCorpId();
1927

2028
public String getCorpSecret();
@@ -25,7 +33,7 @@ public interface WxCpConfigStorage {
2533

2634
public String getAesKey();
2735

28-
public int getExpiresIn();
36+
public long getExpiresTime();
2937

3038
public String getOauth2redirectUri();
3139

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
1616
protected String accessToken;
1717
protected String aesKey;
1818
protected String agentId;
19-
protected int expiresIn;
19+
protected long expiresTime;
2020

2121
protected String oauth2redirectUri;
2222

@@ -25,17 +25,25 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
2525
protected String http_proxy_username;
2626
protected String http_proxy_password;
2727

28+
public String getAccessToken() {
29+
return this.accessToken;
30+
}
31+
32+
public boolean isAccessTokenExpired() {
33+
return System.currentTimeMillis() > this.expiresTime;
34+
}
35+
36+
public void expireAccessToken() {
37+
this.expiresTime = 0;
38+
}
39+
2840
public void updateAccessToken(WxAccessToken accessToken) {
2941
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
3042
}
3143

32-
public void updateAccessToken(String accessToken, int expiresIn) {
44+
public void updateAccessToken(String accessToken, int expiresInSeconds) {
3345
this.accessToken = accessToken;
34-
this.expiresIn = expiresIn;
35-
}
36-
37-
public String getAccessToken() {
38-
return this.accessToken;
46+
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
3947
}
4048

4149
public String getCorpId() {
@@ -50,8 +58,8 @@ public String getToken() {
5058
return this.token;
5159
}
5260

53-
public int getExpiresIn() {
54-
return this.expiresIn;
61+
public long getExpiresTime() {
62+
return this.expiresTime;
5563
}
5664

5765
public void setCorpId(String corpId) {
@@ -78,8 +86,8 @@ public void setAccessToken(String accessToken) {
7886
this.accessToken = accessToken;
7987
}
8088

81-
public void setExpiresIn(int expiresIn) {
82-
this.expiresIn = expiresIn;
89+
public void setExpiresTime(long expiresTime) {
90+
this.expiresTime = expiresTime;
8391
}
8492

8593
public String getAgentId() {
@@ -140,7 +148,7 @@ public String toString() {
140148
", accessToken='" + accessToken + '\'' +
141149
", aesKey='" + aesKey + '\'' +
142150
", agentId='" + agentId + '\'' +
143-
", expiresIn=" + expiresIn +
151+
", expiresTime=" + expiresTime +
144152
", http_proxy_host='" + http_proxy_host + '\'' +
145153
", http_proxy_port=" + http_proxy_port +
146154
", http_proxy_username='" + http_proxy_username + '\'' +

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ public interface WxCpService {
5252
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token
5353
* </pre>
5454
*
55+
* @return
5556
* @throws me.chanjar.weixin.common.exception.WxErrorException
5657
*/
57-
public void accessTokenRefresh() throws WxErrorException;
58+
public String getAccessToken() throws WxErrorException;
5859

5960
/**
6061
* <pre>

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,9 @@
4646
public class WxCpServiceImpl implements WxCpService {
4747

4848
/**
49-
* 全局的是否正在刷新Access Token的flag
50-
* true: 正在刷新
51-
* false: 没有刷新
49+
* 全局的是否正在刷新access token的锁
5250
*/
53-
protected static final AtomicBoolean GLOBAL_ACCESS_TOKEN_REFRESH_FLAG = new AtomicBoolean(false);
51+
protected static final Object GLOBAL_ACCESS_TOKEN_REFRESH_LOCK = new Object();
5452

5553
protected WxCpConfigStorage wxCpConfigStorage;
5654

@@ -73,45 +71,37 @@ public void userAuthenticated(String userId) throws WxErrorException {
7371
execute(new SimpleGetRequestExecutor(), url, null);
7472
}
7573

76-
public void accessTokenRefresh() throws WxErrorException {
77-
if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) {
78-
try {
79-
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
80-
+ "&corpid=" + wxCpConfigStorage.getCorpId()
81-
+ "&corpsecret=" + wxCpConfigStorage.getCorpSecret();
82-
try {
83-
HttpGet httpGet = new HttpGet(url);
84-
if (httpProxy != null) {
85-
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
86-
httpGet.setConfig(config);
87-
}
88-
CloseableHttpClient httpclient = getHttpclient();
89-
CloseableHttpResponse response = httpclient.execute(httpGet);
90-
String resultContent = new BasicResponseHandler().handleResponse(response);
91-
WxError error = WxError.fromJson(resultContent);
92-
if (error.getErrorCode() != 0) {
93-
throw new WxErrorException(error);
74+
public String getAccessToken() throws WxErrorException {
75+
if (wxCpConfigStorage.isAccessTokenExpired()) {
76+
synchronized (GLOBAL_ACCESS_TOKEN_REFRESH_LOCK) {
77+
if (wxCpConfigStorage.isAccessTokenExpired()) {
78+
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
79+
+ "&corpid=" + wxCpConfigStorage.getCorpId()
80+
+ "&corpsecret=" + wxCpConfigStorage.getCorpSecret();
81+
try {
82+
HttpGet httpGet = new HttpGet(url);
83+
if (httpProxy != null) {
84+
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
85+
httpGet.setConfig(config);
86+
}
87+
CloseableHttpClient httpclient = getHttpclient();
88+
CloseableHttpResponse response = httpclient.execute(httpGet);
89+
String resultContent = new BasicResponseHandler().handleResponse(response);
90+
WxError error = WxError.fromJson(resultContent);
91+
if (error.getErrorCode() != 0) {
92+
throw new WxErrorException(error);
93+
}
94+
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
95+
wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
96+
} catch (ClientProtocolException e) {
97+
throw new RuntimeException(e);
98+
} catch (IOException e) {
99+
throw new RuntimeException(e);
94100
}
95-
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
96-
wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
97-
} catch (ClientProtocolException e) {
98-
throw new RuntimeException(e);
99-
} catch (IOException e) {
100-
throw new RuntimeException(e);
101101
}
102-
} finally {
103-
GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.set(false);
104102
}
105-
} else {
106-
// 每隔100ms检查一下是否刷新完毕了
107-
while (GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.get()) {
108-
try {
109-
Thread.sleep(100);
110-
} catch (InterruptedException e) {
111-
}
112-
}
113-
// 刷新完毕了,就没他什么事儿了
114103
}
104+
return wxCpConfigStorage.getAccessToken();
115105
}
116106

117107
public void messageSend(WxCpMessage message) throws WxErrorException {
@@ -369,10 +359,7 @@ public String post(String url, String postData) throws WxErrorException {
369359
* @throws WxErrorException
370360
*/
371361
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
372-
if (StringUtils.isBlank(wxCpConfigStorage.getAccessToken())) {
373-
accessTokenRefresh();
374-
}
375-
String accessToken = wxCpConfigStorage.getAccessToken();
362+
String accessToken = getAccessToken();
376363

377364
String uriWithAccessToken = uri;
378365
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
@@ -387,7 +374,8 @@ public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) thro
387374
* 42001 access_token超时
388375
*/
389376
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) {
390-
accessTokenRefresh();
377+
// 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
378+
wxCpConfigStorage.expireAccessToken();
391379
return execute(executor, uri, data);
392380
}
393381
/**

weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class WxCpBaseAPITest {
2222
public void testRefreshAccessToken() throws WxErrorException {
2323
WxCpConfigStorage configStorage = wxService.wxCpConfigStorage;
2424
String before = configStorage.getAccessToken();
25-
wxService.accessTokenRefresh();
25+
wxService.getAccessToken();
2626

2727
String after = configStorage.getAccessToken();
2828

weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoInMemoryConfigStorage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage {
1616
@Override
1717
public String toString() {
1818
return "SimpleWxConfigProvider [appidOrCorpid=" + corpId + ", corpSecret=" + corpSecret + ", accessToken=" + accessToken
19-
+ ", expiresIn=" + expiresIn + ", token=" + token + ", aesKey=" + aesKey + "]";
19+
+ ", expiresTime=" + expiresTime + ", token=" + token + ", aesKey=" + aesKey + "]";
2020
}
2121

2222

0 commit comments

Comments
 (0)