@@ -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(); | |||||
Lock getJsapiTicketLock(); | |||||
boolean isJsapiTicketExpired(); | |||||
/** | |||||
* 强制将jsapi ticket过期掉 | |||||
*/ | |||||
void expireJsapiTicket(); | |||||
/** | |||||
* 应该是线程安全的 | |||||
* | |||||
* @param jsapiTicket 新的jsapi ticket值 | |||||
* @param expiresInSeconds 过期时间,以秒为单位 | |||||
*/ | |||||
void updateJsapiTicket(String jsapiTicket, int expiresInSeconds); | |||||
String getCardApiTicket(); | |||||
String getTicket(TicketType type); | |||||
Lock getCardApiTicketLock(); | |||||
Lock getTicketLock(TicketType type); | |||||
boolean isCardApiTicketExpired(); | |||||
boolean isTicketExpired(TicketType type); | |||||
/** | /** | ||||
* 强制将卡券api ticket过期掉 | |||||
* 强制将ticket过期掉. | |||||
*/ | */ | ||||
void expireCardApiTicket(); | |||||
void expireTicket(TicketType type); | |||||
/** | /** | ||||
* 更新ticket. | |||||
* 应该是线程安全的 | * 应该是线程安全的 | ||||
* | * | ||||
* @param cardApiTicket 新的cardApi ticket值 | |||||
* @param type ticket类型 | |||||
* @param ticket 新的ticket值 | |||||
* @param expiresInSeconds 过期时间,以秒为单位 | * @param expiresInSeconds 过期时间,以秒为单位 | ||||
*/ | */ | ||||
void updateCardApiTicket(String cardApiTicket, int expiresInSeconds); | |||||
void updateTicket(TicketType type, String ticket, 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() { | |||||
return this.jsapiTicket; | |||||
} | |||||
public void setJsapiTicket(String jsapiTicket) { | |||||
this.jsapiTicket = jsapiTicket; | |||||
} | |||||
@Override | |||||
public Lock getJsapiTicketLock() { | |||||
return this.jsapiTicketLock; | |||||
} | |||||
@Override | |||||
public boolean isJsapiTicketExpired() { | |||||
return System.currentTimeMillis() > this.jsapiTicketExpiresTime; | |||||
} | |||||
@Override | |||||
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | |||||
this.jsapiTicket = jsapiTicket; | |||||
// 预留200秒的时间 | |||||
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; | |||||
} | |||||
@Override | |||||
public void expireJsapiTicket() { | |||||
this.jsapiTicketExpiresTime = 0; | |||||
} | |||||
/** | |||||
* 卡券api_ticket | |||||
*/ | |||||
@Override | |||||
public String getCardApiTicket() { | |||||
return this.cardApiTicket; | |||||
} | |||||
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; | |||||
public String getTicket(TicketType type) { | |||||
switch (type) { | |||||
case SDK: | |||||
return this.sdkTicket; | |||||
case JSAPI: | |||||
return this.jsapiTicket; | |||||
case WX_CARD: | |||||
return this.cardApiTicket; | |||||
default: | |||||
return null; | |||||
} | |||||
} | |||||
public void setTicket(TicketType type, String ticket) { | |||||
switch (type) { | |||||
case JSAPI: | |||||
this.jsapiTicket = ticket; | |||||
break; | |||||
case WX_CARD: | |||||
this.cardApiTicket = ticket; | |||||
break; | |||||
case SDK: | |||||
this.sdkTicket = ticket; | |||||
break; | |||||
default: | |||||
} | |||||
} | |||||
@Override | |||||
public Lock getTicketLock(TicketType type) { | |||||
switch (type) { | |||||
case SDK: | |||||
return this.sdkTicketLock; | |||||
case JSAPI: | |||||
return this.jsapiTicketLock; | |||||
case WX_CARD: | |||||
return this.cardApiTicketLock; | |||||
default: | |||||
return null; | |||||
} | |||||
} | |||||
@Override | |||||
public boolean isTicketExpired(TicketType type) { | |||||
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 | |||||
public synchronized void updateTicket(TicketType type, String ticket, int expiresInSeconds) { | |||||
switch (type) { | |||||
case JSAPI: | |||||
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 | |||||
public void expireTicket(TicketType type) { | |||||
switch (type) { | |||||
case JSAPI: | |||||
this.jsapiTicketExpiresTime = 0; | |||||
break; | |||||
case WX_CARD: | |||||
this.cardApiTicketExpiresTime = 0; | |||||
break; | |||||
case SDK: | |||||
this.sdkTicketExpiresTime = 0; | |||||
break; | |||||
default: | |||||
} | |||||
} | } | ||||
@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 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_"; | |||||
private static final String ACCESS_TOKEN_KEY = "wx:access_token:"; | |||||
/** | /** | ||||
* 使用连接池保证线程安全 | |||||
* 使用连接池保证线程安全. | |||||
*/ | */ | ||||
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 | |||||
* | |||||
* @param appId | |||||
* 每个公众号生成独有的存储key. | |||||
*/ | */ | ||||
@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() { | |||||
try (Jedis jedis = this.jedisPool.getResource()) { | |||||
return jedis.get(this.jsapiTicketKey); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean isJsapiTicketExpired() { | |||||
try (Jedis jedis = this.jedisPool.getResource()) { | |||||
return jedis.ttl(this.jsapiTicketKey) < 2; | |||||
} | |||||
} | |||||
@Override | |||||
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | |||||
public String getTicket(TicketType type) { | |||||
try (Jedis jedis = this.jedisPool.getResource()) { | try (Jedis jedis = this.jedisPool.getResource()) { | ||||
jedis.setex(this.jsapiTicketKey, expiresInSeconds - 200, jsapiTicket); | |||||
return jedis.get(this.getTicketRedisKey(type)); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public void expireJsapiTicket() { | |||||
public boolean isTicketExpired(TicketType type) { | |||||
try (Jedis jedis = this.jedisPool.getResource()) { | try (Jedis jedis = this.jedisPool.getResource()) { | ||||
jedis.expire(this.jsapiTicketKey, 0); | |||||
return jedis.ttl(this.getTicketRedisKey(type)) < 2; | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public String getCardApiTicket() { | |||||
public synchronized void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) { | |||||
try (Jedis jedis = this.jedisPool.getResource()) { | try (Jedis jedis = this.jedisPool.getResource()) { | ||||
return jedis.get(this.cardapiTicketKey); | |||||
jedis.setex(this.getTicketRedisKey(type), expiresInSeconds - 200, jsapiTicket); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public boolean isCardApiTicketExpired() { | |||||
public void expireTicket(TicketType type) { | |||||
try (Jedis jedis = this.jedisPool.getResource()) { | try (Jedis jedis = this.jedisPool.getResource()) { | ||||
return jedis.ttl(this.cardapiTicketKey) < 2; | |||||
jedis.expire(this.getTicketRedisKey(type), 0); | |||||
} | } | ||||
} | } | ||||
@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.mp.api.*; | |||||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||||
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 org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.io.IOException; | |||||
import java.util.concurrent.locks.Lock; | |||||
import me.chanjar.weixin.mp.enums.TicketType; | |||||
/** | /** | ||||
* @author someone | * @author someone | ||||
@@ -71,31 +96,42 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||||
} | } | ||||
@Override | @Override | ||||
public String getJsapiTicket() throws WxErrorException { | |||||
return getJsapiTicket(false); | |||||
public String getTicket(TicketType type) throws WxErrorException { | |||||
return this.getTicket(type, false); | |||||
} | } | ||||
@Override | @Override | ||||
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { | |||||
Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); | |||||
public String getTicket(TicketType type, boolean forceRefresh) throws WxErrorException { | |||||
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()) { | |||||
String responseContent = execute(SimpleGetRequestExecutor.create(this), WxMpService.GET_JSAPI_TICKET_URL, null); | |||||
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); | |||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); | |||||
if (this.getWxMpConfigStorage().isTicketExpired(type)) { | |||||
String responseContent = execute(SimpleGetRequestExecutor.create(this), | |||||
WxMpService.GET_TICKET_URL + type.getCode(), null); | |||||
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()) { | |||||
String responseContent = this.wxMpService.execute(SimpleGetRequestExecutor.create(this.getWxMpService().getRequestHttp()), CARD_GET_TICKET, null); | |||||
if (this.getWxMpService().getWxMpConfigStorage().isTicketExpired(type)) { | |||||
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(response); | |||||
return WxMpCardQrcodeCreateResult.fromJson(this.wxMpService.post(CARD_QRCODE_CREATE, GSON.toJson(jsonObject))); | |||||
} | } | ||||
/** | /** | ||||
* 创建卡券货架接口 | |||||
* | |||||
* @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 response; | |||||
return this.wxMpService.post(CARD_CODE_UNAVAILABLE, GSON.toJson(jsonRequest)); | |||||
} | } | ||||
} | } |
@@ -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 org.testng.annotations.*; | |||||
import me.chanjar.weixin.mp.enums.TicketType; | |||||
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; | ||||