diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java index cc2333086..c97facd30 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java @@ -10,27 +10,49 @@ import java.util.Arrays; public class SHA1 { /** - * 生成SHA1签名 + * 串接arr参数,生成sha1 digest + * * @param arr * @return */ public static String gen(String... arr) throws NoSuchAlgorithmException { Arrays.sort(arr); StringBuilder sb = new StringBuilder(); - for(String a : arr) { + for (String a : arr) { sb.append(a); } + return genStr(sb.toString()); + } + /** + * 用&串接arr参数,生成sha1 digest + * + * @param arr + * @return + */ + public static String genWithAmple(String... arr) throws NoSuchAlgorithmException { + Arrays.sort(arr); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < arr.length; i++) { + String a = arr[i]; + sb.append(a); + if (i != arr.length - 1) { + sb.append('&'); + } + } + return genStr(sb.toString()); + } + + public static String genStr(String str) throws NoSuchAlgorithmException { MessageDigest sha1 = MessageDigest.getInstance("SHA1"); - sha1.update(sb.toString().getBytes()); + sha1.update(str.getBytes()); byte[] output = sha1.digest(); return bytesToHex(output); } - protected static String bytesToHex(byte[] b) { - char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; StringBuffer buf = new StringBuffer(); for (int j = 0; j < b.length; j++) { buf.append(hexDigit[(b[j] >> 4) & 0x0f]); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java index 36c9cfbab..44123a36a 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java +++ b/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 void updateAccessToken(WxAccessToken accessToken); - - public void updateAccessToken(String accessToken, int expiresIn); - 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 getCorpId(); public String getCorpSecret(); @@ -25,7 +33,7 @@ public interface WxCpConfigStorage { public String getAesKey(); - public int getExpiresIn(); + public long getExpiresTime(); public String getOauth2redirectUri(); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java index 9ff1f1878..dd4882e29 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java +++ b/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 + '\'' + diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 808eb6ce3..36c78f0c4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -51,10 +51,11 @@ public interface WxCpService { * 程序员在非必要情况下尽量不要主动调用此方法 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token * - * + * @param forceRefresh 强制刷新 + * @return * @throws me.chanjar.weixin.common.exception.WxErrorException */ - public void accessTokenRefresh() throws WxErrorException; + public String getAccessToken(boolean forceRefresh) throws WxErrorException; /** *
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java
index 2e0738c72..fb7255c6c 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java
+++ b/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,40 @@ 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);
- }
- 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) {
- }
- }
- // 刷新完毕了,就没他什么事儿了
+ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
+ if (forceRefresh) {
+ wxCpConfigStorage.expireAccessToken();
}
+ 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);
+ }
+ }
+ }
+ }
+ return wxCpConfigStorage.getAccessToken();
}
public void messageSend(WxCpMessage message) throws WxErrorException {
@@ -369,10 +362,7 @@ public class WxCpServiceImpl implements WxCpService {
* @throws WxErrorException
*/
public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException {
- if (StringUtils.isBlank(wxCpConfigStorage.getAccessToken())) {
- accessTokenRefresh();
- }
- String accessToken = wxCpConfigStorage.getAccessToken();
+ String accessToken = getAccessToken(false);
String uriWithAccessToken = uri;
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
@@ -387,7 +377,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);
}
/**
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java
index 6ed438a96..d8757f340 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java
+++ b/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(false);
String after = configStorage.getAccessToken();
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoInMemoryConfigStorage.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoInMemoryConfigStorage.java
index 1d9103a5f..522198683 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoInMemoryConfigStorage.java
+++ b/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 + "]";
}
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 02c98f3f7..aa99a962b 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 @@
企业号应用Token
企业号应用EncodingAESKey
可以不填写
- 可以不填写
+ 可以不填写
企业号通讯录里的某个userid
企业号通讯录的某个部门id
企业号通讯录里的某个tagid
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
index 3ecbf155a..c54a119db 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
@@ -9,21 +9,52 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
*/
public interface WxMpConfigStorage {
- public void updateAccessToken(WxAccessToken accessToken);
-
- public void updateAccessToken(String accessToken, int expiresIn);
-
public String getAccessToken();
-
+
+ public boolean isAccessTokenExpired();
+
+ /**
+ * 强制将access token过期掉
+ */
+ public void expireAccessToken();
+
+ /**
+ * 应该是线程安全的
+ * @param accessToken
+ */
+ public void updateAccessToken(WxAccessToken accessToken);
+
+ /**
+ * 应该是线程安全的
+ * @param accessToken
+ * @param expiresIn
+ */
+ public void updateAccessToken(String accessToken, int expiresIn);
+
+ public String getJsapiTicket();
+
+ public boolean isJsapiTicketExpired();
+
+ /**
+ * 强制将jsapi ticket过期掉
+ */
+ public void expireJsapiTicket();
+
+ /**
+ * 应该是线程安全的
+ * @param jsapiTicket
+ */
+ public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);
+
public String getAppId();
-
+
public String getSecret();
-
+
public String getToken();
public String getAesKey();
- public int getExpiresIn();
+ public long getExpiresTime();
public String getOauth2redirectUri();
@@ -33,6 +64,7 @@ public interface WxMpConfigStorage {
public String getHttp_proxy_username();
+
public String getHttp_proxy_password();
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
index 82c3d6212..c694dde84 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
@@ -9,12 +9,14 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
*/
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
+ private static final long l = 7000 * 1000l;
+
protected String appId;
protected String secret;
protected String token;
protected String accessToken;
protected String aesKey;
- protected int expiresIn;
+ protected long expiresTime;
protected String oauth2redirectUri;
@@ -23,19 +25,48 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected String http_proxy_username;
protected String http_proxy_password;
- public void updateAccessToken(WxAccessToken accessToken) {
- updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
- }
-
- public void updateAccessToken(String accessToken, int expiresIn) {
- this.accessToken = accessToken;
- this.expiresIn = expiresIn;
- }
+ protected String jsapiTicket;
+ protected long jsapiTicketExpiresTime;
public String getAccessToken() {
return this.accessToken;
}
+ public boolean isAccessTokenExpired() {
+ return System.currentTimeMillis() > this.expiresTime;
+ }
+
+ public synchronized void updateAccessToken(WxAccessToken accessToken) {
+ updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
+ }
+
+ public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
+ this.accessToken = accessToken;
+ this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
+ }
+
+ public void expireAccessToken() {
+ this.expiresTime = 0;
+ }
+
+ public String getJsapiTicket() {
+ return jsapiTicket;
+ }
+
+ public boolean isJsapiTicketExpired() {
+ return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
+ }
+
+ public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
+ this.jsapiTicket = jsapiTicket;
+ // 预留200秒的时间
+ this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
+ }
+
+ public void expireJsapiTicket() {
+ this.jsapiTicketExpiresTime = 0;
+ }
+
public String getAppId() {
return this.appId;
}
@@ -48,8 +79,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
return this.token;
}
- public int getExpiresIn() {
- return this.expiresIn;
+ public long getExpiresTime() {
+ return this.expiresTime;
}
public void setAppId(String appId) {
@@ -76,8 +107,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
this.accessToken = accessToken;
}
- public void setExpiresIn(int expiresIn) {
- this.expiresIn = expiresIn;
+ public void setExpiresTime(long expiresTime) {
+ this.expiresTime = expiresTime;
}
@Override
@@ -121,6 +152,7 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
this.http_proxy_password = http_proxy_password;
}
+
@Override
public String toString() {
return "WxMpInMemoryConfigStorage{" +
@@ -129,7 +161,7 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
", token='" + token + '\'' +
", accessToken='" + accessToken + '\'' +
", aesKey='" + aesKey + '\'' +
- ", expiresIn=" + expiresIn +
+ ", expiresTime=" + expiresTime +
", http_proxy_host='" + http_proxy_host + '\'' +
", http_proxy_port=" + http_proxy_port +
", http_proxy_username='" + http_proxy_username + '\'' +
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
index c4dc3e541..2f0e68446 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
@@ -40,20 +40,48 @@ public interface WxMpService {
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token
*
+ * @param forceRefresh 强制刷新
+ * @return
* @throws me.chanjar.weixin.common.exception.WxErrorException
*/
- public void accessTokenRefresh() throws WxErrorException;
-
+ public String getAccessToken(boolean forceRefresh) throws WxErrorException;
+
+ /**
+ * + * 获得jsapi_ticket + * 获得时会检查jsapiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干 + * + * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 + *+ * @param forceRefresh 强制刷新 + * @return + * @throws WxErrorException + */ + public String getJsapiTicket(boolean forceRefresh) throws WxErrorException; + + /** + *
+ * 创建调用jsapi时所需要的签名 + * + * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 + *+ * @param timestamp 时间戳 + * @param noncestr 用户自己生成的随机字符串 + * @param url url + * @return + */ + public String createJsapiSignature(long timestamp, String noncestr, String url) throws WxErrorException; + /** *
* 上传多媒体文件
- *
+ *
* 上传的多媒体文件有格式和大小限制,如下:
* 图片(image): 1M,支持JPG格式
* 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
* 视频(video):10MB,支持MP4格式
* 缩略图(thumb):64KB,支持JPG格式
- *
+ *
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=上传下载多媒体文件
*
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
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 dbf2adc40..7b2563040 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
@@ -36,6 +36,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
+import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -43,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 ThreadLocal