ソースを参照

refactor: CP 调整access token刷新策略

master
Daniel Qian 10年前
コミット
1daf3a63a1
6個のファイルの変更69行の追加64行の削除
  1. +13
    -5
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java
  2. +20
    -12
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java
  3. +2
    -1
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
  4. +32
    -44
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java
  5. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java
  6. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoInMemoryConfigStorage.java

+ 13
- 5
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java ファイルの表示

@@ -9,12 +9,20 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
*/
public interface WxCpConfigStorage {

public String getAccessToken();

public boolean isAccessTokenExpired();

/**
* 强制将access token过期掉
*/
public void expireAccessToken();

public void updateAccessToken(WxAccessToken accessToken);
public void updateAccessToken(String accessToken, int expiresIn);
public String getAccessToken();


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

public String getAesKey();

public int getExpiresIn();
public long getExpiresTime();

public String getOauth2redirectUri();



+ 20
- 12
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java ファイルの表示

@@ -16,7 +16,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
protected String accessToken;
protected String aesKey;
protected String agentId;
protected int expiresIn;
protected long expiresTime;

protected String oauth2redirectUri;

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

public String getAccessToken() {
return this.accessToken;
}

public boolean isAccessTokenExpired() {
return System.currentTimeMillis() > this.expiresTime;
}

public void expireAccessToken() {
this.expiresTime = 0;
}

public void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
public void updateAccessToken(String accessToken, int expiresIn) {
public void updateAccessToken(String accessToken, int expiresInSeconds) {
this.accessToken = accessToken;
this.expiresIn = expiresIn;
}

public String getAccessToken() {
return this.accessToken;
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
}

public String getCorpId() {
@@ -50,8 +58,8 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
return this.token;
}

public int getExpiresIn() {
return this.expiresIn;
public long getExpiresTime() {
return this.expiresTime;
}

public void setCorpId(String corpId) {
@@ -78,8 +86,8 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
this.accessToken = accessToken;
}

public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
public void setExpiresTime(long expiresTime) {
this.expiresTime = expiresTime;
}

public String getAgentId() {
@@ -140,7 +148,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
", accessToken='" + accessToken + '\'' +
", aesKey='" + aesKey + '\'' +
", agentId='" + agentId + '\'' +
", expiresIn=" + expiresIn +
", expiresTime=" + expiresTime +
", http_proxy_host='" + http_proxy_host + '\'' +
", http_proxy_port=" + http_proxy_port +
", http_proxy_username='" + http_proxy_username + '\'' +


+ 2
- 1
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java ファイルの表示

@@ -52,9 +52,10 @@ public interface WxCpService {
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token
* </pre>
*
* @return
* @throws me.chanjar.weixin.common.exception.WxErrorException
*/
public void accessTokenRefresh() throws WxErrorException;
public String getAccessToken() throws WxErrorException;

/**
* <pre>


+ 32
- 44
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java ファイルの表示

@@ -46,11 +46,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class WxCpServiceImpl implements WxCpService {

/**
* 全局的是否正在刷新Access Token的flag
* true: 正在刷新
* false: 没有刷新
* 全局的是否正在刷新access token的锁
*/
protected static final AtomicBoolean GLOBAL_ACCESS_TOKEN_REFRESH_FLAG = new AtomicBoolean(false);
protected static final Object GLOBAL_ACCESS_TOKEN_REFRESH_LOCK = new Object();

protected WxCpConfigStorage wxCpConfigStorage;

@@ -73,45 +71,37 @@ public class WxCpServiceImpl implements WxCpService {
execute(new SimpleGetRequestExecutor(), url, null);
}

public void accessTokenRefresh() throws WxErrorException {
if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) {
try {
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
+ "&corpid=" + wxCpConfigStorage.getCorpId()
+ "&corpsecret=" + wxCpConfigStorage.getCorpSecret();
try {
HttpGet httpGet = new HttpGet(url);
if (httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
httpGet.setConfig(config);
}
CloseableHttpClient httpclient = getHttpclient();
CloseableHttpResponse response = httpclient.execute(httpGet);
String resultContent = new BasicResponseHandler().handleResponse(response);
WxError error = WxError.fromJson(resultContent);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
public String getAccessToken() throws WxErrorException {
if (wxCpConfigStorage.isAccessTokenExpired()) {
synchronized (GLOBAL_ACCESS_TOKEN_REFRESH_LOCK) {
if (wxCpConfigStorage.isAccessTokenExpired()) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
+ "&corpid=" + wxCpConfigStorage.getCorpId()
+ "&corpsecret=" + wxCpConfigStorage.getCorpSecret();
try {
HttpGet httpGet = new HttpGet(url);
if (httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
httpGet.setConfig(config);
}
CloseableHttpClient httpclient = getHttpclient();
CloseableHttpResponse response = httpclient.execute(httpGet);
String resultContent = new BasicResponseHandler().handleResponse(response);
WxError error = WxError.fromJson(resultContent);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
} finally {
GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.set(false);
}
} else {
// 每隔100ms检查一下是否刷新完毕了
while (GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.get()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
// 刷新完毕了,就没他什么事儿了
}
return wxCpConfigStorage.getAccessToken();
}

public void messageSend(WxCpMessage message) throws WxErrorException {
@@ -369,10 +359,7 @@ public class WxCpServiceImpl implements WxCpService {
* @throws WxErrorException
*/
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
if (StringUtils.isBlank(wxCpConfigStorage.getAccessToken())) {
accessTokenRefresh();
}
String accessToken = wxCpConfigStorage.getAccessToken();
String accessToken = getAccessToken();

String uriWithAccessToken = uri;
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
@@ -387,7 +374,8 @@ public class WxCpServiceImpl implements WxCpService {
* 42001 access_token超时
*/
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) {
accessTokenRefresh();
// 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
wxCpConfigStorage.expireAccessToken();
return execute(executor, uri, data);
}
/**


+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java ファイルの表示

@@ -22,7 +22,7 @@ public class WxCpBaseAPITest {
public void testRefreshAccessToken() throws WxErrorException {
WxCpConfigStorage configStorage = wxService.wxCpConfigStorage;
String before = configStorage.getAccessToken();
wxService.accessTokenRefresh();
wxService.getAccessToken();

String after = configStorage.getAccessToken();



+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoInMemoryConfigStorage.java ファイルの表示

@@ -16,7 +16,7 @@ class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage {
@Override
public String toString() {
return "SimpleWxConfigProvider [appidOrCorpid=" + corpId + ", corpSecret=" + corpSecret + ", accessToken=" + accessToken
+ ", expiresIn=" + expiresIn + ", token=" + token + ", aesKey=" + aesKey + "]";
+ ", expiresTime=" + expiresTime + ", token=" + token + ", aesKey=" + aesKey + "]";
}




読み込み中…
キャンセル
保存