diff --git a/weixin-java-cp/src/test/resources/test-config.sample.xml b/weixin-java-cp/src/test/resources/test-config.sample.xml
index 02c98f3f..aa99a962 100644
--- a/weixin-java-cp/src/test/resources/test-config.sample.xml
+++ b/weixin-java-cp/src/test/resources/test-config.sample.xml
@@ -5,7 +5,7 @@
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index 636e8f62..0bb1c550 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -44,12 +44,15 @@ import java.util.concurrent.atomic.AtomicBoolean; public class WxMpServiceImpl implements WxMpService { /** - * 全局的是否正在刷新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(); + + /** + * 全局的是否正在刷新jsapi_ticket的锁 + */ + protected static final Object GLOBAL_JSAPI_TICKET_REFRESH_LOCK = new Object(); + protected WxMpConfigStorage wxMpConfigStorage; protected final ThreadLocalretryTimes = new ThreadLocal (); @@ -66,52 +69,45 @@ public class WxMpServiceImpl implements WxMpService { } } - public void accessTokenRefresh() throws WxErrorException { - if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) { - try { - String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" - + "&appid=" + wxMpConfigStorage.getAppId() - + "&secret=" + wxMpConfigStorage.getSecret() - ; - 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 (wxMpConfigStorage.isAccessTokenExpired()) { + synchronized (GLOBAL_ACCESS_TOKEN_REFRESH_LOCK) { + if (wxMpConfigStorage.isAccessTokenExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + + "&appid=" + wxMpConfigStorage.getAppId() + + "&secret=" + wxMpConfigStorage.getSecret() + ; + 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); + wxMpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); + } catch (ClientProtocolException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); } - WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); - wxMpConfigStorage.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 wxMpConfigStorage.getAccessToken(); } + public String getJsapiTicket() throws WxErrorException { - if (wxMpConfigStorage.isJsapiTokenExpired()) { - synchronized (wxMpConfigStorage) { - if (wxMpConfigStorage.isJsapiTokenExpired()) { + if (wxMpConfigStorage.isJsapiTicketExpired()) { + synchronized (GLOBAL_JSAPI_TICKET_REFRESH_LOCK) { + if (wxMpConfigStorage.isJsapiTicketExpired()) { String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; String responseContent = execute(new SimpleGetRequestExecutor(), url, null); JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); @@ -440,10 +436,7 @@ public class WxMpServiceImpl implements WxMpService { * @throws WxErrorException */ public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (StringUtils.isBlank(wxMpConfigStorage.getAccessToken())) { - accessTokenRefresh(); - } - String accessToken = wxMpConfigStorage.getAccessToken(); + String accessToken = getAccessToken(); String uriWithAccessToken = uri; uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; @@ -458,7 +451,8 @@ public class WxMpServiceImpl implements WxMpService { * 42001 access_token超时 */ if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - accessTokenRefresh(); + // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token + wxMpConfigStorage.expireAccessToken(); return execute(executor, uri, data); } /** diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java index c2a28546..d2a6ef8e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java @@ -65,7 +65,7 @@ public class WxMpOAuth2AccessToken { public String toString() { return "WxMpOAuth2AccessToken{" + "accessToken='" + accessToken + '\'' + - ", expiresIn=" + expiresIn + + ", expiresTime=" + expiresIn + ", refreshToken='" + refreshToken + '\'' + ", openId='" + openId + '\'' + ", scope='" + scope + '\'' + diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java index ad006acd..e6df8e34 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java @@ -42,7 +42,7 @@ public class ApiTestModule implements Module { @Override public String toString() { return "SimpleWxConfigProvider [appId=" + appId + ", secret=" + secret + ", accessToken=" + accessToken - + ", expiresIn=" + expiresIn + ", token=" + token + ", openId=" + openId + "]"; + + ", expiresTime=" + expiresTime + ", token=" + token + ", openId=" + openId + "]"; } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java index ef9590e6..e773f117 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java @@ -22,7 +22,7 @@ public class WxMpBaseAPITest { public void testRefreshAccessToken() throws WxErrorException { WxMpConfigStorage configStorage = wxService.wxMpConfigStorage; String before = configStorage.getAccessToken(); - wxService.accessTokenRefresh(); + wxService.getAccessToken(); String after = configStorage.getAccessToken(); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java index 22d87dd4..becfbeb4 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java @@ -16,7 +16,7 @@ class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage { @Override public String toString() { return "SimpleWxConfigProvider [appId=" + appId + ", secret=" + secret + ", accessToken=" + accessToken - + ", expiresIn=" + expiresIn + ", token=" + token + ", aesKey=" + aesKey + "]"; + + ", expiresTime=" + expiresTime + ", token=" + token + ", aesKey=" + aesKey + "]"; } diff --git a/weixin-java-mp/src/test/resources/test-config.sample.xml b/weixin-java-mp/src/test/resources/test-config.sample.xml index 19535f3c..6ec4825a 100644 --- a/weixin-java-mp/src/test/resources/test-config.sample.xml +++ b/weixin-java-mp/src/test/resources/test-config.sample.xml @@ -4,7 +4,7 @@ 公众号Token 公众号EncodingAESKey 可以不填写 -可以不填写 +可以不填写 某个加你公众号的用户的openId 网页授权获取用户信息回调地址