mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-04-05 17:38:05 +08:00
Merge pull request #82 from iwareserictsai/develop
修改Token/Ticket的同步机制以支持集群
This commit is contained in:
commit
6278161f23
@ -5,6 +5,7 @@ import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
|
|||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信客户端配置存储
|
* 微信客户端配置存储
|
||||||
@ -15,6 +16,8 @@ public interface WxMpConfigStorage {
|
|||||||
|
|
||||||
String getAccessToken();
|
String getAccessToken();
|
||||||
|
|
||||||
|
Lock getAccessTokenLock();
|
||||||
|
|
||||||
boolean isAccessTokenExpired();
|
boolean isAccessTokenExpired();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,6 +40,8 @@ public interface WxMpConfigStorage {
|
|||||||
|
|
||||||
String getJsapiTicket();
|
String getJsapiTicket();
|
||||||
|
|
||||||
|
Lock getJsapiTicketLock();
|
||||||
|
|
||||||
boolean isJsapiTicketExpired();
|
boolean isJsapiTicketExpired();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,6 +58,8 @@ public interface WxMpConfigStorage {
|
|||||||
|
|
||||||
String getCardApiTicket();
|
String getCardApiTicket();
|
||||||
|
|
||||||
|
Lock getCardApiTicketLock();
|
||||||
|
|
||||||
boolean isCardApiTicketExpired();
|
boolean isCardApiTicketExpired();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,8 @@ import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
|
|||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
|
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
|
||||||
@ -36,6 +38,10 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
protected volatile String cardApiTicket;
|
protected volatile String cardApiTicket;
|
||||||
protected volatile long cardApiTicketExpiresTime;
|
protected volatile long cardApiTicketExpiresTime;
|
||||||
|
|
||||||
|
protected Lock accessTokenLock = new ReentrantLock();
|
||||||
|
protected Lock jsapiTicketLock = new ReentrantLock();
|
||||||
|
protected Lock cardApiTicketLock = new ReentrantLock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 临时文件目录
|
* 临时文件目录
|
||||||
*/
|
*/
|
||||||
@ -50,6 +56,11 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
return this.accessToken;
|
return this.accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lock getAccessTokenLock() {
|
||||||
|
return this.accessTokenLock;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAccessTokenExpired() {
|
public boolean isAccessTokenExpired() {
|
||||||
return System.currentTimeMillis() > this.expiresTime;
|
return System.currentTimeMillis() > this.expiresTime;
|
||||||
@ -76,6 +87,11 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
return this.jsapiTicket;
|
return this.jsapiTicket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lock getJsapiTicketLock() {
|
||||||
|
return this.jsapiTicketLock;
|
||||||
|
}
|
||||||
|
|
||||||
public void setJsapiTicket(String jsapiTicket) {
|
public void setJsapiTicket(String jsapiTicket) {
|
||||||
this.jsapiTicket = jsapiTicket;
|
this.jsapiTicket = jsapiTicket;
|
||||||
}
|
}
|
||||||
@ -113,6 +129,11 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
return this.cardApiTicket;
|
return this.cardApiTicket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lock getCardApiTicketLock() {
|
||||||
|
return this.cardApiTicketLock;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCardApiTicketExpired() {
|
public boolean isCardApiTicketExpired() {
|
||||||
return System.currentTimeMillis() > this.cardApiTicketExpiresTime;
|
return System.currentTimeMillis() > this.cardApiTicketExpiresTime;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package me.chanjar.weixin.mp.api.impl;
|
package me.chanjar.weixin.mp.api.impl;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -29,11 +30,6 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
|
|
||||||
private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class);
|
private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局的是否正在刷新卡券api_ticket的锁
|
|
||||||
*/
|
|
||||||
private final Object globalCardApiTicketRefreshLock = new Object();
|
|
||||||
|
|
||||||
private WxMpService wxMpService;
|
private WxMpService wxMpService;
|
||||||
|
|
||||||
public WxMpCardServiceImpl(WxMpService wxMpService) {
|
public WxMpCardServiceImpl(WxMpService wxMpService) {
|
||||||
@ -66,21 +62,25 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
|
public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
|
||||||
if (forceRefresh) {
|
Lock lock = wxMpService.getWxMpConfigStorage().getCardApiTicketLock();
|
||||||
this.wxMpService.getWxMpConfigStorage().expireCardApiTicket();
|
try {
|
||||||
}
|
lock.lock();
|
||||||
if (this.wxMpService.getWxMpConfigStorage().isCardApiTicketExpired()) {
|
|
||||||
synchronized (this.globalCardApiTicketRefreshLock) {
|
if (forceRefresh) {
|
||||||
if (this.wxMpService.getWxMpConfigStorage().isCardApiTicketExpired()) {
|
this.wxMpService.getWxMpConfigStorage().expireCardApiTicket();
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card";
|
|
||||||
String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null);
|
|
||||||
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
|
|
||||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
|
||||||
String cardApiTicket = tmpJsonObject.get("ticket").getAsString();
|
|
||||||
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
|
||||||
this.wxMpService.getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.wxMpService.getWxMpConfigStorage().isCardApiTicketExpired()) {
|
||||||
|
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card";
|
||||||
|
String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null);
|
||||||
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
|
||||||
|
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
||||||
|
String cardApiTicket = tmpJsonObject.get("ticket").getAsString();
|
||||||
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
||||||
|
this.wxMpService.getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
}
|
}
|
||||||
return this.wxMpService.getWxMpConfigStorage().getCardApiTicket();
|
return this.wxMpService.getWxMpConfigStorage().getCardApiTicket();
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
public class WxMpServiceImpl implements WxMpService {
|
public class WxMpServiceImpl implements WxMpService {
|
||||||
|
|
||||||
@ -35,16 +36,6 @@ public class WxMpServiceImpl implements WxMpService {
|
|||||||
|
|
||||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局的是否正在刷新access token的锁
|
|
||||||
*/
|
|
||||||
private final Object globalAccessTokenRefreshLock = new Object();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局的是否正在刷新jsapi_ticket的锁
|
|
||||||
*/
|
|
||||||
private final Object globalJsapiTicketRefreshLock = new Object();
|
|
||||||
|
|
||||||
private WxMpConfigStorage configStorage;
|
private WxMpConfigStorage configStorage;
|
||||||
|
|
||||||
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
|
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
|
||||||
@ -98,39 +89,42 @@ public class WxMpServiceImpl implements WxMpService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||||
if (forceRefresh) {
|
Lock lock = configStorage.getAccessTokenLock();
|
||||||
this.configStorage.expireAccessToken();
|
try {
|
||||||
}
|
lock.lock();
|
||||||
|
|
||||||
if (this.configStorage.isAccessTokenExpired()) {
|
if (forceRefresh) {
|
||||||
synchronized (this.globalAccessTokenRefreshLock) {
|
this.configStorage.expireAccessToken();
|
||||||
if (this.configStorage.isAccessTokenExpired()) {
|
}
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
|
|
||||||
"&appid=" + this.configStorage.getAppId() + "&secret="
|
if (this.configStorage.isAccessTokenExpired()) {
|
||||||
+ this.configStorage.getSecret();
|
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
|
||||||
try {
|
"&appid=" + this.configStorage.getAppId() + "&secret="
|
||||||
HttpGet httpGet = new HttpGet(url);
|
+ this.configStorage.getSecret();
|
||||||
if (this.httpProxy != null) {
|
try {
|
||||||
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy).build();
|
HttpGet httpGet = new HttpGet(url);
|
||||||
httpGet.setConfig(config);
|
if (this.httpProxy != null) {
|
||||||
}
|
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy).build();
|
||||||
try (CloseableHttpResponse response = getHttpclient().execute(httpGet)) {
|
httpGet.setConfig(config);
|
||||||
String resultContent = new BasicResponseHandler().handleResponse(response);
|
|
||||||
WxError error = WxError.fromJson(resultContent);
|
|
||||||
if (error.getErrorCode() != 0) {
|
|
||||||
throw new WxErrorException(error);
|
|
||||||
}
|
|
||||||
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
|
|
||||||
this.configStorage.updateAccessToken(accessToken.getAccessToken(),
|
|
||||||
accessToken.getExpiresIn());
|
|
||||||
}finally {
|
|
||||||
httpGet.releaseConnection();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
try (CloseableHttpResponse response = getHttpclient().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);
|
||||||
|
this.configStorage.updateAccessToken(accessToken.getAccessToken(),
|
||||||
|
accessToken.getExpiresIn());
|
||||||
|
}finally {
|
||||||
|
httpGet.releaseConnection();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
}
|
}
|
||||||
return this.configStorage.getAccessToken();
|
return this.configStorage.getAccessToken();
|
||||||
}
|
}
|
||||||
@ -142,22 +136,25 @@ public class WxMpServiceImpl implements WxMpService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
|
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
|
||||||
if (forceRefresh) {
|
Lock lock = configStorage.getJsapiTicketLock();
|
||||||
this.configStorage.expireJsapiTicket();
|
try {
|
||||||
}
|
lock.lock();
|
||||||
|
|
||||||
if (this.configStorage.isJsapiTicketExpired()) {
|
if (forceRefresh) {
|
||||||
synchronized (this.globalJsapiTicketRefreshLock) {
|
this.configStorage.expireJsapiTicket();
|
||||||
if (this.configStorage.isJsapiTicketExpired()) {
|
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
|
|
||||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
|
||||||
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
|
|
||||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
|
||||||
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
|
|
||||||
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
|
||||||
this.configStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.configStorage.isJsapiTicketExpired()) {
|
||||||
|
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
|
||||||
|
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||||
|
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
|
||||||
|
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
||||||
|
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
|
||||||
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
||||||
|
this.configStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
}
|
}
|
||||||
return this.configStorage.getJsapiTicket();
|
return this.configStorage.getJsapiTicket();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user