mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-08-24 07:23:01 +08:00
#844 整合优化ticket管理相关接口代码,方便获取sdk_ticket、jsapi_ticket和card_api_ticket等。
This commit is contained in:
parent
1cd06082aa
commit
49633cd123
@ -1,13 +1,14 @@
|
|||||||
package me.chanjar.weixin.mp.api;
|
package me.chanjar.weixin.mp.api;
|
||||||
|
|
||||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
|
||||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||||
|
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||||
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信客户端配置存储
|
* 微信客户端配置存储.
|
||||||
*
|
*
|
||||||
* @author chanjarster
|
* @author chanjarster
|
||||||
*/
|
*/
|
||||||
@ -20,62 +21,45 @@ public interface WxMpConfigStorage {
|
|||||||
boolean isAccessTokenExpired();
|
boolean isAccessTokenExpired();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 强制将access token过期掉
|
* 强制将access token过期掉.
|
||||||
*/
|
*/
|
||||||
void expireAccessToken();
|
void expireAccessToken();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应该是线程安全的
|
* 应该是线程安全的.
|
||||||
*
|
*
|
||||||
* @param accessToken 要更新的WxAccessToken对象
|
* @param accessToken 要更新的WxAccessToken对象
|
||||||
*/
|
*/
|
||||||
void updateAccessToken(WxAccessToken accessToken);
|
void updateAccessToken(WxAccessToken accessToken);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应该是线程安全的
|
* 应该是线程安全的.
|
||||||
*
|
*
|
||||||
* @param accessToken 新的accessToken值
|
* @param accessToken 新的accessToken值
|
||||||
* @param expiresInSeconds 过期时间,以秒为单位
|
* @param expiresInSeconds 过期时间,以秒为单位
|
||||||
*/
|
*/
|
||||||
void updateAccessToken(String accessToken, int expiresInSeconds);
|
void updateAccessToken(String accessToken, int expiresInSeconds);
|
||||||
|
|
||||||
String getJsapiTicket();
|
String getTicket(TicketType type);
|
||||||
|
|
||||||
Lock getJsapiTicketLock();
|
Lock getTicketLock(TicketType type);
|
||||||
|
|
||||||
boolean isJsapiTicketExpired();
|
boolean isTicketExpired(TicketType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 强制将jsapi ticket过期掉
|
* 强制将ticket过期掉.
|
||||||
*/
|
*/
|
||||||
void expireJsapiTicket();
|
void expireTicket(TicketType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 更新ticket.
|
||||||
* 应该是线程安全的
|
* 应该是线程安全的
|
||||||
*
|
*
|
||||||
* @param jsapiTicket 新的jsapi ticket值
|
* @param type ticket类型
|
||||||
|
* @param ticket 新的ticket值
|
||||||
* @param expiresInSeconds 过期时间,以秒为单位
|
* @param expiresInSeconds 过期时间,以秒为单位
|
||||||
*/
|
*/
|
||||||
void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);
|
void updateTicket(TicketType type, String ticket, int expiresInSeconds);
|
||||||
|
|
||||||
String getCardApiTicket();
|
|
||||||
|
|
||||||
Lock getCardApiTicketLock();
|
|
||||||
|
|
||||||
boolean isCardApiTicketExpired();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 强制将卡券api ticket过期掉
|
|
||||||
*/
|
|
||||||
void expireCardApiTicket();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 应该是线程安全的
|
|
||||||
*
|
|
||||||
* @param cardApiTicket 新的cardApi ticket值
|
|
||||||
* @param expiresInSeconds 过期时间,以秒为单位
|
|
||||||
*/
|
|
||||||
void updateCardApiTicket(String cardApiTicket, int expiresInSeconds);
|
|
||||||
|
|
||||||
String getAppId();
|
String getAppId();
|
||||||
|
|
||||||
@ -102,14 +86,14 @@ public interface WxMpConfigStorage {
|
|||||||
File getTmpDirFile();
|
File getTmpDirFile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http client builder
|
* http client builder.
|
||||||
*
|
*
|
||||||
* @return ApacheHttpClientBuilder
|
* @return ApacheHttpClientBuilder
|
||||||
*/
|
*/
|
||||||
ApacheHttpClientBuilder getApacheHttpClientBuilder();
|
ApacheHttpClientBuilder getApacheHttpClientBuilder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否自动刷新token
|
* 是否自动刷新token.
|
||||||
*/
|
*/
|
||||||
boolean autoRefreshToken();
|
boolean autoRefreshToken();
|
||||||
|
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
package me.chanjar.weixin.mp.api;
|
package me.chanjar.weixin.mp.api;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||||
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
|
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化.
|
||||||
*
|
*
|
||||||
* @author chanjarster
|
* @author chanjarster
|
||||||
*/
|
*/
|
||||||
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
@Data
|
||||||
|
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage, Serializable {
|
||||||
|
private static final long serialVersionUID = -6646519023303395185L;
|
||||||
|
|
||||||
protected volatile String appId;
|
protected volatile String appId;
|
||||||
protected volatile String secret;
|
protected volatile String secret;
|
||||||
@ -33,34 +38,21 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
protected volatile String jsapiTicket;
|
protected volatile String jsapiTicket;
|
||||||
protected volatile long jsapiTicketExpiresTime;
|
protected volatile long jsapiTicketExpiresTime;
|
||||||
|
|
||||||
|
protected volatile String sdkTicket;
|
||||||
|
protected volatile long sdkTicketExpiresTime;
|
||||||
|
|
||||||
protected volatile String cardApiTicket;
|
protected volatile String cardApiTicket;
|
||||||
protected volatile long cardApiTicketExpiresTime;
|
protected volatile long cardApiTicketExpiresTime;
|
||||||
|
|
||||||
protected Lock accessTokenLock = new ReentrantLock();
|
protected Lock accessTokenLock = new ReentrantLock();
|
||||||
protected Lock jsapiTicketLock = new ReentrantLock();
|
protected Lock jsapiTicketLock = new ReentrantLock();
|
||||||
|
protected Lock sdkTicketLock = new ReentrantLock();
|
||||||
protected Lock cardApiTicketLock = new ReentrantLock();
|
protected Lock cardApiTicketLock = new ReentrantLock();
|
||||||
|
|
||||||
/**
|
|
||||||
* 临时文件目录
|
|
||||||
*/
|
|
||||||
protected volatile File tmpDirFile;
|
protected volatile File tmpDirFile;
|
||||||
|
|
||||||
protected volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
|
protected volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAccessToken() {
|
|
||||||
return this.accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccessToken(String accessToken) {
|
|
||||||
this.accessToken = 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;
|
||||||
@ -83,167 +75,98 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getJsapiTicket() {
|
public String getTicket(TicketType type) {
|
||||||
return this.jsapiTicket;
|
switch (type) {
|
||||||
|
case SDK:
|
||||||
|
return this.sdkTicket;
|
||||||
|
case JSAPI:
|
||||||
|
return this.jsapiTicket;
|
||||||
|
case WX_CARD:
|
||||||
|
return this.cardApiTicket;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJsapiTicket(String jsapiTicket) {
|
public void setTicket(TicketType type, String ticket) {
|
||||||
this.jsapiTicket = jsapiTicket;
|
switch (type) {
|
||||||
|
case JSAPI:
|
||||||
|
this.jsapiTicket = ticket;
|
||||||
|
break;
|
||||||
|
case WX_CARD:
|
||||||
|
this.cardApiTicket = ticket;
|
||||||
|
break;
|
||||||
|
case SDK:
|
||||||
|
this.sdkTicket = ticket;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Lock getJsapiTicketLock() {
|
public Lock getTicketLock(TicketType type) {
|
||||||
return this.jsapiTicketLock;
|
switch (type) {
|
||||||
|
case SDK:
|
||||||
|
return this.sdkTicketLock;
|
||||||
|
case JSAPI:
|
||||||
|
return this.jsapiTicketLock;
|
||||||
|
case WX_CARD:
|
||||||
|
return this.cardApiTicketLock;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isJsapiTicketExpired() {
|
public boolean isTicketExpired(TicketType type) {
|
||||||
return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
|
switch (type) {
|
||||||
|
case SDK:
|
||||||
|
return System.currentTimeMillis() > this.sdkTicketExpiresTime;
|
||||||
|
case JSAPI:
|
||||||
|
return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
|
||||||
|
case WX_CARD:
|
||||||
|
return System.currentTimeMillis() > this.cardApiTicketExpiresTime;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
|
public synchronized void updateTicket(TicketType type, String ticket, int expiresInSeconds) {
|
||||||
this.jsapiTicket = jsapiTicket;
|
switch (type) {
|
||||||
// 预留200秒的时间
|
case JSAPI:
|
||||||
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
|
this.jsapiTicket = ticket;
|
||||||
|
// 预留200秒的时间
|
||||||
|
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
|
||||||
|
break;
|
||||||
|
case WX_CARD:
|
||||||
|
this.cardApiTicket = ticket;
|
||||||
|
// 预留200秒的时间
|
||||||
|
this.cardApiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
|
||||||
|
break;
|
||||||
|
case SDK:
|
||||||
|
this.sdkTicket = ticket;
|
||||||
|
// 预留200秒的时间
|
||||||
|
this.sdkTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void expireJsapiTicket() {
|
public void expireTicket(TicketType type) {
|
||||||
this.jsapiTicketExpiresTime = 0;
|
switch (type) {
|
||||||
}
|
case JSAPI:
|
||||||
|
this.jsapiTicketExpiresTime = 0;
|
||||||
/**
|
break;
|
||||||
* 卡券api_ticket
|
case WX_CARD:
|
||||||
*/
|
this.cardApiTicketExpiresTime = 0;
|
||||||
@Override
|
break;
|
||||||
public String getCardApiTicket() {
|
case SDK:
|
||||||
return this.cardApiTicket;
|
this.sdkTicketExpiresTime = 0;
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
public void setCardApiTicket(String cardApiTicket) {
|
}
|
||||||
this.cardApiTicket = cardApiTicket;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Lock getCardApiTicketLock() {
|
|
||||||
return this.cardApiTicketLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCardApiTicketExpired() {
|
|
||||||
return System.currentTimeMillis() > this.cardApiTicketExpiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {
|
|
||||||
this.cardApiTicket = cardApiTicket;
|
|
||||||
// 预留200秒的时间
|
|
||||||
this.cardApiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void expireCardApiTicket() {
|
|
||||||
this.cardApiTicketExpiresTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAppId() {
|
|
||||||
return this.appId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAppId(String appId) {
|
|
||||||
this.appId = appId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSecret() {
|
|
||||||
return this.secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecret(String secret) {
|
|
||||||
this.secret = secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getToken() {
|
|
||||||
return this.token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTemplateId() {
|
|
||||||
return this.templateId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTemplateId(String templateId) {
|
|
||||||
this.templateId = templateId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getExpiresTime() {
|
|
||||||
return this.expiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpiresTime(long expiresTime) {
|
|
||||||
this.expiresTime = expiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAesKey() {
|
|
||||||
return this.aesKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAesKey(String aesKey) {
|
|
||||||
this.aesKey = aesKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getOauth2redirectUri() {
|
|
||||||
return this.oauth2redirectUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOauth2redirectUri(String oauth2redirectUri) {
|
|
||||||
this.oauth2redirectUri = oauth2redirectUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHttpProxyHost() {
|
|
||||||
return this.httpProxyHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpProxyHost(String httpProxyHost) {
|
|
||||||
this.httpProxyHost = httpProxyHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHttpProxyPort() {
|
|
||||||
return this.httpProxyPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpProxyPort(int httpProxyPort) {
|
|
||||||
this.httpProxyPort = httpProxyPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHttpProxyUsername() {
|
|
||||||
return this.httpProxyUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpProxyUsername(String httpProxyUsername) {
|
|
||||||
this.httpProxyUsername = httpProxyUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHttpProxyPassword() {
|
|
||||||
return this.httpProxyPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpProxyPassword(String httpProxyPassword) {
|
|
||||||
this.httpProxyPassword = httpProxyPassword;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -251,40 +174,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
return WxMpGsonBuilder.create().toJson(this);
|
return WxMpGsonBuilder.create().toJson(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getTmpDirFile() {
|
|
||||||
return this.tmpDirFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTmpDirFile(File tmpDirFile) {
|
|
||||||
this.tmpDirFile = tmpDirFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApacheHttpClientBuilder getApacheHttpClientBuilder() {
|
|
||||||
return this.apacheHttpClientBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) {
|
|
||||||
this.apacheHttpClientBuilder = apacheHttpClientBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getJsapiTicketExpiresTime() {
|
|
||||||
return this.jsapiTicketExpiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJsapiTicketExpiresTime(long jsapiTicketExpiresTime) {
|
|
||||||
this.jsapiTicketExpiresTime = jsapiTicketExpiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCardApiTicketExpiresTime() {
|
|
||||||
return this.cardApiTicketExpiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCardApiTicketExpiresTime(long cardApiTicketExpiresTime) {
|
|
||||||
this.cardApiTicketExpiresTime = cardApiTicketExpiresTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean autoRefreshToken() {
|
public boolean autoRefreshToken() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,51 +1,45 @@
|
|||||||
package me.chanjar.weixin.mp.api;
|
package me.chanjar.weixin.mp.api;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于Redis的微信配置provider
|
* 基于Redis的微信配置provider.
|
||||||
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* 使用说明:本实现仅供参考,并不完整,
|
* 使用说明:本实现仅供参考,并不完整,
|
||||||
* 比如为减少项目依赖,未加入redis分布式锁的实现,如有需要请自行实现。
|
* 比如为减少项目依赖,未加入redis分布式锁的实现,如有需要请自行实现。
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @author nickwong
|
* @author nickwong
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("hiding")
|
@SuppressWarnings("hiding")
|
||||||
public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage {
|
public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage {
|
||||||
|
private static final String ACCESS_TOKEN_KEY = "wx:access_token:";
|
||||||
private final static String ACCESS_TOKEN_KEY = "wechat_access_token_";
|
|
||||||
|
|
||||||
private final static String JSAPI_TICKET_KEY = "wechat_jsapi_ticket_";
|
|
||||||
|
|
||||||
private final static String CARDAPI_TICKET_KEY = "wechat_cardapi_ticket_";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用连接池保证线程安全
|
* 使用连接池保证线程安全.
|
||||||
*/
|
*/
|
||||||
protected final JedisPool jedisPool;
|
protected final JedisPool jedisPool;
|
||||||
|
|
||||||
private String accessTokenKey;
|
private String accessTokenKey;
|
||||||
|
|
||||||
private String jsapiTicketKey;
|
|
||||||
|
|
||||||
private String cardapiTicketKey;
|
|
||||||
|
|
||||||
public WxMpInRedisConfigStorage(JedisPool jedisPool) {
|
public WxMpInRedisConfigStorage(JedisPool jedisPool) {
|
||||||
this.jedisPool = jedisPool;
|
this.jedisPool = jedisPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每个公众号生成独有的存储key
|
* 每个公众号生成独有的存储key.
|
||||||
*
|
|
||||||
* @param appId
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setAppId(String appId) {
|
public void setAppId(String appId) {
|
||||||
super.setAppId(appId);
|
super.setAppId(appId);
|
||||||
this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
|
this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
|
||||||
this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(appId);
|
}
|
||||||
this.cardapiTicketKey = CARDAPI_TICKET_KEY.concat(appId);
|
|
||||||
|
private String getTicketRedisKey(TicketType type) {
|
||||||
|
return String.format("wx:ticket:key:%s:%s", this.appId, type.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -77,58 +71,31 @@ public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getJsapiTicket() {
|
public String getTicket(TicketType type) {
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||||
return jedis.get(this.jsapiTicketKey);
|
return jedis.get(this.getTicketRedisKey(type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isJsapiTicketExpired() {
|
public boolean isTicketExpired(TicketType type) {
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||||
return jedis.ttl(this.jsapiTicketKey) < 2;
|
return jedis.ttl(this.getTicketRedisKey(type)) < 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
|
public synchronized void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) {
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||||
jedis.setex(this.jsapiTicketKey, expiresInSeconds - 200, jsapiTicket);
|
jedis.setex(this.getTicketRedisKey(type), expiresInSeconds - 200, jsapiTicket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void expireJsapiTicket() {
|
public void expireTicket(TicketType type) {
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||||
jedis.expire(this.jsapiTicketKey, 0);
|
jedis.expire(this.getTicketRedisKey(type), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCardApiTicket() {
|
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
|
||||||
return jedis.get(this.cardapiTicketKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCardApiTicketExpired() {
|
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
|
||||||
return jedis.ttl(this.cardapiTicketKey) < 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {
|
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
|
||||||
jedis.setex(this.cardapiTicketKey, expiresInSeconds - 200, cardApiTicket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void expireCardApiTicket() {
|
|
||||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
|
||||||
jedis.expire(this.cardapiTicketKey, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,76 +10,79 @@ import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
|||||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||||
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信API的Service
|
* 微信公众号API的Service.
|
||||||
|
*
|
||||||
|
* @author chanjarster
|
||||||
*/
|
*/
|
||||||
public interface WxMpService {
|
public interface WxMpService {
|
||||||
/**
|
/**
|
||||||
* 获取access_token
|
* 获取access_token.
|
||||||
*/
|
*/
|
||||||
String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||||
/**
|
/**
|
||||||
* 获得jsapi_ticket
|
* 获得各种类型的ticket.
|
||||||
*/
|
*/
|
||||||
String GET_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
|
String GET_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=";
|
||||||
/**
|
/**
|
||||||
* 长链接转短链接接口
|
* 长链接转短链接接口.
|
||||||
*/
|
*/
|
||||||
String SHORTURL_API_URL = "https://api.weixin.qq.com/cgi-bin/shorturl";
|
String SHORTURL_API_URL = "https://api.weixin.qq.com/cgi-bin/shorturl";
|
||||||
/**
|
/**
|
||||||
* 语义查询接口
|
* 语义查询接口.
|
||||||
*/
|
*/
|
||||||
String SEMANTIC_SEMPROXY_SEARCH_URL = "https://api.weixin.qq.com/semantic/semproxy/search";
|
String SEMANTIC_SEMPROXY_SEARCH_URL = "https://api.weixin.qq.com/semantic/semproxy/search";
|
||||||
/**
|
/**
|
||||||
* 用code换取oauth2的access token
|
* 用code换取oauth2的access token.
|
||||||
*/
|
*/
|
||||||
String OAUTH2_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
|
String OAUTH2_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
|
||||||
/**
|
/**
|
||||||
* 刷新oauth2的access token
|
* 刷新oauth2的access token.
|
||||||
*/
|
*/
|
||||||
String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";
|
String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";
|
||||||
/**
|
/**
|
||||||
* 用oauth2获取用户信息
|
* 用oauth2获取用户信息.
|
||||||
*/
|
*/
|
||||||
String OAUTH2_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s";
|
String OAUTH2_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s";
|
||||||
/**
|
/**
|
||||||
* 验证oauth2的access token是否有效
|
* 验证oauth2的access token是否有效.
|
||||||
*/
|
*/
|
||||||
String OAUTH2_VALIDATE_TOKEN_URL = "https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s";
|
String OAUTH2_VALIDATE_TOKEN_URL = "https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s";
|
||||||
/**
|
/**
|
||||||
* 获取微信服务器IP地址
|
* 获取微信服务器IP地址.
|
||||||
*/
|
*/
|
||||||
String GET_CALLBACK_IP_URL = "https://api.weixin.qq.com/cgi-bin/getcallbackip";
|
String GET_CALLBACK_IP_URL = "https://api.weixin.qq.com/cgi-bin/getcallbackip";
|
||||||
/**
|
/**
|
||||||
* 第三方使用网站应用授权登录的url
|
* 第三方使用网站应用授权登录的url.
|
||||||
*/
|
*/
|
||||||
String QRCONNECT_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";
|
String QRCONNECT_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";
|
||||||
/**
|
/**
|
||||||
* oauth2授权的url连接
|
* oauth2授权的url连接.
|
||||||
*/
|
*/
|
||||||
String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&connect_redirect=1#wechat_redirect";
|
String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&connect_redirect=1#wechat_redirect";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取公众号的自动回复规则
|
* 获取公众号的自动回复规则.
|
||||||
*/
|
*/
|
||||||
String GET_CURRENT_AUTOREPLY_INFO_URL = "https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info";
|
String GET_CURRENT_AUTOREPLY_INFO_URL = "https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公众号调用或第三方平台帮公众号调用对公众号的所有api调用(包括第三方帮其调用)次数进行清零
|
* 公众号调用或第三方平台帮公众号调用对公众号的所有api调用(包括第三方帮其调用)次数进行清零.
|
||||||
*/
|
*/
|
||||||
String CLEAR_QUOTA_URL = "https://api.weixin.qq.com/cgi-bin/clear_quota";
|
String CLEAR_QUOTA_URL = "https://api.weixin.qq.com/cgi-bin/clear_quota";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 验证消息的确来自微信服务器
|
* 验证消息的确来自微信服务器.
|
||||||
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
|
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
boolean checkSignature(String timestamp, String nonce, String signature);
|
boolean checkSignature(String timestamp, String nonce, String signature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取access_token, 不强制刷新access_token
|
* 获取access_token, 不强制刷新access_token.
|
||||||
*
|
*
|
||||||
* @see #getAccessToken(boolean)
|
* @see #getAccessToken(boolean)
|
||||||
*/
|
*/
|
||||||
@ -87,7 +90,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 获取access_token,本方法线程安全
|
* 获取access_token,本方法线程安全.
|
||||||
* 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
|
* 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
|
||||||
*
|
*
|
||||||
* 另:本service的所有方法都会在access_token过期时调用此方法
|
* 另:本service的所有方法都会在access_token过期时调用此方法
|
||||||
@ -102,7 +105,24 @@ public interface WxMpService {
|
|||||||
String getAccessToken(boolean forceRefresh) throws WxErrorException;
|
String getAccessToken(boolean forceRefresh) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得jsapi_ticket,不强制刷新jsapi_ticket
|
* 获得ticket,不强制刷新ticket.
|
||||||
|
*
|
||||||
|
* @see #getTicket(TicketType, boolean)
|
||||||
|
*/
|
||||||
|
String getTicket(TicketType type) throws WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 获得ticket.
|
||||||
|
* 获得时会检查 Token是否过期,如果过期了,那么就刷新一下,否则就什么都不干
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param forceRefresh 强制刷新
|
||||||
|
*/
|
||||||
|
String getTicket(TicketType type, boolean forceRefresh) throws WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得jsapi_ticket,不强制刷新jsapi_ticket.
|
||||||
*
|
*
|
||||||
* @see #getJsapiTicket(boolean)
|
* @see #getJsapiTicket(boolean)
|
||||||
*/
|
*/
|
||||||
@ -110,7 +130,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 获得jsapi_ticket
|
* 获得jsapi_ticket.
|
||||||
* 获得时会检查jsapiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
|
* 获得时会检查jsapiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
|
||||||
*
|
*
|
||||||
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
||||||
@ -122,7 +142,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 创建调用jsapi时所需要的签名
|
* 创建调用jsapi时所需要的签名.
|
||||||
*
|
*
|
||||||
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
||||||
* </pre>
|
* </pre>
|
||||||
@ -131,7 +151,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 长链接转短链接接口
|
* 长链接转短链接接口.
|
||||||
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口
|
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@ -139,7 +159,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 语义查询接口
|
* 语义查询接口.
|
||||||
* 详情请见:http://mp.weixin.qq.com/wiki/index.php?title=语义理解
|
* 详情请见:http://mp.weixin.qq.com/wiki/index.php?title=语义理解
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@ -147,7 +167,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 构造第三方使用网站应用授权登录的url
|
* 构造第三方使用网站应用授权登录的url.
|
||||||
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN">网站应用微信登录开发指南</a>
|
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN">网站应用微信登录开发指南</a>
|
||||||
* URL格式为:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
|
* URL格式为:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
|
||||||
* </pre>
|
* </pre>
|
||||||
@ -161,7 +181,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 构造oauth2授权的url连接
|
* 构造oauth2授权的url连接.
|
||||||
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
|
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
@ -172,7 +192,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 用code换取oauth2的access token
|
* 用code换取oauth2的access token.
|
||||||
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
|
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@ -180,14 +200,14 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 刷新oauth2的access token
|
* 刷新oauth2的access token.
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException;
|
WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以
|
* 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param lang zh_CN, zh_TW, en
|
* @param lang zh_CN, zh_TW, en
|
||||||
@ -196,7 +216,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 验证oauth2的access token是否有效
|
* 验证oauth2的access token是否有效.
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken);
|
boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken);
|
||||||
@ -211,7 +231,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 获取公众号的自动回复规则
|
* 获取公众号的自动回复规则.
|
||||||
* http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751299&token=&lang=zh_CN
|
* http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751299&token=&lang=zh_CN
|
||||||
* 开发者可以通过该接口,获取公众号当前使用的自动回复规则,包括关注后自动回复、消息自动回复(60分钟内触发一次)、关键词自动回复。
|
* 开发者可以通过该接口,获取公众号当前使用的自动回复规则,包括关注后自动回复、消息自动回复(60分钟内触发一次)、关键词自动回复。
|
||||||
* 请注意:
|
* 请注意:
|
||||||
@ -240,12 +260,12 @@ public interface WxMpService {
|
|||||||
void clearQuota(String appid) throws WxErrorException;
|
void clearQuota(String appid) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
|
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求.
|
||||||
*/
|
*/
|
||||||
String get(String url, String queryParam) throws WxErrorException;
|
String get(String url, String queryParam) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求
|
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求.
|
||||||
*/
|
*/
|
||||||
String post(String url, String postData) throws WxErrorException;
|
String post(String url, String postData) throws WxErrorException;
|
||||||
|
|
||||||
@ -260,7 +280,7 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试
|
* 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
|
||||||
* @param retrySleepMillis 默认:1000ms
|
* @param retrySleepMillis 默认:1000ms
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@ -268,131 +288,131 @@ public interface WxMpService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 设置当微信系统响应系统繁忙时,最大重试次数
|
* 设置当微信系统响应系统繁忙时,最大重试次数.
|
||||||
* 默认:5次
|
* 默认:5次
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
void setMaxRetryTimes(int maxRetryTimes);
|
void setMaxRetryTimes(int maxRetryTimes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取WxMpConfigStorage 对象
|
* 获取WxMpConfigStorage 对象.
|
||||||
*
|
*
|
||||||
* @return WxMpConfigStorage
|
* @return WxMpConfigStorage
|
||||||
*/
|
*/
|
||||||
WxMpConfigStorage getWxMpConfigStorage();
|
WxMpConfigStorage getWxMpConfigStorage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注入 {@link WxMpConfigStorage} 的实现
|
* 注入 {@link WxMpConfigStorage} 的实现.
|
||||||
*/
|
*/
|
||||||
void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider);
|
void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回客服接口方法实现类,以方便调用其各个接口
|
* 返回客服接口方法实现类,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpKefuService
|
* @return WxMpKefuService
|
||||||
*/
|
*/
|
||||||
WxMpKefuService getKefuService();
|
WxMpKefuService getKefuService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回素材相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回素材相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpMaterialService
|
* @return WxMpMaterialService
|
||||||
*/
|
*/
|
||||||
WxMpMaterialService getMaterialService();
|
WxMpMaterialService getMaterialService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回菜单相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回菜单相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpMenuService
|
* @return WxMpMenuService
|
||||||
*/
|
*/
|
||||||
WxMpMenuService getMenuService();
|
WxMpMenuService getMenuService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回用户相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回用户相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpUserService
|
* @return WxMpUserService
|
||||||
*/
|
*/
|
||||||
WxMpUserService getUserService();
|
WxMpUserService getUserService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回用户标签相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回用户标签相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpUserTagService
|
* @return WxMpUserTagService
|
||||||
*/
|
*/
|
||||||
WxMpUserTagService getUserTagService();
|
WxMpUserTagService getUserTagService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回二维码相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回二维码相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpQrcodeService
|
* @return WxMpQrcodeService
|
||||||
*/
|
*/
|
||||||
WxMpQrcodeService getQrcodeService();
|
WxMpQrcodeService getQrcodeService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回卡券相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回卡券相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpCardService
|
* @return WxMpCardService
|
||||||
*/
|
*/
|
||||||
WxMpCardService getCardService();
|
WxMpCardService getCardService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回数据分析统计相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回数据分析统计相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpDataCubeService
|
* @return WxMpDataCubeService
|
||||||
*/
|
*/
|
||||||
WxMpDataCubeService getDataCubeService();
|
WxMpDataCubeService getDataCubeService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回用户黑名单管理相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回用户黑名单管理相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpUserBlacklistService
|
* @return WxMpUserBlacklistService
|
||||||
*/
|
*/
|
||||||
WxMpUserBlacklistService getBlackListService();
|
WxMpUserBlacklistService getBlackListService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回门店管理相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回门店管理相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpStoreService
|
* @return WxMpStoreService
|
||||||
*/
|
*/
|
||||||
WxMpStoreService getStoreService();
|
WxMpStoreService getStoreService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回模板消息相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回模板消息相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpTemplateMsgService
|
* @return WxMpTemplateMsgService
|
||||||
*/
|
*/
|
||||||
WxMpTemplateMsgService getTemplateMsgService();
|
WxMpTemplateMsgService getTemplateMsgService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回一次性订阅消息相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回一次性订阅消息相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpSubscribeMsgService
|
* @return WxMpSubscribeMsgService
|
||||||
*/
|
*/
|
||||||
WxMpSubscribeMsgService getSubscribeMsgService();
|
WxMpSubscribeMsgService getSubscribeMsgService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回硬件平台相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回硬件平台相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpDeviceService
|
* @return WxMpDeviceService
|
||||||
*/
|
*/
|
||||||
WxMpDeviceService getDeviceService();
|
WxMpDeviceService getDeviceService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回摇一摇周边相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回摇一摇周边相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpShakeService
|
* @return WxMpShakeService
|
||||||
*/
|
*/
|
||||||
WxMpShakeService getShakeService();
|
WxMpShakeService getShakeService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回会员卡相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回会员卡相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpMemberCardService
|
* @return WxMpMemberCardService
|
||||||
*/
|
*/
|
||||||
WxMpMemberCardService getMemberCardService();
|
WxMpMemberCardService getMemberCardService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化http请求对象
|
* 初始化http请求对象.
|
||||||
*/
|
*/
|
||||||
void initHttp();
|
void initHttp();
|
||||||
|
|
||||||
@ -402,21 +422,21 @@ public interface WxMpService {
|
|||||||
RequestHttp getRequestHttp();
|
RequestHttp getRequestHttp();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回群发消息相关接口方法的实现类对象,以方便调用其各个接口
|
* 返回群发消息相关接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpMassMessageService
|
* @return WxMpMassMessageService
|
||||||
*/
|
*/
|
||||||
WxMpMassMessageService getMassMessageService();
|
WxMpMassMessageService getMassMessageService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回AI开放接口方法的实现类对象,以方便调用其各个接口
|
* 返回AI开放接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpAiOpenService
|
* @return WxMpAiOpenService
|
||||||
*/
|
*/
|
||||||
WxMpAiOpenService getAiOpenService();
|
WxMpAiOpenService getAiOpenService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回WIFI接口方法的实现类对象,以方便调用其各个接口
|
* 返回WIFI接口方法的实现类对象,以方便调用其各个接口.
|
||||||
*
|
*
|
||||||
* @return WxMpWifiService
|
* @return WxMpWifiService
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package me.chanjar.weixin.mp.api.impl;
|
package me.chanjar.weixin.mp.api.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@ -12,19 +19,37 @@ import me.chanjar.weixin.common.session.WxSessionManager;
|
|||||||
import me.chanjar.weixin.common.util.DataUtils;
|
import me.chanjar.weixin.common.util.DataUtils;
|
||||||
import me.chanjar.weixin.common.util.RandomUtils;
|
import me.chanjar.weixin.common.util.RandomUtils;
|
||||||
import me.chanjar.weixin.common.util.crypto.SHA1;
|
import me.chanjar.weixin.common.util.crypto.SHA1;
|
||||||
import me.chanjar.weixin.common.util.http.*;
|
import me.chanjar.weixin.common.util.http.RequestExecutor;
|
||||||
import me.chanjar.weixin.mp.api.*;
|
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||||
|
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
|
||||||
|
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
|
||||||
|
import me.chanjar.weixin.common.util.http.URIUtil;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpAiOpenService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpCardService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpDataCubeService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpDeviceService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpKefuService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMassMessageService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMaterialService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMemberCardService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMenuService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpShakeService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpStoreService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpSubscribeMsgService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpTemplateMsgService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpUserBlacklistService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpUserService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpUserTagService;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpWifiService;
|
||||||
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
|
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author someone
|
* @author someone
|
||||||
@ -71,31 +96,42 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getJsapiTicket() throws WxErrorException {
|
public String getTicket(TicketType type) throws WxErrorException {
|
||||||
return getJsapiTicket(false);
|
return this.getTicket(type, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
|
public String getTicket(TicketType type, boolean forceRefresh) throws WxErrorException {
|
||||||
Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock();
|
Lock lock = this.getWxMpConfigStorage().getTicketLock(type);
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
if (forceRefresh) {
|
if (forceRefresh) {
|
||||||
this.getWxMpConfigStorage().expireJsapiTicket();
|
this.getWxMpConfigStorage().expireTicket(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getWxMpConfigStorage().isJsapiTicketExpired()) {
|
if (this.getWxMpConfigStorage().isTicketExpired(type)) {
|
||||||
String responseContent = execute(SimpleGetRequestExecutor.create(this), WxMpService.GET_JSAPI_TICKET_URL, null);
|
String responseContent = execute(SimpleGetRequestExecutor.create(this),
|
||||||
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
|
WxMpService.GET_TICKET_URL + type.getCode(), null);
|
||||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
JsonObject tmpJsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
|
||||||
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
|
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
|
||||||
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
||||||
this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds);
|
this.getWxMpConfigStorage().updateTicket(type, jsapiTicket, expiresInSeconds);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
return this.getWxMpConfigStorage().getJsapiTicket();
|
|
||||||
|
return this.getWxMpConfigStorage().getTicket(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJsapiTicket() throws WxErrorException {
|
||||||
|
return this.getJsapiTicket(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
|
||||||
|
return this.getTicket(TicketType.JSAPI, forceRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,13 +26,15 @@ import me.chanjar.weixin.mp.bean.card.WxMpCardLandingPageCreateRequest;
|
|||||||
import me.chanjar.weixin.mp.bean.card.WxMpCardLandingPageCreateResult;
|
import me.chanjar.weixin.mp.bean.card.WxMpCardLandingPageCreateResult;
|
||||||
import me.chanjar.weixin.mp.bean.card.WxMpCardQrcodeCreateResult;
|
import me.chanjar.weixin.mp.bean.card.WxMpCardQrcodeCreateResult;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
|
import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
|
||||||
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Binary Wang on 2016/7/27.
|
* Created by Binary Wang on 2016/7/27.
|
||||||
|
*
|
||||||
|
* @author BinaryWang
|
||||||
*/
|
*/
|
||||||
public class WxMpCardServiceImpl implements WxMpCardService {
|
public class WxMpCardServiceImpl implements WxMpCardService {
|
||||||
|
|
||||||
private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class);
|
private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class);
|
||||||
|
|
||||||
private WxMpService wxMpService;
|
private WxMpService wxMpService;
|
||||||
@ -49,7 +51,7 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得卡券api_ticket,不强制刷新卡券api_ticket
|
* 获得卡券api_ticket,不强制刷新卡券api_ticket.
|
||||||
*
|
*
|
||||||
* @return 卡券api_ticket
|
* @return 卡券api_ticket
|
||||||
* @see #getCardApiTicket(boolean)
|
* @see #getCardApiTicket(boolean)
|
||||||
@ -61,7 +63,7 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 获得卡券api_ticket
|
* 获得卡券api_ticket.
|
||||||
* 获得时会检查卡券apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
|
* 获得时会检查卡券apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
|
||||||
*
|
*
|
||||||
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
|
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
|
||||||
@ -74,26 +76,28 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
|
public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
|
||||||
Lock lock = getWxMpService().getWxMpConfigStorage().getCardApiTicketLock();
|
final TicketType type = TicketType.WX_CARD;
|
||||||
|
Lock lock = getWxMpService().getWxMpConfigStorage().getTicketLock(type);
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
if (forceRefresh) {
|
if (forceRefresh) {
|
||||||
this.getWxMpService().getWxMpConfigStorage().expireCardApiTicket();
|
this.getWxMpService().getWxMpConfigStorage().expireTicket(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getWxMpService().getWxMpConfigStorage().isCardApiTicketExpired()) {
|
if (this.getWxMpService().getWxMpConfigStorage().isTicketExpired(type)) {
|
||||||
String responseContent = this.wxMpService.execute(SimpleGetRequestExecutor.create(this.getWxMpService().getRequestHttp()), CARD_GET_TICKET, null);
|
String responseContent = this.wxMpService.execute(SimpleGetRequestExecutor
|
||||||
|
.create(this.getWxMpService().getRequestHttp()), CARD_GET_TICKET, null);
|
||||||
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
|
||||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
||||||
String cardApiTicket = tmpJsonObject.get("ticket").getAsString();
|
String cardApiTicket = tmpJsonObject.get("ticket").getAsString();
|
||||||
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
||||||
this.getWxMpService().getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds);
|
this.getWxMpService().getWxMpConfigStorage().updateTicket(type, cardApiTicket, expiresInSeconds);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
return this.getWxMpService().getWxMpConfigStorage().getCardApiTicket();
|
return this.getWxMpService().getWxMpConfigStorage().getTicket(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,7 +151,7 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 卡券Code查询
|
* 卡券Code查询.
|
||||||
*
|
*
|
||||||
* @param cardId 卡券ID代表一类卡券
|
* @param cardId 卡券ID代表一类卡券
|
||||||
* @param code 单张卡券的唯一标准
|
* @param code 单张卡券的唯一标准
|
||||||
@ -247,11 +251,11 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加测试白名单
|
* 添加测试白名单.
|
||||||
*
|
*
|
||||||
* @param openid 用户的openid
|
* @param openid 用户的openid
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String addTestWhiteList(String openid) throws WxErrorException {
|
public String addTestWhiteList(String openid) throws WxErrorException {
|
||||||
JsonArray array = new JsonArray();
|
JsonArray array = new JsonArray();
|
||||||
array.add(openid);
|
array.add(openid);
|
||||||
@ -262,25 +266,21 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建卡券二维码
|
* 创建卡券二维码.
|
||||||
*
|
|
||||||
* @param cardId
|
|
||||||
* @param outerStr
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public WxMpCardQrcodeCreateResult createQrcodeCard(String cardId, String outerStr) throws WxErrorException {
|
public WxMpCardQrcodeCreateResult createQrcodeCard(String cardId, String outerStr) throws WxErrorException {
|
||||||
return createQrcodeCard(cardId, outerStr, 0);
|
return createQrcodeCard(cardId, outerStr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建卡券二维码
|
* 创建卡券二维码.
|
||||||
*
|
*
|
||||||
* @param cardId 卡券编号
|
* @param cardId 卡券编号
|
||||||
* @param outerStr 二维码标识
|
* @param outerStr 二维码标识
|
||||||
* @param expiresIn 失效时间,单位秒,不填默认365天
|
* @param expiresIn 失效时间,单位秒,不填默认365天
|
||||||
* @return
|
|
||||||
* @throws WxErrorException
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public WxMpCardQrcodeCreateResult createQrcodeCard(String cardId, String outerStr, int expiresIn) throws WxErrorException {
|
public WxMpCardQrcodeCreateResult createQrcodeCard(String cardId, String outerStr, int expiresIn) throws WxErrorException {
|
||||||
JsonObject jsonObject = new JsonObject();
|
JsonObject jsonObject = new JsonObject();
|
||||||
jsonObject.addProperty("action_name", "QR_CARD");
|
jsonObject.addProperty("action_name", "QR_CARD");
|
||||||
@ -293,16 +293,11 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
cardJson.addProperty("outer_str", outerStr);
|
cardJson.addProperty("outer_str", outerStr);
|
||||||
actionInfoJson.add("card", cardJson);
|
actionInfoJson.add("card", cardJson);
|
||||||
jsonObject.add("action_info", actionInfoJson);
|
jsonObject.add("action_info", actionInfoJson);
|
||||||
String response = this.wxMpService.post(CARD_QRCODE_CREATE, GSON.toJson(jsonObject));
|
return WxMpCardQrcodeCreateResult.fromJson(this.wxMpService.post(CARD_QRCODE_CREATE, GSON.toJson(jsonObject)));
|
||||||
return WxMpCardQrcodeCreateResult.fromJson(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建卡券货架接口
|
* 创建卡券货架接口.
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
* @throws WxErrorException
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public WxMpCardLandingPageCreateResult createLandingPage(WxMpCardLandingPageCreateRequest request) throws WxErrorException {
|
public WxMpCardLandingPageCreateResult createLandingPage(WxMpCardLandingPageCreateRequest request) throws WxErrorException {
|
||||||
@ -311,24 +306,22 @@ public class WxMpCardServiceImpl implements WxMpCardService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将用户的卡券设置为失效状态
|
* 将用户的卡券设置为失效状态.
|
||||||
* 详见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025272&anchor=9
|
* 详见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025272&anchor=9
|
||||||
*
|
*
|
||||||
* @param cardId 卡券编号
|
* @param cardId 卡券编号
|
||||||
* @param code 用户会员卡号
|
* @param code 用户会员卡号
|
||||||
* @param reason 设置为失效的原因
|
* @param reason 设置为失效的原因
|
||||||
* @return
|
|
||||||
* @throws WxErrorException
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String unavailableCardCode(String cardId, String code, String reason) throws WxErrorException {
|
public String unavailableCardCode(String cardId, String code, String reason) throws WxErrorException {
|
||||||
if (StringUtils.isAnyBlank(cardId, code, reason))
|
if (StringUtils.isAnyBlank(cardId, code, reason)) {
|
||||||
throw new WxErrorException(WxError.builder().errorCode(41012).errorMsg("参数不完整").build());
|
throw new WxErrorException(WxError.builder().errorCode(41012).errorMsg("参数不完整").build());
|
||||||
|
}
|
||||||
JsonObject jsonRequest = new JsonObject();
|
JsonObject jsonRequest = new JsonObject();
|
||||||
jsonRequest.addProperty("card_id", cardId);
|
jsonRequest.addProperty("card_id", cardId);
|
||||||
jsonRequest.addProperty("code", code);
|
jsonRequest.addProperty("code", code);
|
||||||
jsonRequest.addProperty("reason", reason);
|
jsonRequest.addProperty("reason", reason);
|
||||||
String response = this.wxMpService.post(CARD_CODE_UNAVAILABLE, GSON.toJson(jsonRequest));
|
return this.wxMpService.post(CARD_CODE_UNAVAILABLE, GSON.toJson(jsonRequest));
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package me.chanjar.weixin.mp.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* ticket类型枚举
|
||||||
|
* Created by Binary Wang on 2018/11/18.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum TicketType {
|
||||||
|
/**
|
||||||
|
* jsapi
|
||||||
|
*/
|
||||||
|
JSAPI("jsapi"),
|
||||||
|
/**
|
||||||
|
* sdk
|
||||||
|
*/
|
||||||
|
SDK("2"),
|
||||||
|
/**
|
||||||
|
* 微信卡券
|
||||||
|
*/
|
||||||
|
WX_CARD("wx_card");
|
||||||
|
/**
|
||||||
|
* type代码
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
TicketType(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
}
|
@ -1,38 +0,0 @@
|
|||||||
package me.chanjar.weixin.mp.api;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
|
||||||
import me.chanjar.weixin.mp.api.test.ApiTestModule;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.testng.*;
|
|
||||||
import org.testng.annotations.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 基础API测试
|
|
||||||
*
|
|
||||||
* @author chanjarster
|
|
||||||
*/
|
|
||||||
@Test(groups = "baseAPI")
|
|
||||||
@Guice(modules = ApiTestModule.class)
|
|
||||||
public class WxMpBaseAPITest {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected WxMpService wxService;
|
|
||||||
|
|
||||||
public void testRefreshAccessToken() throws WxErrorException {
|
|
||||||
WxMpConfigStorage configStorage = this.wxService.getWxMpConfigStorage();
|
|
||||||
String before = configStorage.getAccessToken();
|
|
||||||
this.wxService.getAccessToken(false);
|
|
||||||
|
|
||||||
String after = configStorage.getAccessToken();
|
|
||||||
Assert.assertNotEquals(before, after);
|
|
||||||
Assert.assertTrue(StringUtils.isNotBlank(after));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testJsapiTicket() throws WxErrorException {
|
|
||||||
String jsapiTicket = this.wxService.getJsapiTicket(false);
|
|
||||||
System.out.println(jsapiTicket);
|
|
||||||
Assert.assertNotNull(jsapiTicket);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,14 +1,18 @@
|
|||||||
package me.chanjar.weixin.mp.api.impl;
|
package me.chanjar.weixin.mp.api.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.testng.*;
|
||||||
|
import org.testng.annotations.*;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import me.chanjar.weixin.common.api.WxConsts;
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import me.chanjar.weixin.mp.api.test.ApiTestModule;
|
import me.chanjar.weixin.mp.api.test.ApiTestModule;
|
||||||
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
|
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
||||||
import org.testng.*;
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import org.testng.annotations.*;
|
|
||||||
|
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
@ -40,4 +44,19 @@ public class WxMpServiceImplTest {
|
|||||||
System.out.println(qrConnectUrl);
|
System.out.println(qrConnectUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetTicket() throws WxErrorException {
|
||||||
|
String ticket = this.wxService.getTicket(TicketType.SDK, false);
|
||||||
|
System.out.println(ticket);
|
||||||
|
Assert.assertNotNull(ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRefreshAccessToken() throws WxErrorException {
|
||||||
|
WxMpConfigStorage configStorage = this.wxService.getWxMpConfigStorage();
|
||||||
|
String before = configStorage.getAccessToken();
|
||||||
|
this.wxService.getAccessToken(false);
|
||||||
|
|
||||||
|
String after = configStorage.getAccessToken();
|
||||||
|
Assert.assertNotEquals(before, after);
|
||||||
|
Assert.assertTrue(StringUtils.isNotBlank(after));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
package me.chanjar.weixin.mp.demo;
|
package me.chanjar.weixin.mp.demo;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import com.thoughtworks.xstream.XStream;
|
import com.thoughtworks.xstream.XStream;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||||
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
|
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Daniel Qian
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
@XStreamAlias("xml")
|
@XStreamAlias("xml")
|
||||||
class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
|
class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
|
||||||
|
private static final long serialVersionUID = -3706236839197109704L;
|
||||||
|
|
||||||
public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) {
|
public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) {
|
||||||
XStream xstream = XStreamInitializer.getInstance();
|
XStream xstream = XStreamInitializer.getInstance();
|
||||||
@ -24,10 +25,4 @@ class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
|
|||||||
return wxMpDemoInMemoryConfigStorage;
|
return wxMpDemoInMemoryConfigStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SimpleWxConfigProvider [appId=" + this.appId + ", secret=" + this.secret + ", accessToken=" + this.accessToken
|
|
||||||
+ ", expiresTime=" + this.expiresTime + ", token=" + this.token + ", aesKey=" + this.aesKey + ", templateId=" + this.templateId + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import cn.binarywang.wx.miniapp.config.WxMaConfig;
|
|||||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||||
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
||||||
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
|
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
|
||||||
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
|
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
|
||||||
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
|
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
|
||||||
@ -322,6 +323,31 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
|
|||||||
wxOpenConfigStorage.updateAuthorizerAccessToken(appId, accessToken, expiresInSeconds);
|
wxOpenConfigStorage.updateAuthorizerAccessToken(appId, accessToken, expiresInSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTicket(TicketType type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lock getTicketLock(TicketType type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTicketExpired(TicketType type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expireTicket(TicketType type) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTicket(TicketType type, String ticket, int expiresInSeconds) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAppid() {
|
public String getAppid() {
|
||||||
return this.appId;
|
return this.appId;
|
||||||
|
Loading…
Reference in New Issue
Block a user