mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-04-05 17:38:05 +08:00
🎨 #2000 【企业微信】第三方应用增加基于分布式并发锁获取各种token和ticket的版本
This commit is contained in:
parent
3bb918d125
commit
9d3c11f552
@ -2,8 +2,10 @@ package me.chanjar.weixin.cp.config;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||
import me.chanjar.weixin.cp.bean.WxCpProviderToken;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* 微信客户端(第三方应用)配置存储
|
||||
@ -30,6 +32,11 @@ public interface WxCpTpConfigStorage {
|
||||
* 第三方应用的suite access token相关
|
||||
*/
|
||||
String getSuiteAccessToken();
|
||||
/**
|
||||
* 获取suite_access_token和剩余过期时间
|
||||
* @return suite access token and the remaining expiration time
|
||||
*/
|
||||
WxAccessToken getSuiteAccessTokenEntity();
|
||||
boolean isSuiteAccessTokenExpired();
|
||||
//强制将suite access token过期掉.
|
||||
void expireSuiteAccessToken();
|
||||
@ -71,7 +78,9 @@ public interface WxCpTpConfigStorage {
|
||||
* 授权企业的access token相关
|
||||
*/
|
||||
String getAccessToken(String authCorpId);
|
||||
WxAccessToken getAccessTokenEntity(String authCorpId);
|
||||
boolean isAccessTokenExpired(String authCorpId);
|
||||
void expireAccessToken(String authCorpId);
|
||||
void updateAccessToken(String authCorpId, String accessToken, int expiredInSeconds);
|
||||
|
||||
/**
|
||||
@ -79,6 +88,7 @@ public interface WxCpTpConfigStorage {
|
||||
*/
|
||||
String getAuthCorpJsApiTicket(String authCorpId);
|
||||
boolean isAuthCorpJsApiTicketExpired(String authCorpId);
|
||||
void expireAuthCorpJsApiTicket(String authCorpId);
|
||||
void updateAuthCorpJsApiTicket(String authCorpId, String jsApiTicket, int expiredInSeconds);
|
||||
|
||||
/**
|
||||
@ -86,12 +96,16 @@ public interface WxCpTpConfigStorage {
|
||||
*/
|
||||
String getAuthSuiteJsApiTicket(String authCorpId);
|
||||
boolean isAuthSuiteJsApiTicketExpired(String authCorpId);
|
||||
void expireAuthSuiteJsApiTicket(String authCorpId);
|
||||
void updateAuthSuiteJsApiTicket(String authCorpId, String jsApiTicket, int expiredInSeconds);;
|
||||
|
||||
boolean isProviderTokenExpired();
|
||||
void updateProviderToken(String providerToken, int expiredInSeconds);
|
||||
|
||||
String getProviderToken();
|
||||
WxCpProviderToken getProviderTokenEntity();
|
||||
// 强制过期
|
||||
void expireProviderToken();
|
||||
|
||||
/**
|
||||
* 网络代理相关
|
||||
@ -108,4 +122,9 @@ public interface WxCpTpConfigStorage {
|
||||
@Deprecated
|
||||
File getTmpDirFile();
|
||||
|
||||
Lock getProviderAccessTokenLock();
|
||||
Lock getSuiteAccessTokenLock();
|
||||
Lock getAccessTokenLock(String authCorpId);
|
||||
Lock getAuthCorpJsapiTicketLock(String authCorpId);
|
||||
Lock getSuiteJsapiTicketLock(String authCorpId);
|
||||
}
|
||||
|
@ -2,13 +2,18 @@ package me.chanjar.weixin.cp.config.impl;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||
import me.chanjar.weixin.cp.bean.WxCpProviderToken;
|
||||
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
|
||||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化.
|
||||
@ -59,6 +64,12 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
|
||||
private volatile String baseApiUrl;
|
||||
|
||||
// locker
|
||||
private final transient Map<String, Lock> providerAccessTokenLocker = new ConcurrentHashMap<>();
|
||||
private final transient Map<String, Lock> suiteAccessTokenLocker = new ConcurrentHashMap<>();
|
||||
private final transient Map<String, Lock> accessTokenLocker = new ConcurrentHashMap<>();
|
||||
private final transient Map<String, Lock> authCorpJsapiTicketLocker = new ConcurrentHashMap<>();
|
||||
private final transient Map<String, Lock> authSuiteJsapiTicketLocker = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void setBaseApiUrl(String baseUrl) {
|
||||
@ -78,6 +89,15 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
return this.suiteAccessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getSuiteAccessTokenEntity() {
|
||||
WxAccessToken accessToken = new WxAccessToken();
|
||||
int expiresIn = Math.toIntExact((this.suiteAccessTokenExpiresTime - System.currentTimeMillis()) / 1000L);
|
||||
accessToken.setExpiresIn(expiresIn <= 0 ? -1 : expiresIn);
|
||||
accessToken.setAccessToken(this.suiteAccessToken);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setSuiteAccessToken(String suiteAccessToken) {
|
||||
this.suiteAccessToken = suiteAccessToken;
|
||||
}
|
||||
@ -218,12 +238,28 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
return authCorpAccessTokenMap.get(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getAccessTokenEntity(String authCorpId) {
|
||||
String accessToken = authCorpAccessTokenMap.getOrDefault(authCorpId, StringUtils.EMPTY);
|
||||
Long expire = authCorpAccessTokenExpireTimeMap.getOrDefault(authCorpId, 0L);
|
||||
WxAccessToken accessTokenEntity = new WxAccessToken();
|
||||
accessTokenEntity.setAccessToken(accessToken);
|
||||
accessTokenEntity.setExpiresIn(Math.toIntExact(expire));
|
||||
return accessTokenEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccessTokenExpired(String authCorpId) {
|
||||
return System.currentTimeMillis() > authCorpAccessTokenExpireTimeMap.get(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void expireAccessToken(String authCorpId) {
|
||||
authCorpAccessTokenMap.remove(authCorpId);
|
||||
authCorpAccessTokenExpireTimeMap.remove(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAccessToken(String authCorpId, String accessToken, int expiredInSeconds) {
|
||||
authCorpAccessTokenMap.put(authCorpId, accessToken);
|
||||
// 预留200秒的时间
|
||||
@ -246,6 +282,12 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireAuthCorpJsApiTicket(String authCorpId) {
|
||||
this.authCorpJsApiTicketMap.remove(authCorpId);
|
||||
this.authCorpJsApiTicketExpireTimeMap.remove(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuthCorpJsApiTicket(String authCorpId, String jsApiTicket, int expiredInSeconds) {
|
||||
// 应该根据不同的授权企业做区分
|
||||
@ -269,6 +311,12 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireAuthSuiteJsApiTicket(String authCorpId) {
|
||||
this.authSuiteJsApiTicketMap.remove(authCorpId);
|
||||
this.authSuiteJsApiTicketExpireTimeMap.remove(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuthSuiteJsApiTicket(String authCorpId, String jsApiTicket, int expiredInSeconds) {
|
||||
// 应该根据不同的授权企业做区分
|
||||
@ -293,6 +341,16 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
return providerToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpProviderToken getProviderTokenEntity() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireProviderToken() {
|
||||
this.providerTokenExpiresTime = 0L;
|
||||
}
|
||||
|
||||
public void setOauth2redirectUri(String oauth2redirectUri) {
|
||||
this.oauth2redirectUri = oauth2redirectUri;
|
||||
}
|
||||
@ -343,6 +401,35 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
|
||||
return this.tmpDirFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getProviderAccessTokenLock() {
|
||||
return this.providerAccessTokenLocker
|
||||
.computeIfAbsent(String.join(":", this.suiteId, this.corpId), key -> new ReentrantLock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getSuiteAccessTokenLock() {
|
||||
return this.suiteAccessTokenLocker.computeIfAbsent(this.suiteId, key -> new ReentrantLock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getAccessTokenLock(String authCorpId) {
|
||||
return this.accessTokenLocker
|
||||
.computeIfAbsent(String.join(":", this.suiteId, authCorpId), key -> new ReentrantLock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getAuthCorpJsapiTicketLock(String authCorpId) {
|
||||
return this.authCorpJsapiTicketLocker
|
||||
.computeIfAbsent(String.join(":", this.suiteId, authCorpId), key -> new ReentrantLock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getSuiteJsapiTicketLock(String authCorpId) {
|
||||
return this.authSuiteJsapiTicketLocker
|
||||
.computeIfAbsent(String.join(":", this.suiteId, authCorpId), key -> new ReentrantLock());
|
||||
}
|
||||
|
||||
public void setTmpDirFile(File tmpDirFile) {
|
||||
this.tmpDirFile = tmpDirFile;
|
||||
}
|
||||
|
@ -6,12 +6,15 @@ import lombok.NonNull;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.redis.WxRedisOps;
|
||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||
import me.chanjar.weixin.cp.bean.WxCpProviderToken;
|
||||
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
|
||||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* 企业微信各种固定、授权配置的Redisson存储实现
|
||||
@ -66,6 +69,14 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
*/
|
||||
private volatile String providerSecret;
|
||||
|
||||
// lock key
|
||||
protected static final String LOCK_KEY = "wechat_tp_lock:";
|
||||
protected static final String LOCKER_PROVIDER_ACCESS_TOKEN = "providerAccessTokenLock";
|
||||
protected static final String LOCKER_SUITE_ACCESS_TOKEN = "suiteAccessTokenLock";
|
||||
protected static final String LOCKER_ACCESS_TOKEN = "accessTokenLock";
|
||||
protected static final String LOCKER_CORP_JSAPI_TICKET = "corpJsapiTicketLock";
|
||||
protected static final String LOCKER_SUITE_JSAPI_TICKET = "suiteJsapiTicketLock";
|
||||
|
||||
@Override
|
||||
public void setBaseApiUrl(String baseUrl) {
|
||||
this.baseApiUrl = baseUrl;
|
||||
@ -88,6 +99,20 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
return wxRedisOps.getValue(keyWithPrefix(suiteAccessTokenKey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getSuiteAccessTokenEntity() {
|
||||
String suiteAccessToken = wxRedisOps.getValue(keyWithPrefix(suiteAccessTokenKey));
|
||||
Long expireIn = wxRedisOps.getExpire(keyWithPrefix(suiteAccessTokenKey));
|
||||
if (StringUtils.isBlank(suiteAccessToken) || expireIn == null || expireIn == 0 || expireIn == -2) {
|
||||
return new WxAccessToken();
|
||||
}
|
||||
|
||||
WxAccessToken suiteAccessTokenEntity = new WxAccessToken();
|
||||
suiteAccessTokenEntity.setAccessToken(suiteAccessToken);
|
||||
suiteAccessTokenEntity.setExpiresIn(Math.max(Math.toIntExact(expireIn), 0));
|
||||
return suiteAccessTokenEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuiteAccessTokenExpired() {
|
||||
//remain time to live in seconds, or key not exist
|
||||
@ -185,6 +210,20 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
return wxRedisOps.getValue(keyWithPrefix(authCorpId) + accessTokenKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getAccessTokenEntity(String authCorpId) {
|
||||
String accessToken = wxRedisOps.getValue(keyWithPrefix(authCorpId) + accessTokenKey);
|
||||
Long expire = wxRedisOps.getExpire(keyWithPrefix(authCorpId) + accessTokenKey);
|
||||
if (StringUtils.isBlank(accessToken) || expire == null || expire == 0 || expire == -2) {
|
||||
return new WxAccessToken();
|
||||
}
|
||||
|
||||
WxAccessToken accessTokenEntity = new WxAccessToken();
|
||||
accessTokenEntity.setAccessToken(accessToken);
|
||||
accessTokenEntity.setExpiresIn(Math.max(Math.toIntExact(expire), 0));
|
||||
return accessTokenEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccessTokenExpired(String authCorpId) {
|
||||
//没有设置或者TTL为0,都是过期
|
||||
@ -192,6 +231,11 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
|| wxRedisOps.getExpire(keyWithPrefix(authCorpId) + accessTokenKey) == -2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireAccessToken(String authCorpId) {
|
||||
wxRedisOps.expire(keyWithPrefix(authCorpId) + accessTokenKey, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAccessToken(String authCorpId, String accessToken, int expiredInSeconds) {
|
||||
wxRedisOps.setValue(keyWithPrefix(authCorpId) + accessTokenKey, accessToken, expiredInSeconds, TimeUnit.SECONDS);
|
||||
@ -213,6 +257,11 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
|| wxRedisOps.getExpire(keyWithPrefix(authCorpId) + authCorpJsApiTicketKey) == -2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireAuthCorpJsApiTicket(String authCorpId) {
|
||||
wxRedisOps.expire(keyWithPrefix(authCorpId) + authCorpJsApiTicketKey, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuthCorpJsApiTicket(String authCorpId, String jsApiTicket, int expiredInSeconds) {
|
||||
wxRedisOps.setValue(keyWithPrefix(authCorpId) + authCorpJsApiTicketKey, jsApiTicket, expiredInSeconds,
|
||||
@ -235,6 +284,11 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
|| wxRedisOps.getExpire(keyWithPrefix(authCorpId) + authSuiteJsApiTicketKey) == -2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireAuthSuiteJsApiTicket(String authCorpId) {
|
||||
wxRedisOps.expire(keyWithPrefix(authCorpId) + authSuiteJsApiTicketKey, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuthSuiteJsApiTicket(String authCorpId, String jsApiTicket, int expiredInSeconds) {
|
||||
wxRedisOps.setValue(keyWithPrefix(authCorpId) + authSuiteJsApiTicketKey, jsApiTicket, expiredInSeconds,
|
||||
@ -257,6 +311,25 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
return wxRedisOps.getValue(keyWithPrefix(providerTokenKey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpProviderToken getProviderTokenEntity() {
|
||||
String providerToken = wxRedisOps.getValue(keyWithPrefix(providerTokenKey));
|
||||
Long expire = wxRedisOps.getExpire(keyWithPrefix(providerTokenKey));
|
||||
|
||||
if (StringUtils.isBlank(providerToken) || expire == null || expire == 0 || expire == -2) {
|
||||
return new WxCpProviderToken();
|
||||
}
|
||||
|
||||
WxCpProviderToken wxCpProviderToken = new WxCpProviderToken();
|
||||
wxCpProviderToken.setProviderAccessToken(providerToken);
|
||||
wxCpProviderToken.setExpiresIn(Math.max(Math.toIntExact(expire), 0));
|
||||
return wxCpProviderToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireProviderToken() {
|
||||
wxRedisOps.expire(keyWithPrefix(providerTokenKey), 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络代理相关
|
||||
@ -286,6 +359,37 @@ public class WxCpTpRedissonConfigImpl implements WxCpTpConfigStorage, Serializab
|
||||
return tmpDirFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getProviderAccessTokenLock() {
|
||||
return getLockByKey(String.join(":", this.corpId, LOCKER_PROVIDER_ACCESS_TOKEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getSuiteAccessTokenLock() {
|
||||
return getLockByKey(LOCKER_SUITE_ACCESS_TOKEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getAccessTokenLock(String authCorpId) {
|
||||
return getLockByKey(String.join(":", authCorpId, LOCKER_ACCESS_TOKEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getAuthCorpJsapiTicketLock(String authCorpId) {
|
||||
return getLockByKey(String.join(":", authCorpId, LOCKER_CORP_JSAPI_TICKET));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getSuiteJsapiTicketLock(String authCorpId) {
|
||||
return getLockByKey(String.join(":", authCorpId, LOCKER_SUITE_JSAPI_TICKET));
|
||||
}
|
||||
|
||||
private Lock getLockByKey(String key) {
|
||||
// 最终key的模式:(keyPrefix:)wechat_tp_lock:suiteId:(authCorpId):lockKey
|
||||
// 其中keyPrefix目前不支持外部配置,authCorpId只有涉及到corpAccessToken, suiteJsapiTicket, authCorpJsapiTicket时才会拼上
|
||||
return this.wxRedisOps.getLock(String.join(":", keyWithPrefix(LOCK_KEY + this.suiteId), key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder getApacheHttpClientBuilder() {
|
||||
return this.apacheHttpClientBuilder;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.chanjar.weixin.cp.tp.service;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.bean.WxJsapiSignature;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
|
||||
@ -53,6 +54,20 @@ public interface WxCpTpService {
|
||||
*/
|
||||
String getSuiteAccessToken(boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取suite_access_token和剩余过期时间, 不强制刷新suite_access_token
|
||||
* @return suite access token and the remaining expiration time
|
||||
*/
|
||||
WxAccessToken getSuiteAccessTokenEntity() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取suite_access_token和剩余过期时间, 支持强制刷新suite_access_token
|
||||
* @param forceRefresh 是否调用微信服务器强制刷新token
|
||||
* @return suite access token and the remaining expiration time
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
WxAccessToken getSuiteAccessTokenEntity(boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获得suite_ticket,不强制刷新suite_ticket
|
||||
*
|
||||
@ -115,6 +130,15 @@ public interface WxCpTpService {
|
||||
*/
|
||||
String getSuiteJsApiTicket(String authCorpId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取应用的 jsapi ticket, 支持强制刷新
|
||||
* @param authCorpId
|
||||
* @param forceRefresh
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
String getSuiteJsApiTicket(String authCorpId, boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 小程序登录凭证校验
|
||||
*
|
||||
@ -134,6 +158,16 @@ public interface WxCpTpService {
|
||||
*/
|
||||
WxAccessToken getCorpToken(String authCorpId, String permanentCode) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取企业凭证, 支持强制刷新
|
||||
* @param authCorpId
|
||||
* @param permanentCode
|
||||
* @param forceRefresh
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
WxAccessToken getCorpToken(String authCorpId, String permanentCode, boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取企业永久授权码 .
|
||||
*
|
||||
@ -173,13 +207,13 @@ public interface WxCpTpService {
|
||||
/**
|
||||
* <pre>
|
||||
* 获取预授权链接,测试环境下使用
|
||||
* </pre>
|
||||
* @param redirectUri 授权完成后的回调网址
|
||||
* @param state a-zA-Z0-9的参数值(不超过128个字节),用于第三方自行校验session,防止跨域攻击
|
||||
* @param authType 授权类型:0 正式授权, 1 测试授权。
|
||||
* @return pre auth url
|
||||
* @throws WxErrorException the wx error exception
|
||||
* @link https ://work.weixin.qq.com/api/doc/90001/90143/90602
|
||||
* </pre>
|
||||
*/
|
||||
String getPreAuthUrl(String redirectUri, String state, int authType) throws WxErrorException;
|
||||
|
||||
@ -202,6 +236,15 @@ public interface WxCpTpService {
|
||||
*/
|
||||
String getAuthCorpJsApiTicket(String authCorpId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取授权企业的 jsapi ticket, 支持强制刷新
|
||||
* @param authCorpId
|
||||
* @param forceRefresh
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
String getAuthCorpJsApiTicket(String authCorpId, boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求.
|
||||
*
|
||||
@ -335,6 +378,21 @@ public interface WxCpTpService {
|
||||
*/
|
||||
String getWxCpProviderToken() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取服务商providerToken和剩余过期时间
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
WxCpProviderToken getWxCpProviderTokenEntity() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取服务商providerToken和剩余过期时间,支持强制刷新
|
||||
* @param forceRefresh
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
WxCpProviderToken getWxCpProviderTokenEntity(boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* get contact service
|
||||
*
|
||||
@ -415,4 +473,22 @@ public interface WxCpTpService {
|
||||
*/
|
||||
WxCpTpAdmin getAdminList(String authCorpId, Integer agentId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 创建机构级jsApiTicket签名
|
||||
* 详情参见企业微信第三方应用开发文档:https://work.weixin.qq.com/api/doc/90001/90144/90539
|
||||
* @param url 调用JS接口页面的完整URL
|
||||
* @param authCorpId
|
||||
* @return
|
||||
*/
|
||||
WxJsapiSignature createAuthCorpJsApiTicketSignature(String url, String authCorpId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 创建应用级jsapiTicket签名
|
||||
* 详情参见企业微信第三方应用开发文档:https://work.weixin.qq.com/api/doc/90001/90144/90539
|
||||
* @param url 调用JS接口页面的完整URL
|
||||
* @param authCorpId
|
||||
* @return
|
||||
*/
|
||||
WxJsapiSignature createSuiteJsApiTicketSignature(String url, String authCorpId) throws WxErrorException;
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.google.gson.JsonObject;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.bean.WxJsapiSignature;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxCpErrorMsgEnum;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
@ -14,6 +15,7 @@ import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
import me.chanjar.weixin.common.session.StandardSessionManager;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.common.util.DataUtils;
|
||||
import me.chanjar.weixin.common.util.RandomUtils;
|
||||
import me.chanjar.weixin.common.util.crypto.SHA1;
|
||||
import me.chanjar.weixin.common.util.http.RequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
@ -97,6 +99,17 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
|
||||
return getSuiteAccessToken(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getSuiteAccessTokenEntity() throws WxErrorException {
|
||||
return this.getSuiteAccessTokenEntity(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getSuiteAccessTokenEntity(boolean forceRefresh) throws WxErrorException {
|
||||
getSuiteAccessToken(forceRefresh);
|
||||
return this.configStorage.getSuiteAccessTokenEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSuiteTicket() throws WxErrorException {
|
||||
if (this.configStorage.isSuiteTicketExpired()) {
|
||||
@ -150,6 +163,14 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
|
||||
return configStorage.getAuthSuiteJsApiTicket(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSuiteJsApiTicket(String authCorpId, boolean forceRefresh) throws WxErrorException {
|
||||
if (forceRefresh) {
|
||||
this.configStorage.expireAuthSuiteJsApiTicket(authCorpId);
|
||||
}
|
||||
return this.getSuiteJsApiTicket(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthCorpJsApiTicket(String authCorpId) throws WxErrorException {
|
||||
if (this.configStorage.isAuthCorpJsApiTicketExpired(authCorpId)) {
|
||||
@ -169,7 +190,15 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
|
||||
throw new WxErrorException(WxError.fromJson(resp));
|
||||
}
|
||||
}
|
||||
return configStorage.getProviderToken();
|
||||
return configStorage.getAuthCorpJsApiTicket(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthCorpJsApiTicket(String authCorpId, boolean forceRefresh) throws WxErrorException {
|
||||
if (forceRefresh) {
|
||||
this.configStorage.expireAuthCorpJsApiTicket(authCorpId);
|
||||
}
|
||||
return this.getAuthCorpJsApiTicket(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -193,6 +222,16 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
|
||||
return WxAccessToken.fromJson(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getCorpToken(String authCorpId, String permanentCode, boolean forceRefresh)
|
||||
throws WxErrorException {
|
||||
if (this.configStorage.isAccessTokenExpired(authCorpId) || forceRefresh) {
|
||||
WxAccessToken corpToken = this.getCorpToken(authCorpId, permanentCode);
|
||||
this.configStorage.updateAccessToken(authCorpId, corpToken.getAccessToken(), corpToken.getExpiresIn());
|
||||
}
|
||||
return this.configStorage.getAccessTokenEntity(authCorpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpTpCorp getPermanentCode(String authCode) throws WxErrorException {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
@ -426,6 +465,19 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
|
||||
return configStorage.getProviderToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpProviderToken getWxCpProviderTokenEntity() throws WxErrorException {
|
||||
return this.getWxCpProviderTokenEntity(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpProviderToken getWxCpProviderTokenEntity(boolean forceRefresh) throws WxErrorException {
|
||||
if (forceRefresh) {
|
||||
this.configStorage.expireProviderToken();
|
||||
}
|
||||
this.getWxCpProviderToken();
|
||||
return this.configStorage.getProviderTokenEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpTpContactService getWxCpTpContactService() {
|
||||
@ -486,4 +538,30 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
|
||||
return WxCpTpAdmin.fromJson(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxJsapiSignature createAuthCorpJsApiTicketSignature(String url, String authCorpId) throws WxErrorException {
|
||||
return doCreateWxJsapiSignature(url, authCorpId, this.getAuthCorpJsApiTicket(authCorpId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxJsapiSignature createSuiteJsApiTicketSignature(String url, String authCorpId) throws WxErrorException {
|
||||
return doCreateWxJsapiSignature(url, authCorpId, this.getSuiteJsApiTicket(authCorpId));
|
||||
}
|
||||
|
||||
private WxJsapiSignature doCreateWxJsapiSignature(String url, String authCorpId, String jsapiTicket) {
|
||||
long timestamp = System.currentTimeMillis() / 1000;
|
||||
String noncestr = RandomUtils.getRandomStr();
|
||||
String signature = SHA1
|
||||
.genWithAmple("jsapi_ticket=" + jsapiTicket, "noncestr=" + noncestr, "timestamp=" + timestamp,
|
||||
"url=" + url);
|
||||
WxJsapiSignature jsapiSignature = new WxJsapiSignature();
|
||||
jsapiSignature.setTimestamp(timestamp);
|
||||
jsapiSignature.setNonceStr(noncestr);
|
||||
jsapiSignature.setUrl(url);
|
||||
jsapiSignature.setSignature(signature);
|
||||
jsapiSignature.setAppId(authCorpId);
|
||||
|
||||
return jsapiSignature;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,169 @@
|
||||
package me.chanjar.weixin.cp.tp.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.cp.bean.WxCpProviderToken;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 默认接口实现类,使用apache httpclient实现
|
||||
* Created by zhenjun cai.
|
||||
* </pre>
|
||||
* <pre>
|
||||
* 实现分布式锁(基于WxCpTpRedissonConfigImpl存储引擎实现类)版本;
|
||||
* 主要封装了suiteAccessToken,corpAccessToken,suiteJsapiTicket,corpJsapiTicket等的获取方法
|
||||
* Updated by zhangq <zhangq002@gmail.com> on 2021-02-13
|
||||
* </pre>
|
||||
*
|
||||
* @author zhenjun cai
|
||||
* @author zhangq
|
||||
*/
|
||||
@Slf4j
|
||||
public class WxCpTpServiceImpl extends WxCpTpServiceApacheHttpClientImpl {
|
||||
|
||||
@Override
|
||||
public WxAccessToken getSuiteAccessTokenEntity() throws WxErrorException {
|
||||
return this.getSuiteAccessTokenEntity(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getSuiteAccessTokenEntity(boolean forceRefresh) throws WxErrorException {
|
||||
if (!this.configStorage.isSuiteAccessTokenExpired() && !forceRefresh) {
|
||||
return this.configStorage.getSuiteAccessTokenEntity();
|
||||
}
|
||||
|
||||
// 此处configStorage推荐使用WxCpTpRedissonConfigImpl实现类,
|
||||
// 它底层采用了redisson提供的并发锁,会自动续期,无需担心异常中断导致的死锁问题,以及锁提前释放导致的并发问题
|
||||
Lock lock = this.configStorage.getSuiteAccessTokenLock();
|
||||
lock.lock();
|
||||
try {
|
||||
if (!this.configStorage.isSuiteAccessTokenExpired() && !forceRefresh) {
|
||||
return this.configStorage.getSuiteAccessTokenEntity();
|
||||
}
|
||||
|
||||
super.getSuiteAccessToken(forceRefresh);
|
||||
return this.configStorage.getSuiteAccessTokenEntity();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复写父类方法,使其支持并发锁模式
|
||||
* @param forceRefresh
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
@Override
|
||||
public String getSuiteAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
WxAccessToken suiteToken = this.getSuiteAccessTokenEntity(forceRefresh);
|
||||
return suiteToken.getAccessToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpProviderToken getWxCpProviderTokenEntity() throws WxErrorException {
|
||||
return this.getWxCpProviderTokenEntity(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpProviderToken getWxCpProviderTokenEntity(boolean forceRefresh) throws WxErrorException {
|
||||
if (!this.configStorage.isProviderTokenExpired() && !forceRefresh) {
|
||||
return this.configStorage.getProviderTokenEntity();
|
||||
}
|
||||
|
||||
Lock lock = this.configStorage.getProviderAccessTokenLock();
|
||||
lock.lock();
|
||||
try {
|
||||
if (!this.configStorage.isProviderTokenExpired() && !forceRefresh) {
|
||||
return this.configStorage.getProviderTokenEntity();
|
||||
}
|
||||
|
||||
return super.getWxCpProviderTokenEntity(forceRefresh);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getCorpToken(String authCorpId, String permanentCode) throws WxErrorException {
|
||||
return this.getCorpToken(authCorpId, permanentCode, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxAccessToken getCorpToken(String authCorpId, String permanentCode, boolean forceRefresh)
|
||||
throws WxErrorException {
|
||||
if (!this.configStorage.isAccessTokenExpired(authCorpId) && !forceRefresh) {
|
||||
return this.configStorage.getAccessTokenEntity(authCorpId);
|
||||
}
|
||||
|
||||
Lock lock = this.configStorage.getAccessTokenLock(authCorpId);
|
||||
lock.lock();
|
||||
try {
|
||||
if (!this.configStorage.isAccessTokenExpired(authCorpId) && !forceRefresh) {
|
||||
return this.configStorage.getAccessTokenEntity(authCorpId);
|
||||
}
|
||||
|
||||
WxAccessToken accessToken = super.getCorpToken(authCorpId, permanentCode);
|
||||
this.configStorage.updateAccessToken(authCorpId, accessToken.getAccessToken(), accessToken.getExpiresIn());
|
||||
return accessToken;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthCorpJsApiTicket(String authCorpId) throws WxErrorException {
|
||||
return this.getAuthCorpJsApiTicket(authCorpId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthCorpJsApiTicket(String authCorpId, boolean forceRefresh) throws WxErrorException {
|
||||
if (!this.configStorage.isAuthCorpJsApiTicketExpired(authCorpId) && !forceRefresh) {
|
||||
return this.configStorage.getAuthCorpJsApiTicket(authCorpId);
|
||||
}
|
||||
|
||||
Lock lock = this.configStorage.getAuthCorpJsapiTicketLock(authCorpId);
|
||||
lock.lock();
|
||||
try {
|
||||
if (!this.configStorage.isAuthCorpJsApiTicketExpired(authCorpId) && !forceRefresh) {
|
||||
return this.configStorage.getAuthCorpJsApiTicket(authCorpId);
|
||||
}
|
||||
if (forceRefresh) {
|
||||
this.configStorage.expireAuthCorpJsApiTicket(authCorpId);
|
||||
}
|
||||
return super.getAuthCorpJsApiTicket(authCorpId);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSuiteJsApiTicket(String authCorpId) throws WxErrorException {
|
||||
return this.getSuiteJsApiTicket(authCorpId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSuiteJsApiTicket(String authCorpId, boolean forceRefresh) throws WxErrorException {
|
||||
if (!this.configStorage.isAuthSuiteJsApiTicketExpired(authCorpId) && !forceRefresh) {
|
||||
return this.configStorage.getAuthSuiteJsApiTicket(authCorpId);
|
||||
}
|
||||
|
||||
Lock lock = this.configStorage.getSuiteJsapiTicketLock(authCorpId);
|
||||
lock.lock();
|
||||
try {
|
||||
if (!this.configStorage.isAuthSuiteJsApiTicketExpired(authCorpId) && !forceRefresh) {
|
||||
return this.configStorage.getAuthSuiteJsApiTicket(authCorpId);
|
||||
}
|
||||
if (forceRefresh) {
|
||||
this.configStorage.expireAuthSuiteJsApiTicket(authCorpId);
|
||||
}
|
||||
return super.getSuiteJsApiTicket(authCorpId);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
package me.chanjar.weixin.cp.config.impl;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class WxCpTpDefaultConfigImplTest {
|
||||
|
||||
@Test
|
||||
public void testGetSuiteAccessTokenEntity() throws InterruptedException {
|
||||
final String testAccessToken = "5O_32IEDOib99RliaF301vzGiZaAJw3CsaNb4QXyQ-07KJ0UDQ8nxq9vs66jNLIZ4TvYs3QFlYZag1WfG8i4gNu_dYQj2Ff89xznZPquv7EFMAZha_faYZrE0uCFRqkV";
|
||||
final long testExpireTime = 7200L;
|
||||
final long restTime = 10L;
|
||||
WxCpTpDefaultConfigImpl storage = new WxCpTpDefaultConfigImpl();
|
||||
storage.setSuiteAccessToken(testAccessToken);
|
||||
storage.setSuiteAccessTokenExpiresTime(System.currentTimeMillis() + (testExpireTime - 200) * 1000L);
|
||||
TimeUnit.SECONDS.sleep(restTime);
|
||||
WxAccessToken accessToken = storage.getSuiteAccessTokenEntity();
|
||||
Assert.assertEquals(accessToken.getAccessToken(), testAccessToken, "accessToken不一致");
|
||||
Assert.assertTrue(accessToken.getExpiresIn() <= testExpireTime - restTime, "过期时间计算有误");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package me.chanjar.weixin.cp.tp.service.impl;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.redis.RedissonWxRedisOps;
|
||||
import me.chanjar.weixin.cp.bean.WxCpProviderToken;
|
||||
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
|
||||
import me.chanjar.weixin.cp.config.impl.WxCpTpRedissonConfigImpl;
|
||||
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.redisson.Redisson;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.redisson.config.Config;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* 测试用参数请在自己的企业微信第三方开发者后台查找匹配
|
||||
* 如果测试不过,请检查redis中是否存在微信定期推送的suite_ticket
|
||||
*
|
||||
* @author zhangq <zhangq002@gmail.com>
|
||||
*/
|
||||
public class WxCpTpServiceImplTest {
|
||||
|
||||
public static final String API_URL = "https://qyapi.weixin.qq.com";
|
||||
public static final String SUITE_ID = "xxxxxx";
|
||||
public static final String SUITE_SECRET = "xxxxxx";
|
||||
public static final String TOKEN = "xxxxxx";
|
||||
public static final String AES_KEY = "xxxxxx";
|
||||
public static final String PROVIDER_CORP_ID = "xxxxxx";
|
||||
public static final String CORP_SECRET = "xxxxxx";
|
||||
public static final String PROVIDER_SECRET = CORP_SECRET;
|
||||
public static final String REDIS_ADDR = "redis://xxx.xxx.xxx.xxx:6379";
|
||||
public static final String REDIS_PASSWD = "xxxxxx";
|
||||
|
||||
private static final String AUTH_CORP_ID = "xxxxxx";
|
||||
private static final String PERMANENT_CODE = "xxxxxx";
|
||||
|
||||
private WxCpTpService wxCpTpService;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
wxCpTpService = new WxCpTpServiceImpl();
|
||||
wxCpTpService.setWxCpTpConfigStorage(wxCpTpConfigStorage());
|
||||
}
|
||||
|
||||
public WxCpTpConfigStorage wxCpTpConfigStorage() {
|
||||
return WxCpTpRedissonConfigImpl.builder().baseApiUrl(API_URL).suiteId(SUITE_ID).suiteSecret(SUITE_SECRET)
|
||||
.token(TOKEN).aesKey(AES_KEY).corpId(PROVIDER_CORP_ID).corpSecret(CORP_SECRET).providerSecret(PROVIDER_SECRET)
|
||||
.wxRedisOps(new RedissonWxRedisOps(redissonClient())).build();
|
||||
}
|
||||
|
||||
public RedissonClient redissonClient() {
|
||||
Config config = new Config();
|
||||
config.useSingleServer().setAddress(REDIS_ADDR).setConnectTimeout(10 * 1000).setDatabase(6)
|
||||
.setPassword(REDIS_PASSWD).setConnectionMinimumIdleSize(2).setConnectionPoolSize(2);
|
||||
return Redisson.create(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSuiteAccessTokenEntity() throws WxErrorException {
|
||||
wxCpTpService.getWxCpTpConfigStorage().expireSuiteAccessToken();
|
||||
WxAccessToken suiteAccessTokenEntity = wxCpTpService.getSuiteAccessTokenEntity(true);
|
||||
System.out.println("suiteAccessTokenEntity:" + suiteAccessTokenEntity);
|
||||
Assert.assertTrue(
|
||||
StringUtils.isNotBlank(suiteAccessTokenEntity.getAccessToken()) && suiteAccessTokenEntity.getExpiresIn() > 0);
|
||||
suiteAccessTokenEntity = wxCpTpService.getSuiteAccessTokenEntity();
|
||||
System.out.println("suiteAccessTokenEntity:" + suiteAccessTokenEntity);
|
||||
Assert.assertTrue(
|
||||
StringUtils.isNotBlank(suiteAccessTokenEntity.getAccessToken()) && suiteAccessTokenEntity.getExpiresIn() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWxCpProviderTokenEntity() throws WxErrorException {
|
||||
wxCpTpService.getWxCpTpConfigStorage().expireProviderToken();
|
||||
WxCpProviderToken providerToken = wxCpTpService.getWxCpProviderTokenEntity(true);
|
||||
System.out.println("providerToken:" + providerToken);
|
||||
Assert
|
||||
.assertTrue(StringUtils.isNotBlank(providerToken.getProviderAccessToken()) && providerToken.getExpiresIn() > 0);
|
||||
providerToken = wxCpTpService.getWxCpProviderTokenEntity();
|
||||
System.out.println("providerToken:" + providerToken);
|
||||
Assert
|
||||
.assertTrue(StringUtils.isNotBlank(providerToken.getProviderAccessToken()) && providerToken.getExpiresIn() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCorpToken() throws WxErrorException {
|
||||
wxCpTpService.getWxCpTpConfigStorage().expireAccessToken(AUTH_CORP_ID);
|
||||
WxAccessToken accessToken = wxCpTpService.getCorpToken(AUTH_CORP_ID, PERMANENT_CODE, true);
|
||||
System.out.println("accessToken:" + accessToken);
|
||||
accessToken = wxCpTpService.getCorpToken(AUTH_CORP_ID, PERMANENT_CODE);
|
||||
System.out.println("accessToken:" + accessToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAuthCorpJsApiTicket() throws WxErrorException {
|
||||
wxCpTpService.getWxCpTpConfigStorage().expireAuthCorpJsApiTicket(AUTH_CORP_ID);
|
||||
String authCorpJsApiTicket = wxCpTpService.getAuthCorpJsApiTicket(AUTH_CORP_ID, true);
|
||||
System.out.println("authCorpJsApiTicket:" + authCorpJsApiTicket);
|
||||
authCorpJsApiTicket = wxCpTpService.getAuthCorpJsApiTicket(AUTH_CORP_ID);
|
||||
System.out.println("authCorpJsApiTicket:" + authCorpJsApiTicket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSuiteJsApiTicket() throws WxErrorException {
|
||||
wxCpTpService.getWxCpTpConfigStorage().expireAuthSuiteJsApiTicket(AUTH_CORP_ID);
|
||||
String suiteJsApiTicket = wxCpTpService.getSuiteJsApiTicket(AUTH_CORP_ID, true);
|
||||
System.out.println("suiteJsApiTicket:" + suiteJsApiTicket);
|
||||
suiteJsApiTicket = wxCpTpService.getSuiteJsApiTicket(AUTH_CORP_ID);
|
||||
System.out.println("suiteJsApiTicket:" + suiteJsApiTicket);
|
||||
}
|
||||
}
|
@ -5,8 +5,9 @@
|
||||
<classes>
|
||||
<class name="me.chanjar.weixin.cp.api.WxCpBusyRetryTest"/>
|
||||
<class name="me.chanjar.weixin.cp.api.WxCpBaseAPITest"/>
|
||||
<class name="me.chanjar.weixin.cp.api.WxCpMessageAPITest"/>
|
||||
<class name="me.chanjar.weixin.cp.api.WxCpMessageRouterTest"/>
|
||||
<class name="me.chanjar.weixin.cp.tp.service.impl.WxCpTpServiceImplTest"/>
|
||||
<class name="me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImplTest"/>
|
||||
</classes>
|
||||
</test>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user