重构Cache实现

This commit is contained in:
jinyu 2016-05-28 11:33:05 +08:00
parent bc93a22563
commit b797580384
116 changed files with 1932 additions and 1313 deletions

View File

@ -702,3 +702,7 @@
+ weixin4j-base:修改Memcached-Java-Client的依赖
+ weixin4j-base:系统配置类抽象化
* 2016-05-28
+ 重构Cache实现

View File

@ -42,7 +42,7 @@
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.0</version>
<version>2.8.1</version>
<optional>true</optional>
</dependency>
<dependency>

View File

@ -632,7 +632,8 @@ public class PayApi extends MchApi {
String fileName = String.format("weixin4j_bill_%s_%s_%s.txt",
formatBillDate, billType.name().toLowerCase(),
weixinAccount.getId());
File file = new File(String.format("%s/%s", billPath, fileName));
File file = new File(String.format("%s%s%s", billPath, File.separator,
fileName));
if (file.exists()) {
return file;
}

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.token;
package com.foxinmy.weixin4j.cache;
import com.foxinmy.weixin4j.exception.WeixinException;
@ -11,7 +11,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
* @since JDK 1.6
* @see
*/
public interface CacheCreator<T> {
public interface CacheCreator<T extends Cacheable> {
/**
* CacheKey
*

View File

@ -0,0 +1,69 @@
package com.foxinmy.weixin4j.cache;
import com.foxinmy.weixin4j.exception.WeixinException;
/**
* 缓存管理类
*
* @className CacheManager
* @author jinyu(foxinmy@gmail.com)
* @date 2016年5月27日
* @since JDK 1.7
* @see
*/
public class CacheManager<T extends Cacheable> {
protected final CacheCreator<T> cacheCreator;
protected final CacheStorager<T> cacheStorager;
public CacheManager(CacheCreator<T> cacheCreator,
CacheStorager<T> cacheStorager) {
this.cacheCreator = cacheCreator;
this.cacheStorager = cacheStorager;
}
/**
* 获取缓存对象
*
* @return 缓存对象
* @throws WeixinException
*/
public T getCache() throws WeixinException {
String cacheKey = cacheCreator.key();
T cache = cacheStorager.lookup(cacheKey);
if (cache == null) {
cache = cacheCreator.create();
cacheStorager.caching(cacheKey, cache);
}
return cache;
}
/**
* 刷新缓存对象
*
* @return 缓存对象
* @throws WeixinException
*/
public T refreshCache() throws WeixinException {
String cacheKey = cacheCreator.key();
T cache = cacheCreator.create();
cacheStorager.caching(cacheKey, cache);
return cache;
}
/**
* 移除缓存
*
* @return 被移除的缓存对象
*/
public T evictCache() {
String cacheKey = cacheCreator.key();
return cacheStorager.evict(cacheKey);
}
/**
* 清除所有的缓存(<font color="red">请慎重</font>)
*/
public void clearCache() {
cacheStorager.clear();
}
}

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.token;
package com.foxinmy.weixin4j.cache;
/**
* Cache的存储
@ -9,7 +9,17 @@ package com.foxinmy.weixin4j.token;
* @since JDK 1.6
* @see
*/
public interface CacheStorager<T> {
public interface CacheStorager<T extends Cacheable> {
/**
* 考虑到临界情况,实际缓存的有效时间减去该毫秒数(60秒)
*/
long CUTMS = 60 * 1000l;
/**
* 所有的缓存KEY
*/
String ALLKEY = "weixin4j_cache_keys";
/**
* 查找缓存中的对象
*
@ -42,8 +52,6 @@ public interface CacheStorager<T> {
/**
* 清除所有缓存对象(<font color="red">请慎重</font>)
*
* @param prefix
* 缓存key的前缀
*/
void clear(String prefix);
void clear();
}

View File

@ -0,0 +1,28 @@
package com.foxinmy.weixin4j.cache;
import java.io.Serializable;
/**
* 可缓存的对象
*
* @className Cacheable
* @author jinyu(foxinmy@gmail.com)
* @date 2016年5月26日
* @since JDK 1.6
* @see
*/
public interface Cacheable extends Serializable {
/**
* 过期时间(单位:毫秒),值小于0时视为永不过期
*
* @return 缓存过期时间
*/
public long getExpires();
/**
* 创建时间(单位:毫秒)
*
* @return 缓存对象创建时间
*/
public long getCreateTime();
}

View File

@ -0,0 +1,87 @@
package com.foxinmy.weixin4j.cache;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.foxinmy.weixin4j.util.SerializationUtils;
/**
* 用File保存缓存对象
*
* @className FileCacheStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2016年5月27日
* @since JDK 1.6
* @see
*/
public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T> {
private final File tmpdir;
private final String SEPARATOR = File.separator;
public FileCacheStorager(String cachePath) {
this.tmpdir = new File(String.format("%s%sweixin4j_token_temp",
cachePath, SEPARATOR));
this.tmpdir.mkdirs();
}
@Override
public T lookup(String cacheKey) {
File cacheFile = new File(String.format("%s%s%s",
tmpdir.getAbsolutePath(), SEPARATOR, cacheKey));
try {
if (cacheFile.exists()) {
T cache = SerializationUtils.deserialize(new FileInputStream(
cacheFile));
if (cache.getCreateTime() < 0) {
return cache;
}
if ((cache.getCreateTime() + cache.getExpires() - CUTMS) > System
.currentTimeMillis()) {
return cache;
}
}
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void caching(String cacheKey, T cache) {
try {
SerializationUtils.serialize(
cache,
new FileOutputStream(new File(String.format("%s%s%s",
tmpdir.getAbsolutePath(), SEPARATOR, cacheKey))));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public T evict(String cacheKey) {
T cache = null;
File cacheFile = new File(String.format("%s%s%s",
tmpdir.getAbsolutePath(), SEPARATOR, cacheKey));
try {
if (cacheFile.exists()) {
cache = SerializationUtils.deserialize(new FileInputStream(
cacheFile));
cacheFile.delete();
}
} catch (IOException e) {
; // ingore
}
return cache;
}
@Override
public void clear() {
for (File cache : tmpdir.listFiles()) {
cache.delete();
}
}
}

View File

@ -1,61 +1,82 @@
package com.foxinmy.weixin4j.token;
package com.foxinmy.weixin4j.cache;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.foxinmy.weixin4j.model.Token;
import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;
/**
* 用Memcache保存Token信息(推荐使用)
* 用Memcache保存缓存对象(推荐使用)
*
* @className MemcacheTokenStorager
* @className MemcacheCacheStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2016年5月11日
* @since JDK 1.6
* @see
*/
public class MemcacheTokenStorager extends TokenStorager {
public class MemcacheCacheStorager<T extends Cacheable> implements
CacheStorager<T> {
private final MemCachedClient mc;
public MemcacheTokenStorager(MemcachePoolConfig poolConfig) {
public MemcacheCacheStorager() {
this(new MemcachePoolConfig());
}
public MemcacheCacheStorager(MemcachePoolConfig poolConfig) {
mc = new MemCachedClient();
poolConfig.initSocketIO();
mc.set(ALLKEY, new HashSet<String>());
}
@SuppressWarnings("unchecked")
@Override
public Token lookup(String cacheKey) {
return (Token) mc.get(cacheKey);
public T lookup(String cacheKey) {
return (T) mc.get(cacheKey);
}
@SuppressWarnings("unchecked")
@Override
public void caching(String cacheKey, Token token) {
if (token.getExpiresIn() > 0) {
mc.set(cacheKey, token,
new Date(token.getCreateTime() + token.getExpiresIn()
* 1000 - ms()));
public void caching(String cacheKey, T cache) {
if (cache.getCreateTime() > 0l) {
mc.set(cacheKey,
cache,
new Date(cache.getCreateTime() + cache.getExpires() - CUTMS));
} else {
mc.set(cacheKey, token);
mc.set(cacheKey, cache);
}
Set<String> all = (Set<String>) mc.get(ALLKEY);
all.add(cacheKey);
mc.set(ALLKEY, all);
}
@SuppressWarnings("unchecked")
@Override
public Token evict(String cacheKey) {
Token token = lookup(cacheKey);
public T evict(String cacheKey) {
T cache = lookup(cacheKey);
mc.delete(cacheKey);
return token;
Set<String> all = (Set<String>) mc.get(ALLKEY);
all.remove(cacheKey);
mc.set(ALLKEY, all);
return cache;
}
@SuppressWarnings("unchecked")
@Override
public void clear(String prefix) {
throw new UnsupportedOperationException();
public void clear() {
Set<String> all = (Set<String>) mc.get(ALLKEY);
for (String key : all) {
mc.delete(key);
}
mc.delete(ALLKEY);
}
public static class MemcachePoolConfig {
public final static String HOST = "localhost";
public final static String HOST = "127.0.0.1";
public final static int PORT = 11211;
public final static int WEIGHT = 1;

View File

@ -0,0 +1,50 @@
package com.foxinmy.weixin4j.cache;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 用内存保存缓存对象(不推荐使用)
*
* @className MemoryCacheStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2016年1月24日
* @since JDK 1.6
* @see
*/
public class MemoryCacheStorager<T extends Cacheable> implements
CacheStorager<T> {
private final Map<String, T> CONMAP;
public MemoryCacheStorager() {
this.CONMAP = new ConcurrentHashMap<String, T>();
}
@Override
public T lookup(String cacheKey) {
T cache = this.CONMAP.get(cacheKey);
if (cache != null) {
if ((cache.getCreateTime() + cache.getExpires() - CUTMS) > System
.currentTimeMillis()) {
return cache;
}
}
return null;
}
@Override
public void caching(String cacheKey, T cache) {
this.CONMAP.put(cacheKey, cache);
}
@Override
public T evict(String cacheKey) {
return this.CONMAP.remove(cacheKey);
}
@Override
public void clear() {
this.CONMAP.clear();
}
}

View File

@ -0,0 +1,13 @@
### CACHE的实现
* CacheCreator 负责创建新的缓存对象
* CacheStorager 负责查找已缓存的对象或者缓存新的对象
* TokenManager 负责对缓存对象的管理(屏蔽细节)
* FileCacheStorager 是系统默认的缓存存储策略实现
* RedisCacheStorager(RedisClusterCacheStorager) 使用redis保存缓存对象(需要自行添加客户端包,[jedis](https://github.com/xetorthio/jedis))
* MemcacheCacheStorager 使用memcache保存缓存对象(需要自行添加客户端包,[Memcached-Java-Client](https://github.com/gwhalin/Memcached-Java-Client))

View File

@ -0,0 +1,128 @@
package com.foxinmy.weixin4j.cache;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.util.SerializationUtils;
/**
* 用Redis保存缓存对象(推荐使用)
*
* @className RedisCacheStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月9日
* @since JDK 1.6
*/
public class RedisCacheStorager<T extends Cacheable> implements
CacheStorager<T> {
private JedisPool jedisPool;
private final static String HOST = "127.0.0.1";
private final static int PORT = 6379;
private final static int TIMEOUT = 5000;
private final static int MAX_TOTAL = 50;
private final static int MAX_IDLE = 5;
private final static int MAX_WAIT_MILLIS = 5000;
private final static boolean TEST_ON_BORROW = false;
private final static boolean TEST_ON_RETURN = true;
public RedisCacheStorager() {
this(HOST, PORT, TIMEOUT);
}
public RedisCacheStorager(String host, int port, int timeout) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(MAX_TOTAL);
jedisPoolConfig.setMaxIdle(MAX_IDLE);
jedisPoolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);
jedisPoolConfig.setTestOnBorrow(TEST_ON_BORROW);
jedisPoolConfig.setTestOnReturn(TEST_ON_RETURN);
this.jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout);
}
public RedisCacheStorager(JedisPoolConfig jedisPoolConfig) {
this(new JedisPool(jedisPoolConfig, HOST, PORT, TIMEOUT));
}
public RedisCacheStorager(String host, int port, int timeout,
JedisPoolConfig jedisPoolConfig) {
this(new JedisPool(jedisPoolConfig, host, port, timeout));
}
public RedisCacheStorager(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@SuppressWarnings("unchecked")
@Override
public T lookup(String cacheKey) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
byte[] value = jedis.get(cacheKey.getBytes(Consts.UTF_8));
return value != null ? (T) SerializationUtils.deserialize(value)
: null;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
@Override
public void caching(String cacheKey, T cache) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
byte[] key = cacheKey.getBytes(Consts.UTF_8);
byte[] value = SerializationUtils.serialize(cache);
jedis.set(key, value);
if (cache.getExpires() > 0) {
jedis.expire(key, (int) (cache.getExpires() - CUTMS) / 1000);
}
jedis.sadd(ALLKEY, cacheKey);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
@Override
public T evict(String cacheKey) {
T cache = lookup(cacheKey);
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(cacheKey);
jedis.srem(ALLKEY, cacheKey);
} finally {
if (jedis != null) {
jedis.close();
}
}
return cache;
}
@Override
public void clear() {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
Set<String> cacheKeys = jedis.smembers(ALLKEY);
if (!cacheKeys.isEmpty()) {
cacheKeys.add(ALLKEY);
jedis.del(cacheKeys.toArray(new String[cacheKeys.size()]));
}
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}

View File

@ -0,0 +1,94 @@
package com.foxinmy.weixin4j.cache;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.util.SerializationUtils;
/**
* 用Redis(集群)保存缓存对象(推荐使用)
*
* @className RedisCacheStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月9日
* @since JDK 1.6
*/
public class RedisClusterCacheStorager<T extends Cacheable> implements
CacheStorager<T> {
private final static int CONNECTION_TIMEOUT = 5000;
private final static int SO_TIMEOUT = 5000;
private final static int MAX_REDIRECTIONS = 5;
private final static int MAX_TOTAL = 50;
private final static int MAX_IDLE = 5;
private final static int MAX_WAIT_MILLIS = 5000;
private final static boolean TEST_ON_BORROW = false;
private final static boolean TEST_ON_RETURN = true;
private final JedisCluster jedisCluster;
public RedisClusterCacheStorager(Set<HostAndPort> nodes) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(MAX_TOTAL);
jedisPoolConfig.setMaxIdle(MAX_IDLE);
jedisPoolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);
jedisPoolConfig.setTestOnBorrow(TEST_ON_BORROW);
jedisPoolConfig.setTestOnReturn(TEST_ON_RETURN);
this.jedisCluster = new JedisCluster(nodes, CONNECTION_TIMEOUT,
SO_TIMEOUT, MAX_REDIRECTIONS, jedisPoolConfig);
}
public RedisClusterCacheStorager(Set<HostAndPort> nodes,
JedisPoolConfig poolConfig) {
this(nodes, CONNECTION_TIMEOUT, SO_TIMEOUT, MAX_REDIRECTIONS,
poolConfig);
}
public RedisClusterCacheStorager(Set<HostAndPort> nodes,
int connectionTimeout, int soTimeout, int maxRedirections,
JedisPoolConfig poolConfig) {
this(new JedisCluster(nodes, connectionTimeout, soTimeout,
maxRedirections, poolConfig));
}
public RedisClusterCacheStorager(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
@SuppressWarnings("unchecked")
@Override
public T lookup(String cacheKey) {
byte[] value = jedisCluster.get(cacheKey.getBytes(Consts.UTF_8));
return value != null ? (T) SerializationUtils.deserialize(value) : null;
}
@Override
public void caching(String cacheKey, T cache) {
byte[] key = cacheKey.getBytes(Consts.UTF_8);
byte[] value = SerializationUtils.serialize(cache);
jedisCluster.set(key, value);
if (cache.getExpires() > 0) {
jedisCluster.expire(key, (int) (cache.getExpires() - CUTMS) / 1000);
}
jedisCluster.sadd(ALLKEY, cacheKey);
}
@Override
public T evict(String cacheKey) {
T cache = lookup(cacheKey);
jedisCluster.del(cacheKey);
jedisCluster.srem(ALLKEY, cacheKey);
return cache;
}
@Override
public void clear() {
Set<String> cacheKeys = jedisCluster.smembers(ALLKEY);
if (!cacheKeys.isEmpty()) {
cacheKeys.add(ALLKEY);
jedisCluster.del(cacheKeys.toArray(new String[cacheKeys.size()]));
}
}
}

View File

@ -1431,6 +1431,10 @@
<code>81003</code>
<text>邀请额度已用完</text>
</error>
<error>
<code>81004</code>
<text>部门数量超过上限</text>
</error>
<error>
<code>82001</code>
<text>发送消息或者邀请的参数全部为空或者全部不合法</text>

View File

@ -7,7 +7,7 @@ import java.util.Set;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
@ -25,17 +25,17 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
* @see
*/
public class JSSDKConfigurator {
private final TokenHolder ticketTokenHolder;
private final TokenManager ticketTokenManager;
private JSONObject config;
private Set<JSSDKAPI> apis;
/**
* ticket保存类 可调用WeixinProxy#getTicketHolder获取
* ticket保存类 可调用WeixinProxy#getTicketManager获取
*
* @param ticketTokenHolder
* @param ticketTokenManager
*/
public JSSDKConfigurator(TokenHolder ticketTokenHolder) {
this.ticketTokenHolder = ticketTokenHolder;
public JSSDKConfigurator(TokenManager ticketTokenManager) {
this.ticketTokenManager = ticketTokenManager;
this.config = new JSONObject();
this.apis = new HashSet<JSSDKAPI>();
}
@ -113,7 +113,7 @@ public class JSSDKConfigurator {
String noncestr = RandomUtil.generateString(24);
signMap.put("timestamp", timestamp);
signMap.put("noncestr", noncestr);
signMap.put("jsapi_ticket", this.ticketTokenHolder.getAccessToken());
signMap.put("jsapi_ticket", this.ticketTokenManager.getAccessToken());
signMap.put("url", url);
String sign = DigestUtil.SHA1(MapUtil.toJoinString(signMap, false,
false));

View File

@ -6,6 +6,7 @@ import java.util.Arrays;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.type.ButtonType;
/**
@ -38,13 +39,20 @@ public class Button implements Serializable {
/**
* 菜单KEY值,根据type的类型而定</p> 通过公众平台设置的自定义菜单</br> <li>text:保存文字 <li>
* imgvoice保存媒体ID <li>video保存视频URL <li>
* news保存图文消息:List#com.foxinmy.weixin4j.tuple.MpArticle# <li>view保存链接URL
* <p>使用API设置的自定义菜单</p> <li>
* news保存图文消息媒体ID <li>view保存链接URL
* <p>
* 使用API设置的自定义菜单
* </p> <li>
* clickscancode_pushscancode_waitmsgpic_sysphotopic_photo_or_album
* pic_weixinlocation_select保存key <li>view保存链接URL; <li>
* media_idview_limited保存媒体ID
*/
private Serializable content;
private String content;
/**
* 图文列表 只有在公众平台设置的菜单才有
*/
@JSONField(serialize = false, deserialize = false)
private List<MpArticle> articles;
/**
* 二级菜单数组个数应为1~5个
*/
@ -101,14 +109,27 @@ public class Button implements Serializable {
this.type = type;
}
public Serializable getContent() {
public String getContent() {
return content;
}
public void setContent(Serializable content) {
public void setContent(String content) {
this.content = content;
}
public List<MpArticle> getArticles() {
return articles;
}
/**
* <font color="red">创建菜单设置无效</font>
*
* @param articles
*/
public void setArticles(List<MpArticle> articles) {
this.articles = articles;
}
public List<Button> getSubs() {
return subs;
}
@ -125,6 +146,6 @@ public class Button implements Serializable {
@Override
public String toString() {
return "Button [name=" + name + ", type=" + type + ", content="
+ content + ", subs=" + subs + "]";
+ content + ", articles=" + articles + ", subs=" + subs + "]";
}
}

View File

@ -1,12 +1,10 @@
package com.foxinmy.weixin4j.model;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.MediaType;
import java.io.Serializable;
import java.util.Date;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 媒体文件上传结果
*
@ -27,11 +25,8 @@ public class MediaUploadResult implements Serializable {
*/
private String url;
@JSONCreator
public MediaUploadResult(@JSONField(name = "media_id") String mediaId,
@JSONField(name = "type") MediaType mediaType,
@JSONField(name = "created_at") Date createdAt,
@JSONField(name = "url") String url) {
public MediaUploadResult(String mediaId, MediaType mediaType,
Date createdAt, String url) {
this.mediaId = mediaId;
this.mediaType = mediaType;
this.createdAt = createdAt;

View File

@ -1,8 +1,9 @@
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.cache.Cacheable;
/**
* access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,正常情况下access_token有效期为7200秒,
@ -17,75 +18,95 @@ import com.alibaba.fastjson.annotation.JSONField;
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%B8%BB%E5%8A%A8%E8%B0%83%E7%94%A8">微信企业号的主动模式</a>
*/
public class Token implements Serializable {
public class Token implements Cacheable {
private static final long serialVersionUID = -7564855472419104084L;
/**
* 获取到的凭证
*/
@JSONField(name = "access_token")
private String accessToken;
/**
* 凭证有效时间单位
* 凭证有效时间单位
*/
@JSONField(name = "expires_in")
private int expiresIn;
private long expires;
/**
* token创建的时间,单位毫秒
*/
@JSONField(name = "create_time")
private long createTime;
/**
* 请求返回的原始结果
* 扩展信息
*/
@JSONField(name = "original_result")
private String originalResult;
private Map<String, String> extra;
protected Token() {
// jaxb required
/**
* 永不过期创建时间为当前时间戳的token对象
*
* @param accessToken
* 凭证字符串
*/
public Token(String accessToken) {
this(accessToken, -1);
}
public Token(String accessToken) {
/**
* 有过期时间创建时间为当前时间戳的token对象
*
* @param accessToken
* 凭证字符串
* @param expires
* 过期时间 单位毫秒
*/
public Token(String accessToken, long expires) {
this(accessToken, expires, System.currentTimeMillis());
}
/**
*
* @param accessToken
* 凭证字符串
* @param expires
* 过期时间 单位毫秒
* @param createTime
* 创建时间戳 单位毫秒
*/
public Token(String accessToken, long expires, long createTime) {
this.accessToken = accessToken;
this.createTime = System.currentTimeMillis();
this.expires = expires;
this.createTime = createTime;
this.extra = new HashMap<String, String>();
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
@Override
public long getExpires() {
return expires;
}
@Override
public long getCreateTime() {
return createTime;
}
public void setCreateTime(long createTime) {
this.createTime = createTime;
public Map<String, String> getExtra() {
return extra;
}
public String getOriginalResult() {
return originalResult;
public void setExtra(Map<String, String> extra) {
this.extra = extra;
}
public void setOriginalResult(String originalResult) {
this.originalResult = originalResult;
public Token pushExtra(String name, String value) {
this.extra.put(name, value);
return this;
}
@Override
public String toString() {
return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn
+ ", createTime=" + createTime + "]";
return "Token [accessToken=" + accessToken + ", expires=" + expires
+ ", createTime=" + createTime + ", extra=" + extra + "]";
}
}

View File

@ -1,8 +1,6 @@
package com.foxinmy.weixin4j.setting;
import com.foxinmy.weixin4j.http.HttpParams;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenStorager;
/**
* 系统配置相关
@ -22,10 +20,6 @@ public abstract class SystemSettings<T> {
* Http参数
*/
private HttpParams httpParams;
/**
* token存储方式 默认为FileTokenStorager
*/
private TokenStorager tokenStorager;
/**
* 系统临时目录
*/
@ -59,17 +53,6 @@ public abstract class SystemSettings<T> {
public abstract String getTmpdir0();
public TokenStorager getTokenStorager() {
return tokenStorager;
}
public TokenStorager getTokenStorager0() {
if (tokenStorager == null) {
return new FileTokenStorager(getTmpdir0());
}
return tokenStorager;
}
public void setHttpParams(HttpParams httpParams) {
this.httpParams = httpParams;
}
@ -78,13 +61,9 @@ public abstract class SystemSettings<T> {
this.tmpdir = tmpdir;
}
public void setTokenStorager(TokenStorager tokenStorager) {
this.tokenStorager = tokenStorager;
}
@Override
public String toString() {
return "account=" + account + ", httpParams=" + httpParams
+ ",tokenStorager=" + tokenStorager + ", tmpdir=" + tmpdir;
+ ", tmpdir=" + tmpdir;
}
}

View File

@ -1,6 +1,9 @@
package com.foxinmy.weixin4j.setting;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.cache.FileCacheStorager;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.util.StringUtil;
@ -20,6 +23,10 @@ public class Weixin4jSettings extends SystemSettings<WeixinAccount> {
* 微信支付账号信息
*/
private WeixinPayAccount weixinPayAccount;
/**
* Token的存储方式 默认为FileCacheStorager
*/
private CacheStorager<Token> cacheStorager;
/**
* 支付接口需要的证书文件(*.p12)
*/
@ -81,6 +88,21 @@ public class Weixin4jSettings extends SystemSettings<WeixinAccount> {
return getTmpdir();
}
public CacheStorager<Token> getCacheStorager() {
return cacheStorager;
}
public CacheStorager<Token> getCacheStorager0() {
if (cacheStorager == null) {
return new FileCacheStorager<Token>(getTmpdir0());
}
return cacheStorager;
}
public void setCacheStorager(CacheStorager<Token> cacheStorager) {
this.cacheStorager = cacheStorager;
}
public String getCertificateFile() {
return certificateFile;
}

View File

@ -15,8 +15,9 @@ public abstract class AbstractWeixinSignature implements WeixinSignature {
/**
* 是否编码
*
* @return
* @return 默认false不进行编码
*/
@Override
public boolean encoder() {
return false;
}
@ -24,8 +25,9 @@ public abstract class AbstractWeixinSignature implements WeixinSignature {
/**
* 是否转换小写
*
* @return
* @return 默认false不转换小写
*/
@Override
public boolean lowerCase() {
return false;
}

View File

@ -1,95 +0,0 @@
package com.foxinmy.weixin4j.token;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.FileUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 用File形式保存Token信息
*
* @className FileTokenStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月9日
* @since JDK 1.6
*/
public class FileTokenStorager extends TokenStorager {
private final String cachePath;
public FileTokenStorager(String cachePath) {
this.cachePath = cachePath;
}
@Override
public Token lookup(String cacheKey) {
File token_file = new File(String.format("%s/%s.xml", cachePath,
cacheKey));
try {
if (token_file.exists()) {
Token token = XmlStream.fromXML(
new FileInputStream(token_file), Token.class);
if (token.getCreateTime() < 0) {
return token;
}
if ((token.getCreateTime() + (token.getExpiresIn() * 1000l) - ms()) > System
.currentTimeMillis()) {
return token;
}
}
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void caching(String cacheKey, Token token) {
try {
XmlStream.toXML(
token,
new FileOutputStream(new File(String.format("%s/%s.xml",
cachePath, cacheKey))));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public Token evict(String cacheKey) {
Token token = null;
File token_file = new File(String.format("%s/%s.xml", cachePath,
cacheKey));
try {
if (token_file.exists()) {
token = XmlStream.fromXML(new FileInputStream(token_file),
Token.class);
token_file.delete();
}
} catch (IOException e) {
; // ingore
}
return token;
}
@Override
public void clear(final String prefix) {
File[] files = new File(cachePath).listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isFile()
&& file.getName().startsWith(prefix)
&& "xml".equals(FileUtil.getFileExtension(file
.getName()));
}
});
for (File token : files) {
token.delete();
}
}
}

View File

@ -1,51 +0,0 @@
package com.foxinmy.weixin4j.token;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.foxinmy.weixin4j.model.Token;
/**
* 用内存保存Token信息(不推荐使用)
*
* @className MemoryTokenStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2016年1月24日
* @since JDK 1.6
* @see
*/
public class MemoryTokenStorager extends TokenStorager {
private final Map<String, Token> CONMAP;
public MemoryTokenStorager() {
this.CONMAP = new ConcurrentHashMap<String, Token>();
}
@Override
public Token lookup(String cacheKey) {
Token token = this.CONMAP.get(cacheKey);
if (token != null) {
if ((token.getCreateTime() + (token.getExpiresIn() * 1000l) - ms()) > System
.currentTimeMillis()) {
return token;
}
}
return null;
}
@Override
public void caching(String cacheKey, Token token) {
this.CONMAP.put(cacheKey, token);
}
@Override
public Token evict(String cacheKey) {
return this.CONMAP.remove(cacheKey);
}
@Override
public void clear(String prefix) {
this.CONMAP.clear();
}
}

View File

@ -1,13 +0,0 @@
### TOKEN的实现
* TokenCreator 负责创建新的token
* TokenStorager 负责查找已缓存的token或者缓存新的token
* TokenHolder 负责获取token(屏蔽了获取细节)
* FileTokenStorager 是系统默认的token存储策略实现
* RedisTokenStorager 使用redis保存token(需要自行添加客户端包,[jedis](https://github.com/xetorthio/jedis))
* MemcacheTokenStorager 使用memcache保存token(需要自行添加客户端包,[Memcached-Java-Client](https://github.com/gwhalin/Memcached-Java-Client))

View File

@ -1,147 +0,0 @@
package com.foxinmy.weixin4j.token;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import com.foxinmy.weixin4j.model.Token;
/**
* 用Redis保存Token信息(推荐使用)
*
* @className RedisTokenStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月9日
* @since JDK 1.6
*/
public class RedisTokenStorager extends TokenStorager {
private JedisPool jedisPool;
public final static String HOST = "localhost";
public final static int PORT = 6379;
public final static int MAX_TOTAL = 50;
public final static int MAX_IDLE = 5;
public final static int MAX_WAIT_MILLIS = 3000;
public final static boolean TEST_ON_BORROW = false;
public final static boolean TEST_ON_RETURN = true;
public RedisTokenStorager() {
this(HOST, PORT);
}
public RedisTokenStorager(String host, int port) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(MAX_TOTAL);
jedisPoolConfig.setMaxIdle(MAX_IDLE);
jedisPoolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);
jedisPoolConfig.setTestOnBorrow(TEST_ON_BORROW);
jedisPoolConfig.setTestOnReturn(TEST_ON_RETURN);
this.jedisPool = new JedisPool(jedisPoolConfig, host, port);
}
public RedisTokenStorager(String host, int port,
JedisPoolConfig jedisPoolConfig) {
this(new JedisPool(jedisPoolConfig, host, port));
}
public RedisTokenStorager(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public Token lookup(String cacheKey) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
Map<String, String> map = jedis.hgetAll(cacheKey);
if (map != null && !map.isEmpty()) {
return map2token(map);
}
} finally {
if (jedis != null) {
jedis.close();
}
}
return null;
}
@Override
public void caching(String cacheKey, Token token) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.hmset(cacheKey, token2map(token));
if (token.getExpiresIn() > 0) {
jedis.expire(cacheKey, token.getExpiresIn()
- (int) (ms() / 1000l));
}
} finally {
if (jedis != null) {
jedis.close();
}
}
}
private final static String ACCESSTOKEN_KEY = "accessToken";
private final static String EXPIRESIN_KEY = "expiresIn";
private final static String CREATETIME_KEY = "createTime";
private final static String ORIGINAL_KEY = "originalResult";
protected Map<String, String> token2map(Token token) {
Map<String, String> map = new HashMap<String, String>();
map.put(ACCESSTOKEN_KEY, token.getAccessToken());
map.put(EXPIRESIN_KEY, Integer.toString(token.getExpiresIn()));
map.put(CREATETIME_KEY, Long.toString(token.getCreateTime()));
map.put(ORIGINAL_KEY, token.getOriginalResult());
return map;
}
protected Token map2token(Map<String, String> map) {
Token token = new Token(map.get(ACCESSTOKEN_KEY));
token.setExpiresIn(Integer.parseInt(map.get(EXPIRESIN_KEY)));
token.setCreateTime(Long.parseLong(map.get(CREATETIME_KEY)));
token.setOriginalResult(map.get(ORIGINAL_KEY));
return token;
}
@Override
public Token evict(String cacheKey) {
Token token = lookup(cacheKey);
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(cacheKey);
} finally {
if (jedis != null) {
jedis.close();
}
}
return token;
}
@Override
public void clear(String prefix) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
Set<String> cacheKeys = jedis.keys(String.format("%s*", prefix));
if (!cacheKeys.isEmpty()) {
Pipeline pipeline = jedis.pipelined();
for (String cacheKey : cacheKeys) {
pipeline.del(cacheKey);
}
pipeline.sync();
}
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}

View File

@ -1,5 +1,6 @@
package com.foxinmy.weixin4j.token;
import com.foxinmy.weixin4j.cache.CacheCreator;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.model.Token;
@ -14,21 +15,17 @@ import com.foxinmy.weixin4j.model.Token;
*/
public abstract class TokenCreator implements CacheCreator<Token> {
/**
* 缓存KEY前缀
*/
public final static String CACHEKEY_PREFIX = "weixin4j_";
protected final WeixinRequestExecutor weixinExecutor;
public TokenCreator() {
this.weixinExecutor = new WeixinRequestExecutor();
}
/**
* 缓存key的前缀
*
* @return 默认为weixin4j_
*/
public String prefix() {
return "weixin4j_";
}
/**
* 缓存key:附加key前缀
*
@ -36,7 +33,7 @@ public abstract class TokenCreator implements CacheCreator<Token> {
*/
@Override
public String key() {
return String.format("%s%s", prefix(), key0());
return String.format("%s%s", CACHEKEY_PREFIX, key0());
}
/**

View File

@ -1,95 +0,0 @@
package com.foxinmy.weixin4j.token;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Token;
/**
* 对token的缓存获取
*
* @className TokenHolder
* @author jinyu(foxinmy@gmail.com)
* @date 2015年6月12日
* @since JDK 1.6
* @see TokenCreator
* @see TokenStorager
*/
public class TokenHolder {
/**
* token的创建
*/
private final TokenCreator tokenCreator;
/**
* token的存储
*/
private final TokenStorager tokenStorager;
/**
*
* @param tokenCreator
* token创建器
* @param tokenStorager
* token保存器
*/
public TokenHolder(TokenCreator tokenCreator, TokenStorager tokenStorager) {
this.tokenCreator = tokenCreator;
this.tokenStorager = tokenStorager;
}
/**
* 获取token对象
*
* @return
* @throws WeixinException
*/
public Token getToken() throws WeixinException {
String cacheKey = tokenCreator.key();
Token token = tokenStorager.lookup(cacheKey);
if (token == null) {
token = tokenCreator.create();
tokenStorager.caching(cacheKey, token);
}
return token;
}
/**
* 获取token字符串
*
* @return
* @throws WeixinException
*/
public String getAccessToken() throws WeixinException {
return getToken().getAccessToken();
}
/**
* 手动刷新token
*
* @return 刷新后的token
* @throws WeixinException
*/
public Token refreshToken() throws WeixinException {
String cacheKey = tokenCreator.key();
Token token = tokenCreator.create();
tokenStorager.caching(cacheKey, token);
return token;
}
/**
* 移除token
*
* @return 被移除的token
*/
public Token evictToken() {
String cacheKey = tokenCreator.key();
return tokenStorager.evict(cacheKey);
}
/**
* 清除所有的token(<font color="red">请慎重</font>)
*/
public void clearToken() {
String prefix = tokenCreator.prefix();
tokenStorager.clear(prefix);
}
}

View File

@ -0,0 +1,41 @@
package com.foxinmy.weixin4j.token;
import com.foxinmy.weixin4j.cache.CacheManager;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Token;
/**
* 对token的缓存获取
*
* @className TokenManager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年6月12日
* @since JDK 1.6
* @see TokenCreator
* @see com.foxinmy.weixin4j.cache.CacheStorager
*/
public class TokenManager extends CacheManager<Token> {
/**
*
* @param tokenCreator
* 负责微信各种token的创建
* @param cacheStorager
* 负责token的存储
*/
public TokenManager(TokenCreator tokenCreator,
CacheStorager<Token> cacheStorager) {
super(tokenCreator, cacheStorager);
}
/**
* 获取token字符串
*
* @return
* @throws WeixinException
*/
public String getAccessToken() throws WeixinException {
return super.getCache().getAccessToken();
}
}

View File

@ -1,27 +0,0 @@
package com.foxinmy.weixin4j.token;
import com.foxinmy.weixin4j.model.Token;
/**
* Token的存储
*
* @className TokenStorager
* @author jinyu(foxinmy@gmail.com)
* @date 2014年9月27日
* @since JDK 1.6
* @see com.foxinmy.weixin4j.model.Token
* @see MemoryTokenStorager
* @see FileTokenStorager
* @see RedisTokenStorager
* @see MemcacheTokenStorager
*/
public abstract class TokenStorager implements CacheStorager<Token> {
/**
* 考虑到临界情况,实际token的有效时间减去该毫秒数
*
* @return 默认为60秒
*/
public long ms() {
return 60 * 1000l;
}
}

View File

@ -43,6 +43,17 @@ public class Article implements Serializable {
@XmlElement(name = "Url")
private String url;
/**
*
* @param title
* 标题
* @param desc
* 描述
* @param picUrl
* 图片链接
* @param url
* 跳转URL
*/
@JSONCreator
public Article(@JSONField(name = "title") String title,
@JSONField(name = "desc") String desc,

View File

@ -2,12 +2,12 @@ package com.foxinmy.weixin4j.tuple;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 群发消息图文(消息内容存储在微信后台)
*
* @className MpArticle
* @author jinyu(foxinmy@gmail.com)
* @date 2014年4月26日
* @since JDK 1.6
@ -22,7 +22,7 @@ public class MpArticle implements Serializable {
@JSONField(name = "thumb_media_id")
private String thumbMediaId;
/**
* 图文消息的封面图片的地址第三方开发者也可以使用这个URL下载图片到自己服务器中然后显示在自己网站上
* 图文消息的封面图片的地址(不一定有请关注thumbMediaId)
*/
@JSONField(name = "thumb_url")
private String thumbUrl;
@ -34,6 +34,10 @@ public class MpArticle implements Serializable {
* 图文消息的标题 非空
*/
private String title;
/**
* 图文页的URL 获取图文消息时
*/
private String url;
/**
* 在图文消息页面点击阅读原文后的页面 可为空
*/
@ -52,50 +56,40 @@ public class MpArticle implements Serializable {
*/
@JSONField(name = "show_cover_pic")
private String showCoverPic;
/**
* 正文的URL 可为空
*/
@JSONField(name = "content_url")
private String contentUrl;
/**
* 封面图片的URL 可为空
*/
@JSONField(name = "cover_url")
private String coverUrl;
protected MpArticle() {
}
/**
* @param thumbMediaId
* 缩略图
* @param title
* 标题
* @param content
* 内容
*/
public MpArticle(String thumbMediaId, String title, String content) {
this.thumbMediaId = thumbMediaId;
this.title = title;
this.content = content;
}
@JSONCreator
public MpArticle(@JSONField(name = "thumbMediaId") String thumbMediaId,
@JSONField(name = "thumbUrl") String thumbUrl,
@JSONField(name = "author") String author,
@JSONField(name = "title") String title,
@JSONField(name = "sourceUrl") String sourceUrl,
@JSONField(name = "content") String content,
@JSONField(name = "digest") String digest,
@JSONField(name = "showCoverPic") String showCoverPic,
@JSONField(name = "contentUrl") String contentUrl,
@JSONField(name = "coverUrl") String coverUrl) {
this.thumbMediaId = thumbMediaId;
this.thumbUrl = thumbUrl;
this.author = author;
this.title = title;
this.sourceUrl = sourceUrl;
this.content = content;
this.digest = digest;
this.showCoverPic = showCoverPic;
this.contentUrl = contentUrl;
this.coverUrl = coverUrl;
}
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
public String getThumbUrl() {
return thumbUrl;
}
public void setThumbUrl(String thumbUrl) {
this.thumbUrl = thumbUrl;
}
public String getAuthor() {
return author;
}
@ -108,6 +102,18 @@ public class MpArticle implements Serializable {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getSourceUrl() {
return sourceUrl;
}
@ -120,6 +126,10 @@ public class MpArticle implements Serializable {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDigest() {
return digest;
}
@ -132,36 +142,25 @@ public class MpArticle implements Serializable {
return showCoverPic;
}
public void setShowCoverPic(String showCoverPic) {
this.showCoverPic = showCoverPic;
}
public void setShowCoverPic(boolean showCoverPic) {
this.showCoverPic = showCoverPic ? "1" : "0";
}
public String getContentUrl() {
return contentUrl;
}
public void setContentUrl(String contentUrl) {
this.contentUrl = contentUrl;
}
public String getCoverUrl() {
return coverUrl;
}
public void setCoverUrl(String coverUrl) {
this.coverUrl = coverUrl;
}
public String getThumbUrl() {
return thumbUrl;
@JSONField(serialize = false)
public boolean getFormatShowCoverPic() {
return this.showCoverPic != null && this.showCoverPic.equals("1");
}
@Override
public String toString() {
return "MpArticle [thumbMediaId=" + thumbMediaId + ",thumbUrl="
return "MpArticle [thumbMediaId=" + thumbMediaId + ", thumbUrl="
+ thumbUrl + ", author=" + author + ", title=" + title
+ ", sourceUrl=" + sourceUrl + ", content=" + content
+ ", digest=" + digest + ", showCoverPic=" + showCoverPic
+ ", contentUrl=" + contentUrl + ", coverUrl=" + coverUrl + "]";
+ ", url=" + url + ", digest=" + digest + ", showCoverPic="
+ showCoverPic + "]";
}
}

View File

@ -1,19 +1,21 @@
package com.foxinmy.weixin4j.tuple;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 图文对象(mpnews消息与news消息类似不同的是图文消息内容存储在微信后台并且支持保密选项每个应用每天最多可以发送100次)
* <p>
* <font color="red">可用于群发消息(其中mediaId与articles请至少保持一个有值)企业号的客服消息</font>
* <font color="red">可用于公众平台的群发消息客服消息</font>
* </p>
* <li>当用于发送公众平台的群发消息和客服消息时其中mediaId与articles请至少保持一个有值 <li>
* 当用于发送企业号的客服消息时其中articles必须有值
*
* @className MpNews
* @author jinyu(foxinmy@gmail.com)
@ -47,16 +49,35 @@ public class MpNews implements MassTuple, NotifyTuple {
@XmlTransient
private LinkedList<MpArticle> articles;
public MpNews() {
this(null);
}
@JSONCreator
public MpNews(@JSONField(name = "mediaId") String mediaId) {
/**
* 群发消息客服消息 预先上传List#MpArticle得到mediaId
*
* @param mediaId
* 群发素材的媒体ID
*/
public MpNews(String mediaId) {
this.mediaId = mediaId;
this.articles = new LinkedList<MpArticle>();
}
/**
* 群发消息 自动上传List#MpArticle得到mediaId
*
* @param articles
* 文章列表
*/
public MpNews(MpArticle... articles) {
this.articles = new LinkedList<MpArticle>(Arrays.asList(articles));
}
/**
* @param thumbMediaId
* 缩略图
* @param title
* 标题
* @param content
* 内容
*/
public MpNews addArticle(String thumbMediaId, String title, String content) {
return addArticle(new MpArticle(thumbMediaId, title, content));
}

View File

@ -55,10 +55,32 @@ public class Music implements NotifyTuple {
@XmlElement(name = "ThumbMediaId")
private String thumbMediaId;
/**
*
* @param musicUrl
* 音乐链接
* @param hqMusicUrl
* 高品质音乐链接
* @param thumbMediaId
* 缩略图
*/
public Music(String musicUrl, String hqMusicUrl, String thumbMediaId) {
this(null, null, musicUrl, hqMusicUrl, thumbMediaId);
}
/**
*
* @param title
* 标题
* @param desc
* 描述
* @param musicUrl
* 音乐链接
* @param hqMusicUrl
* 高品质音乐链接
* @param thumbMediaId
* 缩略图
*/
public Music(@JSONField(name = "title") String title,
@JSONField(name = "desc") String desc,
@JSONField(name = "musicUrl") String musicUrl,

View File

@ -47,6 +47,17 @@ public class News implements NotifyTuple {
this.articles = new LinkedList<Article>();
}
/**
*
* @param title
* 标题
* @param desc
* 描述
* @param picUrl
* 图片链接
* @param url
* 跳转URL
*/
public News addArticle(String title, String desc, String picUrl, String url) {
return addArticle(new Article(title, desc, picUrl, url));
}

View File

@ -65,6 +65,18 @@ public class Video implements NotifyTuple {
this(mediaId, null, title, desc);
}
/**
* 公众平台发送视频消息
*
* @param mediaId
* 视频媒体文件id可以调用上传临时素材或者永久素材接口获取
* @param thumbMediaId
* 视频缩略图
* @param title
* 视频标题
* @param desc
* 视频描述
*/
@JSONCreator
public Video(@JSONField(name = "mediaId") String mediaId,
@JSONField(name = "thumbMediaId") String thumbMediaId,

View File

@ -0,0 +1,339 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.foxinmy.weixin4j.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* <p>Assists with the serialization process and performs additional functionality based
* on serialization.</p>
*
* <ul>
* <li>Deep clone using serialization
* <li>Serialize managing finally and IOException
* <li>Deserialize managing finally and IOException
* </ul>
*
* <p>This class throws exceptions for invalid {@code null} inputs.
* Each method documents its behaviour in more detail.</p>
*
* <p>#ThreadSafe#</p>
* @since 1.0
* @version $Id: SerializationUtils.java 1583482 2014-03-31 22:54:57Z niallp $
*/
public class SerializationUtils {
/**
* <p>SerializationUtils instances should NOT be constructed in standard programming.
* Instead, the class should be used as {@code SerializationUtils.clone(object)}.</p>
*
* <p>This constructor is public to permit tools that require a JavaBean instance
* to operate.</p>
* @since 2.0
*/
public SerializationUtils() {
super();
}
// Clone
//-----------------------------------------------------------------------
/**
* <p>Deep clone an {@code Object} using serialization.</p>
*
* <p>This is many times slower than writing clone methods by hand
* on all objects in your object graph. However, for complex object
* graphs, or for those that don't support deep cloning this can
* be a simple alternative implementation. Of course all the objects
* must be {@code Serializable}.</p>
*
* @param <T> the type of the object involved
* @param object the {@code Serializable} object to clone
* @return the cloned object
* @throws SerializationException (runtime) if the serialization fails
*/
public static <T extends Serializable> T clone(final T object) {
if (object == null) {
return null;
}
final byte[] objectData = serialize(object);
final ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
ClassLoaderAwareObjectInputStream in = null;
try {
// stream closed in the finally
in = new ClassLoaderAwareObjectInputStream(bais, object.getClass().getClassLoader());
/*
* when we serialize and deserialize an object,
* it is reasonable to assume the deserialized object
* is of the same type as the original serialized object
*/
@SuppressWarnings("unchecked") // see above
final
T readObject = (T) in.readObject();
return readObject;
} catch (final ClassNotFoundException ex) {
throw new RuntimeException("ClassNotFoundException while reading cloned object data", ex);
} catch (final IOException ex) {
throw new RuntimeException("IOException while reading cloned object data", ex);
} finally {
try {
if (in != null) {
in.close();
}
} catch (final IOException ex) {
throw new RuntimeException("IOException on closing cloned object data InputStream.", ex);
}
}
}
/**
* Performs a serialization roundtrip. Serializes and deserializes the given object, great for testing objects that
* implement {@link Serializable}.
*
* @param <T>
* the type of the object involved
* @param msg
* the object to roundtrip
* @return the serialized and deseralized object
* @since 3.3
*/
public static <T extends Serializable> T roundtrip(final T msg) {
return SerializationUtils.deserialize(SerializationUtils.serialize(msg));
}
// Serialize
//-----------------------------------------------------------------------
/**
* <p>Serializes an {@code Object} to the specified stream.</p>
*
* <p>The stream will be closed once the object is written.
* This avoids the need for a finally clause, and maybe also exception
* handling, in the application code.</p>
*
* <p>The stream passed in is not buffered internally within this method.
* This is the responsibility of your application if desired.</p>
*
* @param obj the object to serialize to bytes, may be null
* @param outputStream the stream to write to, must not be null
* @throws IllegalArgumentException if {@code outputStream} is {@code null}
* @throws SerializationException (runtime) if the serialization fails
*/
public static void serialize(final Serializable obj, final OutputStream outputStream) {
if (outputStream == null) {
throw new IllegalArgumentException("The OutputStream must not be null");
}
ObjectOutputStream out = null;
try {
// stream closed in the finally
out = new ObjectOutputStream(outputStream);
out.writeObject(obj);
} catch (final IOException ex) {
throw new RuntimeException(ex);
} finally {
try {
if (out != null) {
out.close();
}
} catch (final IOException ex) { // NOPMD
// ignore close exception
}
}
}
/**
* <p>Serializes an {@code Object} to a byte array for
* storage/serialization.</p>
*
* @param obj the object to serialize to bytes
* @return a byte[] with the converted Serializable
* @throws SerializationException (runtime) if the serialization fails
*/
public static byte[] serialize(final Serializable obj) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
serialize(obj, baos);
return baos.toByteArray();
}
// Deserialize
//-----------------------------------------------------------------------
/**
* <p>
* Deserializes an {@code Object} from the specified stream.
* </p>
*
* <p>
* The stream will be closed once the object is written. This avoids the need for a finally clause, and maybe also
* exception handling, in the application code.
* </p>
*
* <p>
* The stream passed in is not buffered internally within this method. This is the responsibility of your
* application if desired.
* </p>
*
* <p>
* If the call site incorrectly types the return value, a {@link ClassCastException} is thrown from the call site.
* Without Generics in this declaration, the call site must type cast and can cause the same ClassCastException.
* Note that in both cases, the ClassCastException is in the call site, not in this method.
* </p>
*
* @param <T> the object type to be deserialized
* @param inputStream
* the serialized object input stream, must not be null
* @return the deserialized object
* @throws IllegalArgumentException
* if {@code inputStream} is {@code null}
* @throws SerializationException
* (runtime) if the serialization fails
*/
public static <T> T deserialize(final InputStream inputStream) {
if (inputStream == null) {
throw new IllegalArgumentException("The InputStream must not be null");
}
ObjectInputStream in = null;
try {
// stream closed in the finally
in = new ObjectInputStream(inputStream);
@SuppressWarnings("unchecked") // may fail with CCE if serialised form is incorrect
final T obj = (T) in.readObject();
return obj;
} catch (final ClassCastException ex) {
throw new RuntimeException(ex);
} catch (final ClassNotFoundException ex) {
throw new RuntimeException(ex);
} catch (final IOException ex) {
throw new RuntimeException(ex);
} finally {
try {
if (in != null) {
in.close();
}
} catch (final IOException ex) { // NOPMD
// ignore close exception
}
}
}
/**
* <p>
* Deserializes a single {@code Object} from an array of bytes.
* </p>
*
* <p>
* If the call site incorrectly types the return value, a {@link ClassCastException} is thrown from the call site.
* Without Generics in this declaration, the call site must type cast and can cause the same ClassCastException.
* Note that in both cases, the ClassCastException is in the call site, not in this method.
* </p>
*
* @param <T> the object type to be deserialized
* @param objectData
* the serialized object, must not be null
* @return the deserialized object
* @throws IllegalArgumentException
* if {@code objectData} is {@code null}
* @throws SerializationException
* (runtime) if the serialization fails
*/
public static <T> T deserialize(final byte[] objectData) {
if (objectData == null) {
throw new IllegalArgumentException("The byte[] must not be null");
}
return SerializationUtils.<T>deserialize(new ByteArrayInputStream(objectData));
}
/**
* <p>Custom specialization of the standard JDK {@link java.io.ObjectInputStream}
* that uses a custom <code>ClassLoader</code> to resolve a class.
* If the specified <code>ClassLoader</code> is not able to resolve the class,
* the context classloader of the current thread will be used.
* This way, the standard deserialization work also in web-application
* containers and application servers, no matter in which of the
* <code>ClassLoader</code> the particular class that encapsulates
* serialization/deserialization lives. </p>
*
* <p>For more in-depth information about the problem for which this
* class here is a workaround, see the JIRA issue LANG-626. </p>
*/
static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
private static final Map<String, Class<?>> primitiveTypes =
new HashMap<String, Class<?>>();
private final ClassLoader classLoader;
/**
* Constructor.
* @param in The <code>InputStream</code>.
* @param classLoader classloader to use
* @throws IOException if an I/O error occurs while reading stream header.
* @see java.io.ObjectInputStream
*/
public ClassLoaderAwareObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException {
super(in);
this.classLoader = classLoader;
primitiveTypes.put("byte", byte.class);
primitiveTypes.put("short", short.class);
primitiveTypes.put("int", int.class);
primitiveTypes.put("long", long.class);
primitiveTypes.put("float", float.class);
primitiveTypes.put("double", double.class);
primitiveTypes.put("boolean", boolean.class);
primitiveTypes.put("char", char.class);
primitiveTypes.put("void", void.class);
}
/**
* Overriden version that uses the parametrized <code>ClassLoader</code> or the <code>ClassLoader</code>
* of the current <code>Thread</code> to resolve the class.
* @param desc An instance of class <code>ObjectStreamClass</code>.
* @return A <code>Class</code> object corresponding to <code>desc</code>.
* @throws IOException Any of the usual Input/Output exceptions.
* @throws ClassNotFoundException If class of a serialized object cannot be found.
*/
@Override
protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
final String name = desc.getName();
try {
return Class.forName(name, false, classLoader);
} catch (final ClassNotFoundException ex) {
try {
return Class.forName(name, false, Thread.currentThread().getContextClassLoader());
} catch (final ClassNotFoundException cnfe) {
final Class<?> cls = primitiveTypes.get(name);
if (cls != null) {
return cls;
} else {
throw cnfe;
}
}
}
}
}
}

View File

@ -4,6 +4,7 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinAccount;
/**
@ -23,7 +24,7 @@ public class Weixin4jConfigUtil {
CLASSPATH_VALUE = Thread.currentThread().getContextClassLoader()
.getResource("").getPath();
try {
weixinBundle = ResourceBundle.getBundle("weixin4j");
weixinBundle = ResourceBundle.getBundle(Consts.WEIXIN4J);
} catch (MissingResourceException e) {
;
}

View File

@ -84,5 +84,10 @@
<version>1.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@ -51,7 +51,7 @@ import com.foxinmy.weixin4j.mp.type.DatacubeType;
import com.foxinmy.weixin4j.mp.type.IndustryType;
import com.foxinmy.weixin4j.mp.type.Lang;
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MassTuple;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.tuple.MpVideo;
@ -121,7 +121,7 @@ public class WeixinProxy {
/**
* token实现
*/
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
/**
* 配置信息
*/
@ -141,9 +141,9 @@ public class WeixinProxy {
* @see com.foxinmy.weixin4j.setting.Weixin4jSettings
*/
public WeixinProxy(Weixin4jSettings settings) {
this(new TokenHolder(new WeixinTokenCreator(settings.getAccount()
this(new TokenManager(new WeixinTokenCreator(settings.getAccount()
.getId(), settings.getAccount().getSecret()),
settings.getTokenStorager0()));
settings.getCacheStorager0()));
this.settings = settings;
}
@ -151,22 +151,22 @@ public class WeixinProxy {
* 注意TokenCreator 需为 <font color="red">WeixinTokenCreator</font>
*
* @see com.foxinmy.weixin4j.mp.token.WeixinTokenCreator
* @param tokenHolder
* @param tokenManager
*/
private WeixinProxy(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
this.mediaApi = new MediaApi(tokenHolder);
this.notifyApi = new NotifyApi(tokenHolder);
this.customApi = new CustomApi(tokenHolder);
this.massApi = new MassApi(tokenHolder);
this.userApi = new UserApi(tokenHolder);
this.groupApi = new GroupApi(tokenHolder);
this.menuApi = new MenuApi(tokenHolder);
this.qrApi = new QrApi(tokenHolder);
this.tmplApi = new TmplApi(tokenHolder);
this.helperApi = new HelperApi(tokenHolder);
this.dataApi = new DataApi(tokenHolder);
this.tagApi = new TagApi(tokenHolder);
private WeixinProxy(TokenManager tokenManager) {
this.tokenManager = tokenManager;
this.mediaApi = new MediaApi(tokenManager);
this.notifyApi = new NotifyApi(tokenManager);
this.customApi = new CustomApi(tokenManager);
this.massApi = new MassApi(tokenManager);
this.userApi = new UserApi(tokenManager);
this.groupApi = new GroupApi(tokenManager);
this.menuApi = new MenuApi(tokenManager);
this.qrApi = new QrApi(tokenManager);
this.tmplApi = new TmplApi(tokenManager);
this.helperApi = new HelperApi(tokenManager);
this.dataApi = new DataApi(tokenManager);
this.tagApi = new TagApi(tokenManager);
}
/**
@ -179,25 +179,25 @@ public class WeixinProxy {
}
/**
* token获取
* token管理
*
* @return
*/
public TokenHolder getTokenHolder() {
return this.tokenHolder;
public TokenManager getTokenManager() {
return this.tokenManager;
}
/**
* 获取JSSDK Ticket的tokenHolder
* 获取JSSDK Ticket的tokenManager
*
* @param ticketType
* 票据类型
* @return
*/
public TokenHolder getTicketHolder(TicketType ticketType) {
return new TokenHolder(new WeixinTicketCreator(getWeixinAccount()
.getId(), ticketType, this.tokenHolder),
this.settings.getTokenStorager0());
public TokenManager getTicketManager(TicketType ticketType) {
return new TokenManager(new WeixinTicketCreator(getWeixinAccount()
.getId(), ticketType, this.tokenManager),
this.settings.getCacheStorager0());
}
/**

View File

@ -20,7 +20,7 @@ import com.foxinmy.weixin4j.mp.model.KfAccount;
import com.foxinmy.weixin4j.mp.model.KfChatRecord;
import com.foxinmy.weixin4j.mp.model.KfSession;
import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.FileUtil;
import com.foxinmy.weixin4j.util.ObjectId;
@ -37,10 +37,10 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class CustomApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public CustomApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public CustomApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -62,7 +62,7 @@ public class CustomApi extends MpApi {
public List<KfChatRecord> getKfChatRecord(Date startTime, Date endTime, Pageable pageable) throws WeixinException {
List<KfChatRecord> records = new ArrayList<KfChatRecord>();
String kf_chatrecord_uri = getRequestUri("kf_chatrecord_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("starttime", startTime.getTime() / 1000);
obj.put("endtime", endTime.getTime() / 1000);
@ -100,7 +100,7 @@ public class CustomApi extends MpApi {
* @throws WeixinException
*/
public List<KfAccount> listKfAccount(boolean isOnline) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String text = "";
if (isOnline) {
String kf_onlinelist_uri = getRequestUri("kf_onlinelist_uri");
@ -136,7 +136,7 @@ public class CustomApi extends MpApi {
obj.put("nickname", name);
obj.put("password", DigestUtil.MD5(pwd));
String kf_create_uri = getRequestUri("kf_create_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(kf_create_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
@ -164,7 +164,7 @@ public class CustomApi extends MpApi {
obj.put("nickname", name);
obj.put("password", DigestUtil.MD5(pwd));
String kf_update_uri = getRequestUri("kf_update_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(kf_update_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
@ -190,7 +190,7 @@ public class CustomApi extends MpApi {
obj.put("kf_account", kfAccount);
obj.put("invite_wx", inviteAccount);
String kf_invite_uri = getRequestUri("kf_invite_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(kf_invite_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
@ -218,7 +218,7 @@ public class CustomApi extends MpApi {
if (StringUtil.isBlank(FileUtil.getFileExtension(fileName))) {
fileName = String.format("%s.jpg", fileName);
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kf_avatar_uri = getRequestUri("kf_avatar_uri");
WeixinResponse response = weixinExecutor.post(String.format(kf_avatar_uri, token.getAccessToken(), accountId),
new FormBodyPart("media", new InputStreamBody(is, ContentType.IMAGE_JPG.getMimeType(), fileName)));
@ -238,7 +238,7 @@ public class CustomApi extends MpApi {
* 删除客服账号</a>
*/
public JsonResult deleteKfAccount(String id) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kf_delete_uri = getRequestUri("kf_delete_uri");
WeixinResponse response = weixinExecutor.get(String.format(kf_delete_uri, token.getAccessToken(), id));
@ -265,7 +265,7 @@ public class CustomApi extends MpApi {
* 创建会话</a>
*/
public JsonResult createKfSession(String userOpenId, String kfAccount, String text) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kfsession_create_uri = getRequestUri("kfsession_create_uri");
JSONObject obj = new JSONObject();
obj.put("openid", userOpenId);
@ -293,7 +293,7 @@ public class CustomApi extends MpApi {
* 关闭会话</a>
*/
public JsonResult closeKfSession(String userOpenId, String kfAccount, String text) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kfsession_close_uri = getRequestUri("kfsession_close_uri");
JSONObject obj = new JSONObject();
obj.put("openid", userOpenId);
@ -318,7 +318,7 @@ public class CustomApi extends MpApi {
* 获取会话状态</a>
*/
public KfSession getKfSession(String userOpenId) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kfsession_get_uri = getRequestUri("kfsession_get_uri");
WeixinResponse response = weixinExecutor
.get(String.format(kfsession_get_uri, token.getAccessToken(), userOpenId));
@ -342,7 +342,7 @@ public class CustomApi extends MpApi {
* 获取客服的会话列表</a>
*/
public List<KfSession> listKfSession(String kfAccount) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kfsession_list_uri = getRequestUri("kfsession_list_uri");
WeixinResponse response = weixinExecutor
.get(String.format(kfsession_list_uri, token.getAccessToken(), kfAccount));
@ -364,7 +364,7 @@ public class CustomApi extends MpApi {
* 获取客服的会话列表</a>
*/
public KfSessionCounter listKfWaitSession() throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String kfsession_wait_uri = getRequestUri("kfsession_wait_uri");
WeixinResponse response = weixinExecutor.get(String.format(kfsession_wait_uri, token.getAccessToken()));

View File

@ -10,7 +10,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.type.DatacubeType;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.DateUtil;
/**
@ -27,10 +27,10 @@ import com.foxinmy.weixin4j.util.DateUtil;
* @see
*/
public class DataApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public DataApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public DataApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -119,7 +119,7 @@ public class DataApi extends MpApi {
public List<?> datacube(DatacubeType datacubeType, Date beginDate,
Date endDate) throws WeixinException {
String datacube_uri = getRequestUri("datacube_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("begin_date", DateUtil.fortmat2yyyy_MM_dd(beginDate));
obj.put("end_date", DateUtil.fortmat2yyyy_MM_dd(endDate));

View File

@ -9,7 +9,7 @@ import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.Group;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 分组相关API
@ -22,10 +22,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
*/
public class GroupApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public GroupApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public GroupApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -42,7 +42,7 @@ public class GroupApi extends MpApi {
*/
public Group createGroup(String name) throws WeixinException {
String group_create_uri = getRequestUri("group_create_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
Group group = new Group(name);
WeixinResponse response = weixinExecutor.post(
String.format(group_create_uri, token.getAccessToken()),
@ -62,7 +62,7 @@ public class GroupApi extends MpApi {
*/
public List<Group> getGroups() throws WeixinException {
String group_get_uri = getRequestUri("group_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(group_get_uri,
token.getAccessToken()));
@ -83,7 +83,7 @@ public class GroupApi extends MpApi {
*/
public int getGroupByOpenId(String openId) throws WeixinException {
String group_getid_uri = getRequestUri("group_getid_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(group_getid_uri, token.getAccessToken()),
String.format("{\"openid\":\"%s\"}", openId));
@ -107,7 +107,7 @@ public class GroupApi extends MpApi {
public JsonResult modifyGroup(int groupId, String name)
throws WeixinException {
String group_modify_uri = getRequestUri("group_modify_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
Group group = new Group(groupId, name);
WeixinResponse response = weixinExecutor.post(
@ -131,7 +131,7 @@ public class GroupApi extends MpApi {
public JsonResult moveGroup(int groupId, String openId)
throws WeixinException {
String group_move_uri = getRequestUri("group_move_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(group_move_uri,
token.getAccessToken()), String.format(
"{\"openid\":\"%s\",\"to_groupid\":%d}", openId, groupId));
@ -154,7 +154,7 @@ public class GroupApi extends MpApi {
public JsonResult moveGroup(int groupId, String... openIds)
throws WeixinException {
String group_batchmove_uri = getRequestUri("group_batchmove_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("to_groupid", groupId);
obj.put("openid_list", openIds);
@ -177,7 +177,7 @@ public class GroupApi extends MpApi {
*/
public JsonResult deleteGroup(int groupId) throws WeixinException {
String group_delete_uri = getRequestUri("group_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(group_delete_uri, token.getAccessToken()),
String.format("{\"group\":{\"id\":%d}}", groupId));

View File

@ -17,9 +17,10 @@ import com.foxinmy.weixin4j.mp.model.AutoReplySetting;
import com.foxinmy.weixin4j.mp.model.MenuSetting;
import com.foxinmy.weixin4j.mp.model.SemQuery;
import com.foxinmy.weixin4j.mp.model.SemResult;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.type.ButtonType;
import com.foxinmy.weixin4j.util.ReflectionUtil;
/**
* 辅助相关API
@ -32,10 +33,10 @@ import com.foxinmy.weixin4j.type.ButtonType;
*/
public class HelperApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public HelperApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public HelperApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -50,7 +51,7 @@ public class HelperApi extends MpApi {
*/
public String getShorturl(String url) throws WeixinException {
String shorturl_uri = getRequestUri("shorturl_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("action", "long2short");
obj.put("long_url", url);
@ -75,7 +76,7 @@ public class HelperApi extends MpApi {
*/
public SemResult semantic(SemQuery semQuery) throws WeixinException {
String semantic_uri = getRequestUri("semantic_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(semantic_uri, token.getAccessToken()),
semQuery.toJson());
@ -93,7 +94,7 @@ public class HelperApi extends MpApi {
*/
public List<String> getWechatServerIp() throws WeixinException {
String getcallbackip_uri = getRequestUri("getcallbackip_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(
getcallbackip_uri, token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("ip_list"),
@ -115,7 +116,7 @@ public class HelperApi extends MpApi {
*/
public MenuSetting getMenuSetting() throws WeixinException {
String menu_get_selfmenu_uri = getRequestUri("menu_get_selfmenu_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
menu_get_selfmenu_uri, token.getAccessToken()));
JSONObject result = response.getAsJson();
@ -151,14 +152,18 @@ public class HelperApi extends MpApi {
JSONObject article = null;
for (int i = 0; i < news.size(); i++) {
article = news.getJSONObject(i);
article.put("showCoverPic", article.remove("show_cover"));
article.put("coverUrl", article.remove("cover_url"));
article.put("contentUrl", article.remove("content_url"));
article.put("sourceUrl", article.remove("source_url"));
newsList.add(JSON.parseObject(article.toJSONString(),
MpArticle.class));
article.put("show_cover_pic", article.remove("show_cover"));
article.put("thumb_url", article.remove("cover_url"));
article.put("url", article.remove("content_url"));
article.put("content_source_url",
article.remove("source_url"));
newsList.add(JSON.toJavaObject(article, MpArticle.class));
}
if (ReflectionUtil.getAccessibleField(object, "articles") != null) {
JSONPath.set(object, "$.articles", newsList);
} else {
JSONPath.set(object, "$.content", newsList);
}
JSONPath.set(object, "$.content", newsList);
} else {
JSONPath.set(object, "$.content", value);
}
@ -175,11 +180,12 @@ public class HelperApi extends MpApi {
*/
public AutoReplySetting getAutoReplySetting() throws WeixinException {
String autoreply_setting_get_uri = getRequestUri("autoreply_setting_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
autoreply_setting_get_uri, token.getAccessToken()));
JSONObject result = response.getAsJson();
AutoReplySetting replySetting = JSON.toJavaObject(result,
AutoReplySetting.class);
List<AutoReplySetting.Rule> ruleList = null;

View File

@ -10,7 +10,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MassTuple;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.tuple.MpNews;
@ -27,10 +27,10 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class MassApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public MassApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public MassApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -48,7 +48,7 @@ public class MassApi extends MpApi {
public String uploadArticle(List<MpArticle> articles)
throws WeixinException {
String article_upload_uri = getRequestUri("article_upload_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("articles", articles);
WeixinResponse response = weixinExecutor.post(
@ -110,7 +110,7 @@ public class MassApi extends MpApi {
obj.put(msgtype, JSON.toJSON(tuple));
obj.put("msgtype", msgtype);
String mass_group_uri = getRequestUri("mass_group_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(mass_group_uri, token.getAccessToken()),
obj.toJSONString());
@ -180,7 +180,7 @@ public class MassApi extends MpApi {
obj.put(msgtype, JSON.toJSON(tuple));
obj.put("msgtype", msgtype);
String mass_openid_uri = getRequestUri("mass_openid_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(mass_openid_uri, token.getAccessToken()),
obj.toJSONString());
@ -228,7 +228,7 @@ public class MassApi extends MpApi {
JSONObject obj = new JSONObject();
obj.put("msgid", msgid);
String mass_delete_uri = getRequestUri("mass_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(mass_delete_uri, token.getAccessToken()),
obj.toJSONString());
@ -260,7 +260,7 @@ public class MassApi extends MpApi {
obj.put(msgtype, JSON.toJSON(tuple));
obj.put("msgtype", msgtype);
String mass_preview_uri = getRequestUri("mass_preview_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(mass_preview_uri, token.getAccessToken()),
obj.toJSONString());
@ -282,7 +282,7 @@ public class MassApi extends MpApi {
JSONObject obj = new JSONObject();
obj.put("msg_id", msgId);
String mass_get_uri = getRequestUri("mass_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(mass_get_uri, token.getAccessToken()),
obj.toJSONString());

View File

@ -35,7 +35,7 @@ import com.foxinmy.weixin4j.model.MediaRecord;
import com.foxinmy.weixin4j.model.MediaUploadResult;
import com.foxinmy.weixin4j.model.Pageable;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.tuple.MpVideo;
import com.foxinmy.weixin4j.type.MediaType;
@ -55,10 +55,10 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class MediaApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public MediaApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public MediaApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -81,7 +81,7 @@ public class MediaApi extends MpApi {
fileName = String.format("%s.jpg", fileName);
}
String image_upload_uri = getRequestUri("image_upload_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(
image_upload_uri, token.getAccessToken()),
new FormBodyPart("media", new InputStreamBody(is,
@ -114,7 +114,7 @@ public class MediaApi extends MpApi {
obj.put("title", title);
obj.put("description", description);
String video_upload_uri = getRequestUri("video_upload_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(video_upload_uri, token.getAccessToken()),
obj.toJSONString());
@ -180,7 +180,7 @@ public class MediaApi extends MpApi {
throw new WeixinException(
"please invoke uploadMaterialVideo method");
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = null;
try {
if (isMaterial) {
@ -238,7 +238,7 @@ public class MediaApi extends MpApi {
*/
public MediaDownloadResult downloadMedia(String mediaId, boolean isMaterial)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
try {
HttpRequest request = null;
if (isMaterial) {
@ -310,7 +310,7 @@ public class MediaApi extends MpApi {
*/
public String uploadMaterialArticle(List<MpArticle> articles)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_article_upload_uri = getRequestUri("material_article_upload_uri");
JSONObject obj = new JSONObject();
obj.put("articles", articles);
@ -357,7 +357,7 @@ public class MediaApi extends MpApi {
*/
public JsonResult updateMaterialArticle(String mediaId, int index,
MpArticle article) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_article_update_uri = getRequestUri("material_article_update_uri");
JSONObject obj = new JSONObject();
obj.put("articles", article);
@ -382,7 +382,7 @@ public class MediaApi extends MpApi {
*/
public JsonResult deleteMaterialMedia(String mediaId)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_media_del_uri = getRequestUri("material_media_del_uri");
JSONObject obj = new JSONObject();
obj.put("media_id", mediaId);
@ -418,7 +418,7 @@ public class MediaApi extends MpApi {
fileName = String.format("%s.mp4", fileName);
}
String material_media_upload_uri = getRequestUri("material_media_upload_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
try {
JSONObject description = new JSONObject();
description.put("title", title);
@ -454,7 +454,7 @@ public class MediaApi extends MpApi {
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738733&token=&lang=zh_CN">获取素材总数</a>
*/
public MediaCounter countMaterialMedia() throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_media_count_uri = getRequestUri("material_media_count_uri");
WeixinResponse response = weixinExecutor.get(String.format(
material_media_count_uri, token.getAccessToken()));
@ -482,7 +482,7 @@ public class MediaApi extends MpApi {
*/
public MediaRecord listMaterialMedia(MediaType mediaType, Pageable pageable)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_media_list_uri = getRequestUri("material_media_list_uri");
JSONObject obj = new JSONObject();
obj.put("type", mediaType.name());

View File

@ -17,7 +17,7 @@ import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.Menu;
import com.foxinmy.weixin4j.mp.model.MenuMatchRule;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.type.ButtonType;
/**
@ -30,10 +30,10 @@ import com.foxinmy.weixin4j.type.ButtonType;
*/
public class MenuApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public MenuApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public MenuApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -58,7 +58,7 @@ public class MenuApi extends MpApi {
private WeixinResponse createMenu0(String url, JSONObject data)
throws WeixinException {
return weixinExecutor.post(
String.format(url, tokenHolder.getAccessToken()),
String.format(url, tokenManager.getAccessToken()),
JSON.toJSONString(data, new NameFilter() {
@Override
public String process(Object object, String name,
@ -98,7 +98,7 @@ public class MenuApi extends MpApi {
private JSONObject getMenu0() throws WeixinException {
String menu_get_uri = getRequestUri("menu_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
menu_get_uri, token.getAccessToken()));
return response.getAsJson();
@ -150,7 +150,7 @@ public class MenuApi extends MpApi {
*/
public JsonResult deleteMenu() throws WeixinException {
String menu_delete_uri = getRequestUri("menu_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
menu_delete_uri, token.getAccessToken()));
@ -192,7 +192,7 @@ public class MenuApi extends MpApi {
*/
public JsonResult deleteCustomMenu(String menuId) throws WeixinException {
String menu_delete_uri = getRequestUri("menu_delete_custom_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("menuid", menuId);
WeixinResponse response = weixinExecutor.post(
@ -216,7 +216,7 @@ public class MenuApi extends MpApi {
*/
public List<Button> matchCustomMenu(String userId) throws WeixinException {
String menu_trymatch_uri = getRequestUri("menu_trymatch_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("user_id", userId);
WeixinResponse response = weixinExecutor.post(

View File

@ -1,12 +1,16 @@
package com.foxinmy.weixin4j.mp.api;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.tuple.MpNews;
import com.foxinmy.weixin4j.tuple.NotifyTuple;
import com.foxinmy.weixin4j.util.StringUtil;
@ -20,10 +24,12 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class NotifyApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
private final MassApi massApi;
public NotifyApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public NotifyApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
this.massApi = new MassApi(tokenManager);
}
/**
@ -61,6 +67,17 @@ public class NotifyApi extends MpApi {
public JsonResult sendNotify(NotifyMessage notify, String kfAccount)
throws WeixinException {
NotifyTuple tuple = notify.getTuple();
if (tuple instanceof MpNews) {
MpNews _news = (MpNews) tuple;
List<MpArticle> _articles = _news.getArticles();
if (StringUtil.isBlank(_news.getMediaId())) {
if (_articles.isEmpty()) {
throw new WeixinException(
"notify fail:mediaId or articles is required");
}
tuple = new MpNews(massApi.uploadArticle(_articles));
}
}
String msgtype = tuple.getMessageType();
JSONObject obj = new JSONObject();
obj.put("touser", notify.getTouser());
@ -72,7 +89,7 @@ public class NotifyApi extends MpApi {
obj.put("customservice", kf);
}
String custom_notify_uri = getRequestUri("custom_notify_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(custom_notify_uri, token.getAccessToken()),
obj.toJSONString());

View File

@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.mp.api;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
@ -110,9 +111,14 @@ public class OauthApi extends MpApi {
String user_token_uri = getRequestUri("sns_user_token_uri");
WeixinResponse response = weixinExecutor.get(String.format(
user_token_uri, account.getId(), account.getSecret(), code));
return response.getAsObject(new TypeReference<OauthToken>() {
});
JSONObject result = response.getAsJson();
OauthToken token = new OauthToken(result.getString("access_token"),
result.getLongValue("expires_in") * 1000l);
token.setUnionId(result.getString("unionid"));
token.setOpenId(result.getString("openid"));
token.setScope(result.getString("scope"));
token.setRefreshToken(result.getString("refresh_token"));
return token;
}
/**

View File

@ -25,6 +25,8 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.cache.FileCacheStorager;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
@ -42,9 +44,7 @@ import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.sign.WeixinSignature;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.type.BillType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.RefundType;
@ -69,7 +69,7 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
public class PayOldApi extends MpApi {
private final WeixinOldPayAccount weixinAccount;
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
private final WeixinSignature weixinMD5Signature;
private final WeixinOldPaymentSignature weixinOldSignature;
@ -78,28 +78,28 @@ public class PayOldApi extends MpApi {
*/
public PayOldApi() {
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
WeixinOldPayAccount.class), new FileTokenStorager(
WeixinOldPayAccount.class), new FileCacheStorager<Token>(
Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir",
System.getProperty("java.io.tmpdir"))));
}
public PayOldApi(WeixinOldPayAccount payAccount) {
this(payAccount, new FileTokenStorager(
this(payAccount, new FileCacheStorager<Token>(
Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir",
System.getProperty("java.io.tmpdir"))));
}
public PayOldApi(TokenStorager tokenStorager) {
public PayOldApi(CacheStorager<Token> cacheStorager) {
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
WeixinOldPayAccount.class), tokenStorager);
WeixinOldPayAccount.class), cacheStorager);
}
public PayOldApi(WeixinOldPayAccount weixinAccount,
TokenStorager tokenStorager) {
CacheStorager<Token> cacheStorager) {
this.weixinAccount = weixinAccount;
this.tokenHolder = new TokenHolder(new WeixinTokenCreator(
this.tokenManager = new TokenManager(new WeixinTokenCreator(
weixinAccount.getId(), weixinAccount.getSecret()),
tokenStorager);
cacheStorager);
this.weixinMD5Signature = new WeixinPaymentSignature(
weixinAccount.getPartnerKey());
this.weixinOldSignature = new WeixinOldPaymentSignature();
@ -109,7 +109,7 @@ public class PayOldApi extends MpApi {
return this.weixinAccount;
}
public WeixinOldPaymentSignature getWeixinPaymentSignature(){
public WeixinOldPaymentSignature getWeixinPaymentSignature() {
return this.weixinOldSignature;
}
@ -130,9 +130,9 @@ public class PayOldApi extends MpApi {
*/
public String createPayJsRequestJson(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp) {
PayPackageV2 payPackage = new PayPackageV2(weixinAccount
.getPartnerId(), body, outTradeNo, totalFee, notifyUrl,
createIp);
PayPackageV2 payPackage = new PayPackageV2(
weixinAccount.getPartnerId(), body, outTradeNo, totalFee,
notifyUrl, createIp);
return createPayJsRequestJson(payPackage);
}
@ -145,8 +145,8 @@ public class PayOldApi extends MpApi {
*/
public String createPayJsRequestJson(PayPackageV2 payPackage) {
PayRequest payRequest = new PayRequest(weixinAccount.getId(),
weixinOldSignature.sign(payPackage, weixinAccount
.getPartnerKey()));
weixinOldSignature.sign(payPackage,
weixinAccount.getPartnerKey()));
payRequest.setPaySign(weixinOldSignature.sign(payRequest,
weixinAccount.getPaySignKey()));
payRequest.setSignType(SignType.SHA1);
@ -187,7 +187,7 @@ public class PayOldApi extends MpApi {
*/
public OrderV2 queryOrder(IdQuery idQuery) throws WeixinException {
String orderquery_uri = getRequestUri("orderquery_old_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
StringBuilder sb = new StringBuilder();
sb.append(idQuery.getType().getName()).append("=")
.append(idQuery.getId());
@ -286,9 +286,10 @@ public class PayOldApi extends MpApi {
SSLContext ctx = null;
KeyStore ks = null;
String jksPwd = "";
File jksFile = new File(String.format("%s/tenpay_cacert.jks",
File jksFile = new File(String.format("%s%stenpay_cacert.jks",
Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir",
System.getProperty("java.io.tmpdir"))));
System.getProperty("java.io.tmpdir")),
File.separator));
// create jks ca
if (!jksFile.exists()) {
CertificateFactory cf = CertificateFactory
@ -450,9 +451,10 @@ public class PayOldApi extends MpApi {
}
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
String fileName = String.format("weixin4j_bill_%s_%s_%s.txt",
formatBillDate, billType.name().toLowerCase(), weixinAccount
.getId());
File file = new File(String.format("%s/%s", billPath, fileName));
formatBillDate, billType.name().toLowerCase(),
weixinAccount.getId());
File file = new File(String.format("%s%s%s", billPath, File.separator,
fileName));
if (file.exists()) {
return file;
}
@ -543,7 +545,7 @@ public class PayOldApi extends MpApi {
String outTradeNo, boolean status, String statusMsg)
throws WeixinException {
String delivernotify_uri = getRequestUri("delivernotify_old_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
@ -576,7 +578,7 @@ public class PayOldApi extends MpApi {
public JsonResult updateFeedback(String openId, String feedbackId)
throws WeixinException {
String payfeedback_uri = getRequestUri("payfeedback_old_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
payfeedback_uri, token.getAccessToken(), openId, feedbackId));
return response.getAsJsonResult();

View File

@ -8,7 +8,7 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.QRParameter;
import com.foxinmy.weixin4j.mp.model.QRResult;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.IOUtil;
/**
@ -21,10 +21,10 @@ import com.foxinmy.weixin4j.util.IOUtil;
*/
public class QrApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public QrApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public QrApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -40,7 +40,7 @@ public class QrApi extends MpApi {
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542&token=&lang=zh_CN">生成二维码</a>
*/
public QRResult createQR(QRParameter parameter) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String qr_uri = getRequestUri("qr_ticket_uri");
WeixinResponse response = weixinExecutor.post(
String.format(qr_uri, token.getAccessToken()),

View File

@ -11,7 +11,7 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.mp.model.Following;
import com.foxinmy.weixin4j.mp.model.Tag;
import com.foxinmy.weixin4j.mp.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 标签相关API
@ -23,12 +23,12 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* @see com.foxinmy.weixin4j.mp.model.Tag
*/
public class TagApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
private final UserApi userApi;
public TagApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
this.userApi = new UserApi(tokenHolder);
public TagApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
this.userApi = new UserApi(tokenManager);
}
/**
@ -45,7 +45,7 @@ public class TagApi extends MpApi {
public Tag createTag(String name) throws WeixinException {
String tag_create_uri = getRequestUri("tag_create_uri");
WeixinResponse response = weixinExecutor.post(
String.format(tag_create_uri, tokenHolder.getAccessToken()),
String.format(tag_create_uri, tokenManager.getAccessToken()),
String.format("{\"tag\":{\"name\":\"%s\"}}", name));
return JSON.parseObject(response.getAsJson().getString("tag"),
@ -64,7 +64,7 @@ public class TagApi extends MpApi {
public List<Tag> listTags() throws WeixinException {
String tag_get_uri = getRequestUri("tag_get_uri");
WeixinResponse response = weixinExecutor.get(String.format(tag_get_uri,
tokenHolder.getAccessToken()));
tokenManager.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("tags"),
Tag.class);
@ -86,7 +86,7 @@ public class TagApi extends MpApi {
JSONObject obj = new JSONObject();
obj.put("tag", tag);
WeixinResponse response = weixinExecutor.post(
String.format(tag_update_uri, tokenHolder.getAccessToken()),
String.format(tag_update_uri, tokenManager.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
}
@ -104,7 +104,7 @@ public class TagApi extends MpApi {
public JsonResult deleteTag(int tagId) throws WeixinException {
String tag_delete_uri = getRequestUri("tag_delete_uri");
WeixinResponse response = weixinExecutor.post(
String.format(tag_delete_uri, tokenHolder.getAccessToken()),
String.format(tag_delete_uri, tokenManager.getAccessToken()),
String.format("{\"tagid\":%d}", tagId));
return response.getAsJsonResult();
}
@ -133,7 +133,7 @@ public class TagApi extends MpApi {
obj.put("openid_list", openIds);
obj.put("tagid", tagId);
WeixinResponse response = weixinExecutor.post(
String.format(tag_batch_uri, tokenHolder.getAccessToken()),
String.format(tag_batch_uri, tokenManager.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
}
@ -174,7 +174,7 @@ public class TagApi extends MpApi {
obj.put("tagid", tagId);
obj.put("next_openid", nextOpenId);
WeixinResponse response = weixinExecutor.post(
String.format(tag_user_uri, tokenHolder.getAccessToken()),
String.format(tag_user_uri, tokenManager.getAccessToken()),
obj.toJSONString());
JSONObject result = response.getAsJson();
@ -283,7 +283,7 @@ public class TagApi extends MpApi {
public Integer[] getUserTags(String openId) throws WeixinException {
String tag_userids_uri = getRequestUri("tag_userids_uri");
WeixinResponse response = weixinExecutor.post(
String.format(tag_userids_uri, tokenHolder.getAccessToken()),
String.format(tag_userids_uri, tokenManager.getAccessToken()),
String.format("{\"openid\":\"%s\"}", openId));
return response.getAsJson().getJSONArray("tagid_list")
.toArray(new Integer[] {});

View File

@ -12,7 +12,7 @@ import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
import com.foxinmy.weixin4j.mp.model.TemplateMessageInfo;
import com.foxinmy.weixin4j.mp.type.IndustryType;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.NameValue;
/**
@ -26,10 +26,10 @@ import com.foxinmy.weixin4j.util.NameValue;
*/
public class TmplApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public TmplApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public TmplApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -50,7 +50,7 @@ public class TmplApi extends MpApi {
obj.put(String.format("industry_id%d", i + 1),
Integer.toString(industryTypes[i].getTypeId()));
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String template_set_industry_uri = getRequestUri("template_set_industry_uri");
WeixinResponse response = weixinExecutor.post(String.format(
template_set_industry_uri, token.getAccessToken()), obj
@ -71,7 +71,7 @@ public class TmplApi extends MpApi {
public IndustryType[] getTmplIndustry() throws WeixinException {
String template_get_industry_uri = getRequestUri("template_get_industry_uri");
WeixinResponse response = weixinExecutor.get(String.format(
template_get_industry_uri, tokenHolder.getAccessToken()));
template_get_industry_uri, tokenManager.getAccessToken()));
JSONObject primary = response.getAsJson().getJSONObject(
"primary_industry");
JSONObject secondary = response.getAsJson().getJSONObject(
@ -96,7 +96,7 @@ public class TmplApi extends MpApi {
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277&token=&lang=zh_CN">获得模板ID</a>
*/
public String getTemplateId(String shortId) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String template_getid_uri = getRequestUri("template_getid_uri");
WeixinResponse response = weixinExecutor.post(
String.format(template_getid_uri, token.getAccessToken()),
@ -115,7 +115,7 @@ public class TmplApi extends MpApi {
* @throws WeixinException
*/
public List<TemplateMessageInfo> getAllTemplates() throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String template_getall_uri = getRequestUri("template_getall_uri");
WeixinResponse response = weixinExecutor.get(String.format(
template_getall_uri, token.getAccessToken()));
@ -134,7 +134,7 @@ public class TmplApi extends MpApi {
* @throws WeixinException
*/
public JsonResult deleteTemplate(String templateId) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String template_del_uri = getRequestUri("template_del_uri");
WeixinResponse response = weixinExecutor.post(
String.format(template_del_uri, token.getAccessToken()),
@ -159,7 +159,7 @@ public class TmplApi extends MpApi {
*/
public JsonResult sendTmplMessage(TemplateMessage tplMessage)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String template_send_uri = getRequestUri("template_send_uri");
WeixinResponse response = weixinExecutor.post(
String.format(template_send_uri, token.getAccessToken()),

View File

@ -13,7 +13,7 @@ import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.Following;
import com.foxinmy.weixin4j.mp.model.User;
import com.foxinmy.weixin4j.mp.type.Lang;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 用户相关API
@ -26,10 +26,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
*/
public class UserApi extends MpApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public UserApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public UserApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -66,7 +66,7 @@ public class UserApi extends MpApi {
*/
public User getUser(String openId, Lang lang) throws WeixinException {
String user_info_uri = getRequestUri("api_user_info_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
user_info_uri, token.getAccessToken(), openId, lang.name()));
@ -118,7 +118,7 @@ public class UserApi extends MpApi {
}
parameter.delete(parameter.length() - 1, parameter.length());
parameter.append("]}");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(api_users_info_uri, token.getAccessToken()),
parameter.toString());
@ -174,7 +174,7 @@ public class UserApi extends MpApi {
public Following getFollowingOpenIds(String nextOpenId)
throws WeixinException {
String following_uri = getRequestUri("following_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
following_uri, token.getAccessToken(), nextOpenId == null ? ""
: nextOpenId));
@ -267,7 +267,7 @@ public class UserApi extends MpApi {
public JsonResult remarkUserName(String openId, String remark)
throws WeixinException {
String username_remark_uri = getRequestUri("username_remark_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("openid", openId);
obj.put("remark", remark);

View File

@ -56,10 +56,7 @@ public class TemplateMessage implements Serializable {
private final static String TAIL_KEY = "remark";
private final static String DEFAULT_COLOR = "#173177";
@JSONCreator
public TemplateMessage(@JSONField(name = "toUser") String toUser,
@JSONField(name = "templateId") String templateId,
@JSONField(name = "url") String url) {
public TemplateMessage(String toUser, String templateId, String url) {
this.toUser = toUser;
this.templateId = templateId;
this.url = url;

View File

@ -7,6 +7,7 @@ import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.mp.type.AutomatchMode;
import com.foxinmy.weixin4j.mp.type.AutoreplyMode;
import com.foxinmy.weixin4j.type.ButtonType;
/**
* 自动回复设置
@ -189,10 +190,9 @@ public class AutoReplySetting implements Serializable {
@Override
public String toString() {
return "Rule [ruleName=" + ruleName + ", createTime="
+ createTime + ", replyMode=" + replyMode
+ ", keywordList=" + keywordList + ", replyList="
+ replyList + "]";
return "Rule [ruleName=" + ruleName + ", createTime=" + createTime
+ ", replyMode=" + replyMode + ", keywordList="
+ keywordList + ", replyList=" + replyList + "]";
}
}
@ -212,7 +212,7 @@ public class AutoReplySetting implements Serializable {
* 自动回复的类型关注后自动回复和消息自动回复的类型仅支持文本text图片img语音voice视频video
* 关键词自动回复则还多了图文消息(news)
*/
private String type;
private ButtonType type;
/**
* 对于文本类型content是文本内容对于图片语音视频类型content是mediaID,news是article
*
@ -227,11 +227,11 @@ public class AutoReplySetting implements Serializable {
@JSONField(name = "match_mode")
private AutomatchMode matchMode;
public String getType() {
public ButtonType getType() {
return type;
}
public void setType(String type) {
public void setType(ButtonType type) {
this.type = type;
}

View File

@ -1,5 +1,6 @@
package com.foxinmy.weixin4j.mp.model;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.model.Token;
@ -10,8 +11,6 @@ import com.foxinmy.weixin4j.model.Token;
* @author jinyu(foxinmy@gmail.com)
* @date 2014年4月6日
* @since JDK 1.6
* @see com.foxinmy.weixin4j.mp.model.AuthResult
* @see com.foxinmy.weixin4j.mp.model.AuthResult.AuthScope
*/
public class OauthToken extends Token {
@ -36,6 +35,10 @@ public class OauthToken extends Token {
private String scope;
public OauthToken(String accessToken, long expires) {
super(accessToken, expires);
}
public String getOpenId() {
return openId;
}
@ -71,9 +74,7 @@ public class OauthToken extends Token {
@Override
public String toString() {
return "OauthToken [openId=" + openId + ", unionId=" + unionId
+ ", refreshToken=" + refreshToken + ", scope=" + scope
+ ", accessToken=" + getAccessToken()
+ ", expiresIn=" + getExpiresIn() + ", createTime="
+ getCreateTime() + "]";
+ ", refreshToken=" + refreshToken + ", scope=" + scope + ", "
+ super.toString() + "]";
}
}

View File

@ -6,13 +6,13 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.type.URLConsts;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.type.TicketType;
/**
* 微信公众平台TICKET创建(包括jsticket其它JSSDK所需的ticket的创建
*
* @className WeixinJSTicketCreator
* @className WeixinTicketCreator
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月10日
* @since JDK 1.6
@ -24,7 +24,7 @@ public class WeixinTicketCreator extends TokenCreator {
private final String appid;
private final TicketType ticketType;
private final TokenHolder weixinTokenHolder;
private final TokenManager weixinTokenManager;
/**
* jssdk
@ -33,13 +33,14 @@ public class WeixinTicketCreator extends TokenCreator {
* 公众号的appid
* @param ticketType
* 票据类型
* @param weixinTokenHolder
* @param weixinTokenManager
* <font color="red">公众平台的access_token</font>
*/
public WeixinTicketCreator(String appid, TicketType ticketType, TokenHolder weixinTokenHolder) {
public WeixinTicketCreator(String appid, TicketType ticketType,
TokenManager weixinTokenManager) {
this.appid = appid;
this.ticketType = ticketType;
this.weixinTokenHolder = weixinTokenHolder;
this.weixinTokenManager = weixinTokenManager;
}
@Override
@ -49,12 +50,11 @@ public class WeixinTicketCreator extends TokenCreator {
@Override
public Token create() throws WeixinException {
WeixinResponse response = weixinExecutor.get(
String.format(URLConsts.JS_TICKET_URL, weixinTokenHolder.getToken().getAccessToken(), ticketType.name()));
WeixinResponse response = weixinExecutor.get(String.format(
URLConsts.JS_TICKET_URL, weixinTokenManager.getAccessToken(),
ticketType.name()));
JSONObject result = response.getAsJson();
Token token = new Token(result.getString("ticket"));
token.setExpiresIn(result.getIntValue("expires_in"));
token.setOriginalResult(response.getAsString());
return token;
return new Token(result.getString("ticket"),
result.getLongValue("expires_in") * 1000l);
}
}

View File

@ -1,6 +1,6 @@
package com.foxinmy.weixin4j.mp.token;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
@ -45,10 +45,8 @@ public class WeixinTokenCreator extends TokenCreator {
String tokenUrl = String.format(URLConsts.ASSESS_TOKEN_URL, appid,
secret);
WeixinResponse response = weixinExecutor.get(tokenUrl);
Token token = response.getAsObject(new TypeReference<Token>() {
});
token.setCreateTime(System.currentTimeMillis());
token.setOriginalResult(response.getAsString());
return token;
JSONObject result = response.getAsJson();
return new Token(result.getString("access_token"),
result.getLongValue("expires_in") * 1000l);
}
}

View File

@ -35,7 +35,7 @@ public class CustomTest extends TokenTest {
@Before
public void init() {
customApi = new CustomApi(tokenHolder);
customApi = new CustomApi(tokenManager);
}
@Test

View File

@ -28,7 +28,7 @@ public class DataApiTest extends TokenTest {
@Before
public void init() {
dataApi = new DataApi(tokenHolder);
dataApi = new DataApi(tokenManager);
}
@Test

View File

@ -24,7 +24,7 @@ public class GroupTest extends TokenTest {
@Before
public void init() {
groupApi = new GroupApi(tokenHolder);
groupApi = new GroupApi(tokenManager);
}
@Test

View File

@ -23,7 +23,7 @@ public class HelperTest extends TokenTest {
@Before
public void init() {
helperApi = new HelperApi(tokenHolder);
helperApi = new HelperApi(tokenManager);
}
@Test

View File

@ -34,8 +34,8 @@ public class MassTest extends TokenTest {
@Before
public void init() {
this.massApi = new MassApi(tokenHolder);
this.mediaApi = new MediaApi(tokenHolder);
this.massApi = new MassApi(tokenManager);
this.mediaApi = new MediaApi(tokenManager);
}
@Test

View File

@ -39,7 +39,7 @@ public class MediaTest extends TokenTest {
@Before
public void init() {
mediaApi = new MediaApi(tokenHolder);
mediaApi = new MediaApi(tokenManager);
}
@Test
@ -87,14 +87,14 @@ public class MediaTest extends TokenTest {
List<MpArticle> articles = new ArrayList<MpArticle>();
articles.add(new MpArticle("8790403529", "title", "content"));
String mediaId = mediaApi.uploadMaterialArticle(articles);
// 17385064953
// DVWwU0u9ommOTPgyJszpK943IWCCVAcFGNmiIBObf5E
Assert.assertNotNull(mediaId);
System.err.println(mediaId);
}
@Test
public void downloadArticle() throws WeixinException {
List<MpArticle> articles = mediaApi.downloadArticle("17385064953");
List<MpArticle> articles = mediaApi.downloadArticle("DVWwU0u9ommOTPgyJszpK943IWCCVAcFGNmiIBObf5E");
Assert.assertTrue(articles != null && !articles.isEmpty());
System.err.println(articles);
}

View File

@ -31,7 +31,7 @@ public class MenuTest extends TokenTest {
@Before
public void init() {
menuApi = new MenuApi(tokenHolder);
menuApi = new MenuApi(tokenManager);
}
@Test

View File

@ -37,8 +37,8 @@ public class NotifyTest extends TokenTest {
@Before
public void init() {
notifyApi = new NotifyApi(tokenHolder);
mediaApi = new MediaApi(tokenHolder);
notifyApi = new NotifyApi(tokenManager);
mediaApi = new MediaApi(tokenManager);
}
@Test

View File

@ -24,7 +24,7 @@ public class QRTest extends TokenTest {
@Before
public void init() {
qrApi = new QrApi(tokenHolder);
qrApi = new QrApi(tokenManager);
}
@Test

View File

@ -13,7 +13,7 @@ public class SemanticTest extends TokenTest {
@Before
public void init() {
helperApi = new HelperApi(tokenHolder);
helperApi = new HelperApi(tokenManager);
}
@Test

View File

@ -26,7 +26,7 @@ public class TagTest extends TokenTest {
@Before
public void init() {
tagApi = new TagApi(tokenHolder);
tagApi = new TagApi(tokenManager);
}
@Test

View File

@ -15,7 +15,7 @@ public class TemplateTest extends TokenTest {
@Before
public void init() {
this.tmplApi = new TmplApi(tokenHolder);
this.tmplApi = new TmplApi(tokenManager);
}
@Test

View File

@ -7,7 +7,7 @@ import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* token测试
@ -19,19 +19,19 @@ import com.foxinmy.weixin4j.token.TokenHolder;
*/
public class TokenTest {
protected TokenHolder tokenHolder;
protected TokenManager tokenManager;
protected Weixin4jSettings settings;
@Before
public void setUp() {
this.settings = new Weixin4jSettings();
tokenHolder = new TokenHolder(new WeixinTokenCreator(settings
.getAccount().getId(), settings.getAccount()
.getSecret()), settings.getTokenStorager0());
tokenManager = new TokenManager(new WeixinTokenCreator(settings
.getAccount().getId(), settings.getAccount().getSecret()),
settings.getCacheStorager0());
}
@Test
public void test() throws WeixinException {
Assert.assertNotNull(tokenHolder.getToken());
Assert.assertNotNull(tokenManager.getCache());
}
}

View File

@ -24,7 +24,7 @@ public class UserTest extends TokenTest {
@Before
public void init() {
userApi = new UserApi(tokenHolder);
userApi = new UserApi(tokenManager);
}
@Test

View File

@ -14,9 +14,7 @@ import com.foxinmy.weixin4j.xml.XmlStream;
public class XmlstreamTest {
public static void object2xmlWithRootElement() {
Token token = new Token("accessToken");
token.setExpiresIn(12);
token.setCreateTime(13l);
Token token = new Token("accessToken", 12l, 13l);
String content = XmlStream.toXML(token);
System.err.println(content);
}

View File

@ -38,7 +38,7 @@ import com.foxinmy.weixin4j.qy.model.IdParameter;
import com.foxinmy.weixin4j.qy.model.Party;
import com.foxinmy.weixin4j.qy.model.Tag;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.suite.SuitePerCodeHolder;
import com.foxinmy.weixin4j.qy.suite.SuitePerCodeManager;
import com.foxinmy.weixin4j.qy.suite.WeixinTokenSuiteCreator;
import com.foxinmy.weixin4j.qy.token.WeixinTicketCreator;
import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator;
@ -47,7 +47,7 @@ import com.foxinmy.weixin4j.qy.type.InviteType;
import com.foxinmy.weixin4j.qy.type.KfType;
import com.foxinmy.weixin4j.qy.type.UserStatus;
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.type.TicketType;
@ -106,7 +106,7 @@ public class WeixinProxy {
/**
* token实现
*/
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
/**
* 配置信息
*/
@ -126,30 +126,30 @@ public class WeixinProxy {
* @see com.foxinmy.weixin4j.setting.Weixin4jSettings
*/
public WeixinProxy(Weixin4jSettings settings) {
this(new TokenHolder(new WeixinTokenCreator(settings.getAccount()
this(new TokenManager(new WeixinTokenCreator(settings.getAccount()
.getId(), settings.getAccount().getSecret()),
settings.getTokenStorager0()));
settings.getCacheStorager0()));
this.settings = settings;
}
/**
* 第三方套件(永久授权码机制)
*
* @param perCodeHolder
* @param perCodeManager
* 第三方套件永久授权码
* {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getPerCodeHolder(String)}
* @param suiteTokenHolder
* {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getPerCodeManager(String)}
* @param suitetokenManager
* 第三方套件凭证token
* {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getTokenSuiteHolder(String)}
* {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getTokenSuiteManager(String)}
* @see com.foxinmy.weixin4j.qy.api.SuiteApi
* @see WeixinSuiteProxy#getWeixinProxy(String, String)
*/
public WeixinProxy(SuitePerCodeHolder perCodeHolder,
TokenHolder suiteTokenHolder) {
this(new TokenHolder(new WeixinTokenSuiteCreator(perCodeHolder,
suiteTokenHolder), perCodeHolder.getTokenStorager()));
public WeixinProxy(SuitePerCodeManager perCodeManager,
TokenManager suiteTokenManager) {
this(new TokenManager(new WeixinTokenSuiteCreator(perCodeManager,
suiteTokenManager), perCodeManager.getCacheStorager()));
this.settings = new Weixin4jSettings(new WeixinAccount(
perCodeHolder.getAuthCorpId(), null));
perCodeManager.getAuthCorpId(), null));
}
/**
@ -157,20 +157,20 @@ public class WeixinProxy {
* color="red">WeixinTokenCreator或WeixinTokenSuiteCreator</font>
*
* @see com.foxinmy.weixin4j.qy.token.WeixinTokenCreator
* @param tokenHolder
* @param tokenManager
*/
private WeixinProxy(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
this.partyApi = new PartyApi(tokenHolder);
this.userApi = new UserApi(tokenHolder);
this.tagApi = new TagApi(tokenHolder);
this.helperApi = new HelperApi(tokenHolder);
this.agentApi = new AgentApi(tokenHolder);
this.batchApi = new BatchApi(tokenHolder);
this.notifyApi = new NotifyApi(tokenHolder);
this.menuApi = new MenuApi(tokenHolder);
this.mediaApi = new MediaApi(tokenHolder);
this.chatApi = new ChatApi(tokenHolder);
private WeixinProxy(TokenManager tokenManager) {
this.tokenManager = tokenManager;
this.partyApi = new PartyApi(tokenManager);
this.userApi = new UserApi(tokenManager);
this.tagApi = new TagApi(tokenManager);
this.helperApi = new HelperApi(tokenManager);
this.agentApi = new AgentApi(tokenManager);
this.batchApi = new BatchApi(tokenManager);
this.notifyApi = new NotifyApi(tokenManager);
this.menuApi = new MenuApi(tokenManager);
this.mediaApi = new MediaApi(tokenManager);
this.chatApi = new ChatApi(tokenManager);
}
/**
@ -178,8 +178,8 @@ public class WeixinProxy {
*
* @return
*/
public TokenHolder getTokenHolder() {
return this.tokenHolder;
public TokenManager getTokenManager() {
return this.tokenManager;
}
/**
@ -192,16 +192,16 @@ public class WeixinProxy {
}
/**
* 获取JSSDK Ticket的tokenHolder
* 获取JSSDK Ticket的tokenManager
*
* @param ticketType
* 票据类型
* @return
*/
public TokenHolder getTicketHolder(TicketType ticketType) {
return new TokenHolder(new WeixinTicketCreator(getWeixinAccount()
.getId(), ticketType, this.tokenHolder),
this.settings.getTokenStorager0());
public TokenManager getTicketManager(TicketType ticketType) {
return new TokenManager(new WeixinTicketCreator(getWeixinAccount()
.getId(), ticketType, this.tokenManager),
this.settings.getCacheStorager0());
}
/**

View File

@ -12,12 +12,12 @@ import com.foxinmy.weixin4j.qy.api.ProviderApi;
import com.foxinmy.weixin4j.qy.api.SuiteApi;
import com.foxinmy.weixin4j.qy.model.OUserInfo;
import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
import com.foxinmy.weixin4j.qy.suite.SuiteTicketHolder;
import com.foxinmy.weixin4j.qy.suite.SuiteTicketManager;
import com.foxinmy.weixin4j.qy.suite.Weixin4jSuiteSettings;
import com.foxinmy.weixin4j.qy.token.WeixinProviderTokenCreator;
import com.foxinmy.weixin4j.qy.type.LoginTargetType;
import com.foxinmy.weixin4j.qy.type.URLConsts;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
@ -64,8 +64,8 @@ public class WeixinSuiteProxy {
for (WeixinAccount suite : suiteSettings.getAccount()
.getSuiteAccounts()) {
this.suiteMap.put(suite.getId(), new SuiteApi(
new SuiteTicketHolder(suite.getId(), suite.getSecret(),
suiteSettings.getTokenStorager0())));
new SuiteTicketManager(suite.getId(), suite.getSecret(),
suiteSettings.getCacheStorager0())));
this.suiteMap.put(
null,
suiteMap.get(suiteSettings.getAccount()
@ -75,12 +75,12 @@ public class WeixinSuiteProxy {
if (StringUtil.isNotBlank(suiteSettings.getAccount().getId())
&& StringUtil.isNotBlank(suiteSettings.getAccount()
.getProviderSecret())) {
this.providerApi = new ProviderApi(new TokenHolder(
this.providerApi = new ProviderApi(new TokenManager(
new WeixinProviderTokenCreator(suiteSettings
.getAccount().getId(), suiteSettings
.getAccount().getProviderSecret()),
suiteSettings.getTokenStorager0()),
suiteSettings.getTokenStorager0());
suiteSettings.getCacheStorager0()),
suiteSettings.getCacheStorager0());
}
}
@ -129,7 +129,7 @@ public class WeixinSuiteProxy {
*/
public void cacheTicket(String suiteId, String suiteTicket)
throws WeixinException {
suite(suiteId).getTicketHolder().cachingTicket(suiteTicket);
suite(suiteId).getTicketManager().cachingTicket(suiteTicket);
}
/**
@ -160,7 +160,7 @@ public class WeixinSuiteProxy {
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php?title
* =%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%AE%A1%E7%90%86%E5%91%98%E6%
* 8E%88%E6%9D%83%E5%BA%94%E7%94%A8">企业号第三方应用套件授权</a>
* @see {@link SuiteApi#getPreCodeHolder}
* @see {@link SuiteApi#getPreCodeManager}
* @return 请求授权的URL
* @throws WeixinException
*/
@ -168,7 +168,7 @@ public class WeixinSuiteProxy {
String state) throws WeixinException {
try {
return String.format(URLConsts.SUITE_OAUTH_URL, suiteId,
suite(suiteId).getTicketHolder().getTicket(),
suite(suiteId).getTicketManager().getTicket(),
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state);
} catch (UnsupportedEncodingException e) {
;
@ -226,8 +226,8 @@ public class WeixinSuiteProxy {
* @return
*/
public WeixinProxy getWeixinProxy(String suiteId, String authCorpId) {
return new WeixinProxy(suite(suiteId).getPerCodeHolder(authCorpId),
suite(suiteId).getSuiteTokenHolder());
return new WeixinProxy(suite(suiteId).getPerCodeManager(authCorpId),
suite(suiteId).getSuiteTokenManager());
}
public final static String VERSION = "1.6.9";

View File

@ -13,7 +13,7 @@ import com.foxinmy.weixin4j.qy.model.AgentInfo;
import com.foxinmy.weixin4j.qy.model.AgentOverview;
import com.foxinmy.weixin4j.qy.model.AgentSetter;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 管理应用接口
@ -26,10 +26,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">管理应用接口说明</a>
*/
public class AgentApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public AgentApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public AgentApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -45,7 +45,7 @@ public class AgentApi extends QyApi {
*/
public AgentInfo getAgent(int agentid) throws WeixinException {
String agent_get_uri = getRequestUri("agent_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(agent_get_uri,
token.getAccessToken(), agentid));
JSONObject jsonObj = response.getAsJson();
@ -74,7 +74,7 @@ public class AgentApi extends QyApi {
*/
public JsonResult setAgent(AgentSetter agentSet) throws WeixinException {
String agent_set_uri = getRequestUri("agent_set_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(agent_set_uri, token.getAccessToken()),
JSON.toJSONString(agentSet, typeFilter));
@ -108,7 +108,7 @@ public class AgentApi extends QyApi {
*/
public List<AgentOverview> listAgentOverview() throws WeixinException {
String agent_list_uri = getRequestUri("agent_list_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(agent_list_uri,
token.getAccessToken()));

View File

@ -8,7 +8,7 @@ import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.BatchResult;
import com.foxinmy.weixin4j.qy.model.Callback;
import com.foxinmy.weixin4j.qy.model.IdParameter;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 批量异步任务API
@ -25,10 +25,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
*/
public class BatchApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public BatchApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public BatchApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -50,7 +50,7 @@ public class BatchApi extends QyApi {
public String inviteUser(IdParameter parameter, Callback callback,
String tips) throws WeixinException {
String batch_inviteuser_uri = getRequestUri("batch_inviteuser_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.putAll(parameter.getParameter());
obj.put("callback", callback);
@ -89,7 +89,7 @@ public class BatchApi extends QyApi {
private String batch(String batchUrl, String mediaId, Callback callback)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("media_id", mediaId);
obj.put("callback", callback);
@ -162,7 +162,7 @@ public class BatchApi extends QyApi {
* @throws WeixinException
*/
public BatchResult getBatchResult(String jobId) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String batch_getresult_uri = getRequestUri("batch_getresult_uri");
WeixinResponse response = weixinExecutor.get(String.format(
batch_getresult_uri, token.getAccessToken(), jobId));

View File

@ -12,7 +12,7 @@ import com.foxinmy.weixin4j.qy.message.ChatMessage;
import com.foxinmy.weixin4j.qy.model.ChatInfo;
import com.foxinmy.weixin4j.qy.model.ChatMute;
import com.foxinmy.weixin4j.qy.type.ChatType;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.ChatTuple;
import com.foxinmy.weixin4j.util.ObjectId;
import com.foxinmy.weixin4j.util.StringUtil;
@ -28,10 +28,10 @@ import com.foxinmy.weixin4j.util.StringUtil;
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E6%B6%88%E6%81%AF%E6%9C%8D%E5%8A%A1">企业号消息服务</a>
*/
public class ChatApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public ChatApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public ChatApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -53,7 +53,7 @@ public class ChatApi extends QyApi {
obj.put("chatid", chatId);
}
String message_chat_create_uri = getRequestUri("message_chat_create_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
weixinExecutor.post(
String.format(message_chat_create_uri, token.getAccessToken()),
obj.toJSONString());
@ -73,7 +73,7 @@ public class ChatApi extends QyApi {
*/
public ChatInfo getChat(String chatId) throws WeixinException {
String message_chat_get_uri = getRequestUri("message_chat_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
message_chat_get_uri, token.getAccessToken(), chatId));
return response.getAsJson().getObject("chat_info", ChatInfo.class);
@ -105,7 +105,7 @@ public class ChatApi extends QyApi {
obj.put("add_user_list", addUsers);
obj.put("del_user_list", deleteUsers);
String message_chat_update_uri = getRequestUri("message_chat_update_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(message_chat_update_uri, token.getAccessToken()),
obj.toJSONString());
@ -130,7 +130,7 @@ public class ChatApi extends QyApi {
obj.put("chatid", chatId);
obj.put("op_user", operator);
String message_chat_quit_uri = getRequestUri("message_chat_quit_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(message_chat_quit_uri, token.getAccessToken()),
obj.toJSONString());
@ -157,7 +157,7 @@ public class ChatApi extends QyApi {
chat.put("type", chatType.name());
chat.put("id", targetId);
String message_chat_clearnotify_uri = getRequestUri("message_chat_clearnotify_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(message_chat_clearnotify_uri,
token.getAccessToken()),
@ -184,7 +184,7 @@ public class ChatApi extends QyApi {
JSONObject mute = new JSONObject();
mute.put("user_mute_list", chatMutes);
String message_chat_setmute_uri = getRequestUri("message_chat_setmute_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor
.post(String.format(message_chat_setmute_uri,
token.getAccessToken()), mute.toJSONString());
@ -216,7 +216,7 @@ public class ChatApi extends QyApi {
msg.put("msgtype", msgtype);
msg.put(msgtype, tuple);
String message_chat_send_uri = getRequestUri("message_chat_send_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(message_chat_send_uri, token.getAccessToken()),
msg.toJSONString());

View File

@ -6,7 +6,7 @@ import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 辅助API
@ -18,10 +18,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* @see
*/
public class HelperApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public HelperApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public HelperApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -34,7 +34,7 @@ public class HelperApi extends QyApi {
*/
public List<String> getWechatServerIp() throws WeixinException {
String getcallbackip_uri = getRequestUri("getcallbackip_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(getcallbackip_uri,
token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("ip_list"),

View File

@ -39,7 +39,7 @@ import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.Callback;
import com.foxinmy.weixin4j.qy.model.Party;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.FileUtil;
@ -61,10 +61,10 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class MediaApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public MediaApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public MediaApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -89,7 +89,7 @@ public class MediaApi extends QyApi {
fileName = String.format("%s.jpg", fileName);
}
String media_uploadimg_uri = getRequestUri("media_uploadimg_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(
media_uploadimg_uri, token.getAccessToken()),
new FormBodyPart("media", new InputStreamBody(is,
@ -146,7 +146,7 @@ public class MediaApi extends QyApi {
",%s,", suffixName))) {
mediaType = MediaType.video;
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
try {
WeixinResponse response = null;
if (agentid > 0) {
@ -200,7 +200,7 @@ public class MediaApi extends QyApi {
*/
public MediaDownloadResult downloadMedia(int agentid, String mediaId)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
try {
HttpRequest request = null;
if (agentid > 0) {
@ -273,7 +273,7 @@ public class MediaApi extends QyApi {
*/
public String uploadMaterialArticle(int agentid, List<MpArticle> articles)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_article_upload_uri = getRequestUri("material_article_upload_uri");
JSONObject obj = new JSONObject();
obj.put("agentid", agentid);
@ -301,7 +301,7 @@ public class MediaApi extends QyApi {
*/
public JsonResult deleteMaterialMedia(int agentid, String mediaId)
throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_media_del_uri = getRequestUri("material_media_del_uri");
WeixinResponse response = weixinExecutor.get(String.format(
material_media_del_uri, token.getAccessToken(), mediaId,
@ -348,7 +348,7 @@ public class MediaApi extends QyApi {
*/
public String updateMaterialArticle(int agentid, String mediaId,
List<MpArticle> articles) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_article_update_uri = getRequestUri("material_article_update_uri");
JSONObject obj = new JSONObject();
obj.put("agentid", agentid);
@ -375,7 +375,7 @@ public class MediaApi extends QyApi {
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E7%B4%A0%E6%9D%90%E6%80%BB%E6%95%B0">获取素材总数</a>
*/
public MediaCounter countMaterialMedia(int agentid) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_media_count_uri = getRequestUri("material_media_count_uri");
WeixinResponse response = weixinExecutor.get(String.format(
material_media_count_uri, token.getAccessToken(), agentid));
@ -406,7 +406,7 @@ public class MediaApi extends QyApi {
*/
public MediaRecord listMaterialMedia(int agentid, MediaType mediaType,
Pageable pageable) throws WeixinException {
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
String material_media_list_uri = getRequestUri("material_media_list_uri");
JSONObject obj = new JSONObject();
obj.put("agentid", agentid);

View File

@ -15,7 +15,7 @@ import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.type.ButtonType;
/**
@ -29,10 +29,10 @@ import com.foxinmy.weixin4j.type.ButtonType;
*/
public class MenuApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public MenuApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public MenuApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -51,7 +51,7 @@ public class MenuApi extends QyApi {
*/
public JsonResult createMenu(int agentid, List<Button> buttons) throws WeixinException {
String menu_create_uri = getRequestUri("menu_create_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("button", buttons);
WeixinResponse response = weixinExecutor.post(String.format(menu_create_uri, token.getAccessToken(), agentid),
@ -91,7 +91,7 @@ public class MenuApi extends QyApi {
*/
public List<Button> getMenu(int agentid) throws WeixinException {
String menu_get_uri = getRequestUri("menu_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(menu_get_uri, token.getAccessToken(), agentid));
JSONArray buttons = response.getAsJson().getJSONObject("menu").getJSONArray("button");
@ -121,7 +121,7 @@ public class MenuApi extends QyApi {
*/
public JsonResult deleteMenu(int agentid) throws WeixinException {
String menu_delete_uri = getRequestUri("menu_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(menu_delete_uri, token.getAccessToken(), agentid));
return response.getAsJsonResult();

View File

@ -15,7 +15,8 @@ import com.foxinmy.weixin4j.qy.message.CustomeMessage;
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
import com.foxinmy.weixin4j.qy.model.IdParameter;
import com.foxinmy.weixin4j.qy.type.KfType;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.tuple.MpNews;
import com.foxinmy.weixin4j.tuple.NotifyTuple;
/**
@ -39,10 +40,10 @@ import com.foxinmy.weixin4j.tuple.NotifyTuple;
*/
public class NotifyApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public NotifyApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public NotifyApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -76,6 +77,11 @@ public class NotifyApi extends QyApi {
public IdParameter sendNotifyMessage(NotifyMessage message)
throws WeixinException {
NotifyTuple tuple = message.getTuple();
if (tuple instanceof MpNews) {
if (((MpNews) tuple).getArticles().isEmpty()) {
throw new WeixinException("notify fail:articles is required");
}
}
Map<String, String> target = message.getTarget().getParameter();
String msgtype = tuple.getMessageType();
JSONObject obj = (JSONObject) JSON.toJSON(message);
@ -87,7 +93,7 @@ public class NotifyApi extends QyApi {
obj.putAll(target);
}
String message_send_uri = getRequestUri("message_send_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(message_send_uri, token.getAccessToken()),
obj.toJSONString());
@ -140,7 +146,7 @@ public class NotifyApi extends QyApi {
obj.put("msgtype", msgtype);
obj.put(msgtype, tuple);
String message_kf_send_uri = getRequestUri("message_kf_send_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(message_kf_send_uri, token.getAccessToken()),
obj.toJSONString());
@ -163,7 +169,7 @@ public class NotifyApi extends QyApi {
if (kfType != null) {
message_kf_list_uri += "&type=" + kfType.name();
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
message_kf_list_uri, token.getAccessToken()));
JSONObject obj = response.getAsJson();

View File

@ -9,7 +9,7 @@ import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.Party;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 部门API
@ -23,10 +23,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8">管理部门说明</a>
*/
public class PartyApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public PartyApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public PartyApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -49,7 +49,7 @@ public class PartyApi extends QyApi {
if (party.getId() < 1) {
obj.remove("id");
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(department_create_uri, token.getAccessToken()),
obj.toJSONString());
@ -79,7 +79,7 @@ public class PartyApi extends QyApi {
if (party.getOrder() < 0) {
obj.remove("order");
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(department_update_uri, token.getAccessToken()),
obj.toJSONString());
@ -102,7 +102,7 @@ public class PartyApi extends QyApi {
if (partId > 0) {
department_list_uri += String.format("&id=%d", partId);
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
department_list_uri, token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("department"),
@ -121,7 +121,7 @@ public class PartyApi extends QyApi {
*/
public JsonResult deleteParty(int partId) throws WeixinException {
String department_delete_uri = getRequestUri("department_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(
department_delete_uri, token.getAccessToken(), partId));
return response.getAsJsonResult();

View File

@ -2,13 +2,14 @@ package com.foxinmy.weixin4j.qy.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.OUserInfo;
import com.foxinmy.weixin4j.qy.type.LoginTargetType;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.StringUtil;
/**
@ -22,13 +23,13 @@ import com.foxinmy.weixin4j.util.StringUtil;
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%99%BB%E5%BD%95%E6%8E%88%E6%9D%83">企业号登录授权说明</a>
*/
public class ProviderApi extends QyApi {
private final TokenHolder providerTokenHolder;
private final TokenStorager tokenStorager;
private final TokenManager providerTokenManager;
private final CacheStorager<Token> cacheStorager;
public ProviderApi(TokenHolder providerTokenHolder,
TokenStorager tokenStorager) {
this.providerTokenHolder = providerTokenHolder;
this.tokenStorager = tokenStorager;
public ProviderApi(TokenManager providerTokenManager,
CacheStorager<Token> cacheStorager) {
this.providerTokenManager = providerTokenManager;
this.cacheStorager = cacheStorager;
}
/**
@ -46,20 +47,22 @@ public class ProviderApi extends QyApi {
String oauth_logininfo_uri = getRequestUri("oauth_logininfo_uri");
WeixinResponse response = weixinExecutor.post(
String.format(oauth_logininfo_uri,
providerTokenHolder.getAccessToken()),
providerTokenManager.getAccessToken()),
String.format("{\"auth_code\":\"%s\"}", authCode));
JSONObject obj = response.getAsJson();
OUserInfo oUser = JSON.toJavaObject(obj, OUserInfo.class);
oUser.getRedirectLoginInfo().setAccessToken(
obj.getJSONObject("redirect_login_info").getString(
"login_ticket"));
tokenStorager.caching(getLoginTicketCacheKey(oUser.getCorpInfo()
obj = obj.getJSONObject("redirect_login_info");
Token loginInfo = new Token(obj.getString("login_ticket"),
obj.getLongValue("expires_in") * 1000l);
oUser.setRedirectLoginInfo(loginInfo);
cacheStorager.caching(getLoginTicketCacheKey(oUser.getCorpInfo()
.getCorpId()), oUser.getRedirectLoginInfo());
return oUser;
}
private String getLoginTicketCacheKey(String coprId) {
return String.format("weixin4j_qy_provider_ticket_%s", coprId);
return String.format("%sqy_provider_ticket_%s",
TokenCreator.CACHEKEY_PREFIX, coprId);
}
/**
@ -78,7 +81,7 @@ public class ProviderApi extends QyApi {
*/
public String getLoginUrl(String corpId, LoginTargetType targetType,
int agentId) throws WeixinException {
Token token = tokenStorager.lookup(getLoginTicketCacheKey(corpId));
Token token = cacheStorager.lookup(getLoginTicketCacheKey(corpId));
if (token == null || StringUtil.isBlank(token.getAccessToken())) {
throw new WeixinException("maybe oauth first?");
}
@ -91,7 +94,7 @@ public class ProviderApi extends QyApi {
}
WeixinResponse response = weixinExecutor.post(
String.format(oauth_loginurl_uri,
providerTokenHolder.getAccessToken()),
providerTokenManager.getAccessToken()),
obj.toJSONString());
return response.getAsJson().getString("login_url");
}

View File

@ -10,13 +10,13 @@ import com.foxinmy.weixin4j.qy.model.AgentInfo;
import com.foxinmy.weixin4j.qy.model.AgentSetter;
import com.foxinmy.weixin4j.qy.model.OUserInfo;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.suite.SuitePerCodeHolder;
import com.foxinmy.weixin4j.qy.suite.SuiteTicketHolder;
import com.foxinmy.weixin4j.qy.suite.SuitePerCodeManager;
import com.foxinmy.weixin4j.qy.suite.SuiteTicketManager;
import com.foxinmy.weixin4j.qy.suite.WeixinSuitePreCodeCreator;
import com.foxinmy.weixin4j.qy.suite.WeixinSuiteTokenCreator;
import com.foxinmy.weixin4j.qy.suite.WeixinTokenSuiteCreator;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 第三方应用套件
@ -32,29 +32,29 @@ public class SuiteApi extends QyApi {
/**
* 应用套件token
*/
private final TokenHolder suiteTokenHolder;
private final TokenManager suiteTokenManager;
/**
* 应用套件ticket
*/
private final SuiteTicketHolder suiteTicketHolder;
private final SuiteTicketManager suiteTicketManager;
/**
* 应用套件pre_code
*/
private final TokenHolder suitePreCodeHolder;
private final TokenManager suitePreCodeManager;
/**
*
* @param suiteTicketHolder
* @param suiteTicketManager
* 套件ticket存取
*/
public SuiteApi(SuiteTicketHolder suiteTicketHolder) {
this.suiteTicketHolder = suiteTicketHolder;
this.suiteTokenHolder = new TokenHolder(new WeixinSuiteTokenCreator(
suiteTicketHolder), suiteTicketHolder.getTokenStorager());
this.suitePreCodeHolder = new TokenHolder(
new WeixinSuitePreCodeCreator(suiteTokenHolder,
suiteTicketHolder.getSuiteId()),
suiteTicketHolder.getTokenStorager());
public SuiteApi(SuiteTicketManager suiteTicketManager) {
this.suiteTicketManager = suiteTicketManager;
this.suiteTokenManager = new TokenManager(new WeixinSuiteTokenCreator(
suiteTicketManager), suiteTicketManager.getCacheStorager());
this.suitePreCodeManager = new TokenManager(
new WeixinSuitePreCodeCreator(suiteTokenManager,
suiteTicketManager.getSuiteId()),
suiteTicketManager.getCacheStorager());
}
/**
@ -62,8 +62,8 @@ public class SuiteApi extends QyApi {
*
* @return
*/
public TokenHolder getSuiteTokenHolder() {
return this.suiteTokenHolder;
public TokenManager getSuiteTokenManager() {
return this.suiteTokenManager;
}
/**
@ -71,8 +71,8 @@ public class SuiteApi extends QyApi {
*
* @return
*/
public SuiteTicketHolder getTicketHolder() {
return this.suiteTicketHolder;
public SuiteTicketManager getTicketManager() {
return this.suiteTicketManager;
}
/**
@ -80,8 +80,8 @@ public class SuiteApi extends QyApi {
*
* @return
*/
public TokenHolder getPreCodeHolder() {
return this.suitePreCodeHolder;
public TokenManager getPreCodeManager() {
return this.suitePreCodeManager;
}
/**
@ -91,10 +91,10 @@ public class SuiteApi extends QyApi {
* 授权方corpid
* @return
*/
public SuitePerCodeHolder getPerCodeHolder(String authCorpId) {
return new SuitePerCodeHolder(authCorpId,
suiteTicketHolder.getSuiteId(),
suiteTicketHolder.getTokenStorager());
public SuitePerCodeManager getPerCodeManager(String authCorpId) {
return new SuitePerCodeManager(authCorpId,
suiteTicketManager.getSuiteId(),
suiteTicketManager.getCacheStorager());
}
/**
@ -104,10 +104,10 @@ public class SuiteApi extends QyApi {
* 授权方corpid
* @return 企业号token
*/
public TokenHolder getTokenSuiteHolder(String authCorpId) {
return new TokenHolder(new WeixinTokenSuiteCreator(
getPerCodeHolder(authCorpId), suiteTokenHolder),
suiteTicketHolder.getTokenStorager());
public TokenManager getTokenSuiteManager(String authCorpId) {
return new TokenManager(new WeixinTokenSuiteCreator(
getPerCodeManager(authCorpId), suiteTokenManager),
suiteTicketManager.getCacheStorager());
}
/**
@ -124,13 +124,14 @@ public class SuiteApi extends QyApi {
public JsonResult setSuiteSession(int... appids) throws WeixinException {
String suite_set_session_uri = getRequestUri("suite_set_session_uri");
JSONObject para = new JSONObject();
para.put("pre_auth_code", suitePreCodeHolder.getAccessToken());
para.put("pre_auth_code", suitePreCodeManager.getAccessToken());
JSONObject appid = new JSONObject();
appid.put("appid", appids);
para.put("session_info", appid);
WeixinResponse response = weixinExecutor
.post(String.format(suite_set_session_uri,
suiteTokenHolder.getAccessToken()), para.toJSONString());
WeixinResponse response = weixinExecutor.post(
String.format(suite_set_session_uri,
suiteTokenManager.getAccessToken()),
para.toJSONString());
return response.getAsJsonResult();
}
@ -150,28 +151,28 @@ public class SuiteApi extends QyApi {
throws WeixinException {
String suite_get_permanent_uri = getRequestUri("suite_get_permanent_uri");
JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("suite_id", suiteTicketManager.getSuiteId());
obj.put("auth_code", authCode);
WeixinResponse response = weixinExecutor.post(
String.format(suite_get_permanent_uri,
suiteTokenHolder.getAccessToken()), obj.toJSONString());
WeixinResponse response = weixinExecutor
.post(String.format(suite_get_permanent_uri,
suiteTokenManager.getAccessToken()), obj.toJSONString());
obj = response.getAsJson();
obj.put("corp_info", obj.remove("auth_corp_info"));
obj.put("user_info", obj.remove("auth_user_info"));
OUserInfo oInfo = JSON.toJavaObject(obj, OUserInfo.class);
// 微信授权企业号的永久授权码
SuitePerCodeHolder suitePerCodeHolder = getPerCodeHolder(oInfo
SuitePerCodeManager suitePerCodeManager = getPerCodeManager(oInfo
.getCorpInfo().getCorpId());
// 缓存微信企业号access_token
TokenCreator tokenCreator = new WeixinTokenSuiteCreator(
suitePerCodeHolder, suiteTokenHolder);
Token token = new Token(obj.getString("access_token"));
token.setExpiresIn(obj.getIntValue("expires_in"));
suiteTicketHolder.getTokenStorager().caching(
tokenCreator.key(), token);
suitePerCodeManager, suiteTokenManager);
Token token = new Token(obj.getString("access_token"),
obj.getLongValue("expires_in") * 1000l);
suiteTicketManager.getCacheStorager()
.caching(tokenCreator.key(), token);
// 缓存微信企业号永久授权码
suitePerCodeHolder
.cachingPermanentCode(obj.getString("permanent_code"));
suitePerCodeManager.cachingPermanentCode(obj
.getString("permanent_code"));
return oInfo;
}
@ -189,13 +190,13 @@ public class SuiteApi extends QyApi {
public OUserInfo getOAuthInfo(String authCorpId) throws WeixinException {
String suite_get_authinfo_uri = getRequestUri("suite_get_authinfo_uri");
JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("suite_id", suiteTicketManager.getSuiteId());
obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", getPerCodeHolder(authCorpId)
obj.put("permanent_code", getPerCodeManager(authCorpId)
.getPermanentCode());
WeixinResponse response = weixinExecutor.post(
String.format(suite_get_authinfo_uri,
suiteTokenHolder.getAccessToken()), obj.toJSONString());
WeixinResponse response = weixinExecutor
.post(String.format(suite_get_authinfo_uri,
suiteTokenManager.getAccessToken()), obj.toJSONString());
obj = response.getAsJson();
obj.put("corp_info", obj.remove("auth_corp_info"));
obj.put("user_info", obj.remove("auth_user_info"));
@ -219,14 +220,14 @@ public class SuiteApi extends QyApi {
throws WeixinException {
String suite_get_agent_uri = getRequestUri("suite_get_agent_uri");
JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("suite_id", suiteTicketManager.getSuiteId());
obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", getPerCodeHolder(authCorpId)
obj.put("permanent_code", getPerCodeManager(authCorpId)
.getPermanentCode());
obj.put("agentid", agentid);
WeixinResponse response = weixinExecutor.post(
String.format(suite_get_agent_uri,
suiteTokenHolder.getAccessToken()), obj.toJSONString());
WeixinResponse response = weixinExecutor
.post(String.format(suite_get_agent_uri,
suiteTokenManager.getAccessToken()), obj.toJSONString());
JSONObject jsonObj = response.getAsJson();
AgentInfo agent = JSON.toJavaObject(jsonObj, AgentInfo.class);
agent.setAllowUsers(JSON.parseArray(
@ -257,14 +258,14 @@ public class SuiteApi extends QyApi {
throws WeixinException {
String suite_set_agent_uri = getRequestUri("suite_set_agent_uri");
JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("suite_id", suiteTicketManager.getSuiteId());
obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", getPerCodeHolder(authCorpId)
obj.put("permanent_code", getPerCodeManager(authCorpId)
.getPermanentCode());
obj.put("agent", agentSet);
WeixinResponse response = weixinExecutor.post(
String.format(suite_set_agent_uri,
suiteTokenHolder.getAccessToken()),
suiteTokenManager.getAccessToken()),
JSON.toJSONString(obj, AgentApi.typeFilter));
return response.getAsJsonResult();
}

View File

@ -13,7 +13,7 @@ import com.foxinmy.weixin4j.qy.model.Contacts;
import com.foxinmy.weixin4j.qy.model.IdParameter;
import com.foxinmy.weixin4j.qy.model.Tag;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 标签API
@ -27,10 +27,10 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* 管理标签</a>
*/
public class TagApi extends QyApi {
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public TagApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
public TagApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
@ -47,7 +47,7 @@ public class TagApi extends QyApi {
*/
public int createTag(Tag tag) throws WeixinException {
String tag_create_uri = getRequestUri("tag_create_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
JSONObject obj = (JSONObject) JSON.toJSON(tag);
if (obj.getIntValue("tagid") <= 0) {
obj.remove("tagid");
@ -72,7 +72,7 @@ public class TagApi extends QyApi {
*/
public JsonResult updateTag(Tag tag) throws WeixinException {
String tag_update_uri = getRequestUri("tag_update_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(tag_update_uri, token.getAccessToken()),
JSON.toJSONString(tag));
@ -92,7 +92,7 @@ public class TagApi extends QyApi {
*/
public JsonResult deleteTag(int tagId) throws WeixinException {
String tag_delete_uri = getRequestUri("tag_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
tag_delete_uri, token.getAccessToken(), tagId));
return response.getAsJsonResult();
@ -110,7 +110,7 @@ public class TagApi extends QyApi {
*/
public List<Tag> listTag() throws WeixinException {
String tag_list_uri = getRequestUri("tag_list_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
tag_list_uri, token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("taglist"),
@ -133,7 +133,7 @@ public class TagApi extends QyApi {
*/
public Contacts getTagUsers(int tagId) throws WeixinException {
String tag_get_user_uri = getRequestUri("tag_get_user_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
tag_get_user_uri, token.getAccessToken(), tagId));
JSONObject obj = response.getAsJson();
@ -196,7 +196,7 @@ public class TagApi extends QyApi {
obj.put("tagid", tagId);
obj.put("userlist", userIds);
obj.put("partylist", partyIds);
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(uri, token.getAccessToken()), obj.toJSONString());
obj = response.getAsJson();

View File

@ -15,7 +15,7 @@ import com.foxinmy.weixin4j.qy.model.OUserInfo;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.type.InviteType;
import com.foxinmy.weixin4j.qy.type.UserStatus;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.NameValue;
import com.foxinmy.weixin4j.util.StringUtil;
@ -33,11 +33,11 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class UserApi extends QyApi {
private final MediaApi mediaApi;
private final TokenHolder tokenHolder;
private final TokenManager tokenManager;
public UserApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
this.mediaApi = new MediaApi(tokenHolder);
public UserApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
this.mediaApi = new MediaApi(tokenManager);
}
/**
@ -132,7 +132,7 @@ public class UserApi extends QyApi {
} else {
obj.put("avatar_mediaid", obj.remove("avatar"));
}
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(uri, token.getAccessToken()), obj.toJSONString());
return response.getAsJsonResult();
@ -152,7 +152,7 @@ public class UserApi extends QyApi {
*/
public User getUser(String userid) throws WeixinException {
String user_get_uri = getRequestUri("user_get_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
user_get_uri, token.getAccessToken(), userid));
JSONObject obj = response.getAsJson();
@ -202,7 +202,7 @@ public class UserApi extends QyApi {
*/
public String[] getUserIdByCode(String code) throws WeixinException {
String user_getid_uri = getRequestUri("user_getid_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
user_getid_uri, token.getAccessToken(), code));
JSONObject result = response.getAsJson();
@ -261,7 +261,7 @@ public class UserApi extends QyApi {
UserStatus userStatus, boolean findDetail) throws WeixinException {
String user_list_uri = findDetail ? getRequestUri("user_list_uri")
: getRequestUri("user_slist_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
if (userStatus == null) {
userStatus = UserStatus.UNFOLLOW;
}
@ -316,7 +316,7 @@ public class UserApi extends QyApi {
*/
public JsonResult deleteUser(String userid) throws WeixinException {
String user_delete_uri = getRequestUri("user_delete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
user_delete_uri, token.getAccessToken(), userid));
return response.getAsJsonResult();
@ -338,7 +338,7 @@ public class UserApi extends QyApi {
JSONObject obj = new JSONObject();
obj.put("useridlist", userIds);
String user_delete_uri = getRequestUri("user_batchdelete_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(
user_delete_uri, token.getAccessToken(), obj.toJSONString()));
return response.getAsJsonResult();
@ -357,7 +357,7 @@ public class UserApi extends QyApi {
*/
public JsonResult authsucc(String userId) throws WeixinException {
String user_authsucc_uri = getRequestUri("user_authsucc_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.get(String.format(
user_authsucc_uri, token.getAccessToken(), userId));
return response.getAsJsonResult();
@ -382,7 +382,7 @@ public class UserApi extends QyApi {
obj.put("userid", userId);
obj.put("invite_tips", tips);
String invite_user_uri = getRequestUri("invite_user_uri");
Token token = tokenHolder.getToken();
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(invite_user_uri, token.getAccessToken()),
obj.toJSONString());
@ -419,7 +419,7 @@ public class UserApi extends QyApi {
}
String userid2openid_uri = getRequestUri("userid2openid_uri");
WeixinResponse response = weixinExecutor.post(
String.format(userid2openid_uri, tokenHolder.getAccessToken()),
String.format(userid2openid_uri, tokenManager.getAccessToken()),
obj.toJSONString());
obj = response.getAsJson();
return new String[] { obj.getString("openid"), obj.getString("appid") };
@ -440,7 +440,7 @@ public class UserApi extends QyApi {
public String openid2userid(String openid) throws WeixinException {
String openid2userid_uri = getRequestUri("openid2userid_uri");
WeixinResponse response = weixinExecutor.post(
String.format(openid2userid_uri, tokenHolder.getAccessToken()),
String.format(openid2userid_uri, tokenManager.getAccessToken()),
String.format("{\"openid\": \"%s\"}", openid));
return response.getAsJson().getString("userid");
}

View File

@ -3,11 +3,10 @@ package com.foxinmy.weixin4j.qy.jssdk;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
@ -23,16 +22,16 @@ import com.foxinmy.weixin4j.util.RandomUtil;
* @see
*/
public class JSSDKContactConfigurator {
private final TokenHolder ticketTokenHolder;
private final TokenManager ticketTokenManager;
private JSSDKContactParameter contactParameter;
/**
* ticket保存类 可调用WeixinProxy#getTicketHolder获取
* ticket保存类 可调用WeixinProxy#getTicketManager获取
*
* @param ticketTokenHolder
* @param ticketTokenManager
*/
public JSSDKContactConfigurator(TokenHolder ticketTokenHolder) {
this.ticketTokenHolder = ticketTokenHolder;
public JSSDKContactConfigurator(TokenManager ticketTokenManager) {
this.ticketTokenManager = ticketTokenManager;
this.contactParameter = new JSSDKContactParameter();
}
@ -180,7 +179,7 @@ public class JSSDKContactConfigurator {
Map<String, String> signMap = new HashMap<String, String>();
String timestamp = DateUtil.timestamp2string();
String noncestr = RandomUtil.generateString(24);
Token token = this.ticketTokenHolder.getToken();
Token token = this.ticketTokenManager.getCache();
signMap.put("timestamp", timestamp);
signMap.put("nonceStr", noncestr);
signMap.put("group_ticket", token.getAccessToken());
@ -189,8 +188,7 @@ public class JSSDKContactConfigurator {
.toJoinString(signMap, false, true));
JSONObject config = new JSONObject();
config.put("signature", sign);
config.put("groupId", JSON.parseObject(token.getOriginalResult())
.getString("group_id"));
config.put("groupId", token.getExtra().get("group_id"));
config.put("timestamp", timestamp);
config.put("noncestr", noncestr);
config.put("params", parameter);

View File

@ -2,8 +2,6 @@ package com.foxinmy.weixin4j.qy.message;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.qy.type.ChatType;
import com.foxinmy.weixin4j.tuple.ChatTuple;
@ -39,11 +37,8 @@ public class ChatMessage implements Serializable {
*/
private ChatTuple chatTuple;
@JSONCreator
public ChatMessage(@JSONField(name = "targetId") String targetId,
@JSONField(name = "chatType") ChatType chatType,
@JSONField(name = "senderId") String senderId,
@JSONField(name = "chatTuple") ChatTuple chatTuple) {
public ChatMessage(String targetId, ChatType chatType, String senderId,
ChatTuple chatTuple) {
this.targetId = targetId;
this.chatType = chatType;
this.senderId = senderId;

View File

@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
/**
@ -34,14 +33,12 @@ public class ChatMute implements Serializable {
/**
* 传入true时开启免打扰
*
* @param userid
* @param userId
* 成员userid
* @param status
* 是否开启免打扰
*/
@JSONCreator
public ChatMute(@JSONField(name = "userId") String userId,
@JSONField(name = "status") boolean status) {
public ChatMute(String userId, boolean status) {
this.userId = userId;
this.status = status ? 1 : 0;
}

View File

@ -32,7 +32,7 @@ public class User implements Serializable {
*/
private String name;
/**
* 非必须 成员所属部门id列表注意每个部门的直属员工上限为1000个
* 非必须 成员所属部门id列表,不超过20个
*/
@JSONField(name = "department")
private List<Integer> partyIds;

View File

@ -1,29 +1,30 @@
package com.foxinmy.weixin4j.qy.suite;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.token.TokenCreator;
/**
* 应用套件永久授权码的存取
*
* @className SuitePerCodeHolder
* @className SuitePerCodeManager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年6月22日
* @since JDK 1.6
* @see
*/
public class SuitePerCodeHolder {
public class SuitePerCodeManager {
private final String authCorpId;
private final String suiteId;
private final TokenStorager tokenStorager;
private final CacheStorager<Token> cacheStorager;
public SuitePerCodeHolder(String authCorpId, String suiteId,
TokenStorager tokenStorager) {
public SuitePerCodeManager(String authCorpId, String suiteId,
CacheStorager<Token> cacheStorager) {
this.authCorpId = authCorpId;
this.suiteId = suiteId;
this.tokenStorager = tokenStorager;
this.cacheStorager = cacheStorager;
}
/**
@ -35,8 +36,7 @@ public class SuitePerCodeHolder {
public void cachingPermanentCode(String permanentCode)
throws WeixinException {
Token token = new Token(permanentCode);
token.setExpiresIn(-1);
tokenStorager.caching(getCacheKey(), token);
cacheStorager.caching(getCacheKey(), token);
}
/**
@ -45,8 +45,8 @@ public class SuitePerCodeHolder {
* @return
*/
public String getCacheKey() {
return String.format("weixin4j_qy_suite_percode_%s_%s", suiteId,
authCorpId);
return String.format("%sqy_suite_percode_%s_%s",
TokenCreator.CACHEKEY_PREFIX, suiteId, authCorpId);
}
/**
@ -56,7 +56,7 @@ public class SuitePerCodeHolder {
* @throws WeixinException
*/
public String getPermanentCode() throws WeixinException {
return tokenStorager.lookup(getCacheKey()).getAccessToken();
return cacheStorager.lookup(getCacheKey()).getAccessToken();
}
public String getSuiteId() {
@ -67,7 +67,7 @@ public class SuitePerCodeHolder {
return this.authCorpId;
}
public TokenStorager getTokenStorager() {
return this.tokenStorager;
public CacheStorager<Token> getCacheStorager() {
return this.cacheStorager;
}
}

View File

@ -1,29 +1,30 @@
package com.foxinmy.weixin4j.qy.suite;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.token.TokenCreator;
/**
* 应用套件ticket的存取
*
* @className SuiteTicketHolder
* @className SuiteTicketManager
* @author jinyu(foxinmy@gmail.com)
* @date 2015年6月22日
* @since JDK 1.6
* @see
*/
public class SuiteTicketHolder {
public class SuiteTicketManager {
private final String suiteId;
private final String suiteSecret;
private final TokenStorager tokenStorager;
private final CacheStorager<Token> cacheStorager;
public SuiteTicketHolder(String suiteId, String suiteSecret,
TokenStorager tokenStorager) {
public SuiteTicketManager(String suiteId, String suiteSecret,
CacheStorager<Token> cacheStorager) {
this.suiteId = suiteId;
this.suiteSecret = suiteSecret;
this.tokenStorager = tokenStorager;
this.cacheStorager = cacheStorager;
}
/**
@ -33,7 +34,7 @@ public class SuiteTicketHolder {
* @throws WeixinException
*/
public String getTicket() throws WeixinException {
return tokenStorager.lookup(getCacheKey()).getAccessToken();
return cacheStorager.lookup(getCacheKey()).getAccessToken();
}
/**
@ -42,7 +43,8 @@ public class SuiteTicketHolder {
* @return
*/
public String getCacheKey() {
return String.format("weixin4j_qy_suite_ticket_%s", suiteId);
return String.format("%sqy_suite_ticket_%s",
TokenCreator.CACHEKEY_PREFIX, suiteId);
}
/**
@ -53,8 +55,7 @@ public class SuiteTicketHolder {
*/
public void cachingTicket(String ticket) throws WeixinException {
Token token = new Token(ticket);
token.setExpiresIn(-1);
tokenStorager.caching(getCacheKey(), token);
cacheStorager.caching(getCacheKey(), token);
}
public String getSuiteId() {
@ -65,7 +66,7 @@ public class SuiteTicketHolder {
return this.suiteSecret;
}
public TokenStorager getTokenStorager() {
return this.tokenStorager;
public CacheStorager<Token> getCacheStorager() {
return this.cacheStorager;
}
}

View File

@ -3,6 +3,9 @@ package com.foxinmy.weixin4j.qy.suite;
import java.util.Arrays;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.cache.CacheStorager;
import com.foxinmy.weixin4j.cache.FileCacheStorager;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
import com.foxinmy.weixin4j.setting.SystemSettings;
@ -19,6 +22,10 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
* @see
*/
public class Weixin4jSuiteSettings extends SystemSettings<WeixinQyAccount> {
/**
* Token的存储方式 默认为FileCacheStorager
*/
private CacheStorager<Token> cacheStorager;
/**
* 默认使用weixin4j.properties配置的信息
@ -61,6 +68,17 @@ public class Weixin4jSuiteSettings extends SystemSettings<WeixinQyAccount> {
return getTmpdir();
}
public CacheStorager<Token> getCacheStorager() {
return cacheStorager;
}
public CacheStorager<Token> getCacheStorager0() {
if (cacheStorager == null) {
return new FileCacheStorager<Token>(getTmpdir0());
}
return cacheStorager;
}
@Override
public String toString() {
return "Weixin4jSuiteSettings [" + super.toString() + "]";

View File

@ -6,7 +6,7 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.type.URLConsts;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 微信企业号应用套件预授权码创建
@ -22,18 +22,19 @@ import com.foxinmy.weixin4j.token.TokenHolder;
*/
public class WeixinSuitePreCodeCreator extends TokenCreator {
private final TokenHolder suiteTokenHolder;
private final TokenManager suiteTokenManager;
private final String suiteId;
/**
*
* @param suiteTokenHolder
* @param suiteTokenManager
* 应用套件的token
* @param suiteId
* 应用套件ID
*/
public WeixinSuitePreCodeCreator(TokenHolder suiteTokenHolder, String suiteId) {
this.suiteTokenHolder = suiteTokenHolder;
public WeixinSuitePreCodeCreator(TokenManager suiteTokenManager,
String suiteId) {
this.suiteTokenManager = suiteTokenManager;
this.suiteId = suiteId;
}
@ -45,12 +46,11 @@ public class WeixinSuitePreCodeCreator extends TokenCreator {
@Override
public Token create() throws WeixinException {
WeixinResponse response = weixinExecutor.post(
String.format(URLConsts.SUITE_PRE_CODE_URL, suiteTokenHolder.getAccessToken()),
String.format(URLConsts.SUITE_PRE_CODE_URL,
suiteTokenManager.getAccessToken()),
String.format("{\"suite_id\":\"%s\"}", suiteId));
JSONObject result = response.getAsJson();
Token token = new Token(result.getString("pre_auth_code"));
token.setExpiresIn(result.getIntValue("expires_in"));
token.setOriginalResult(response.getAsString());
return token;
return new Token(result.getString("pre_auth_code"),
result.getLongValue("expires_in") * 1000l);
}
}

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.qy.suite;
package com.foxinmy.weixin4j.qy.suite;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
@ -20,34 +20,32 @@ import com.foxinmy.weixin4j.token.TokenCreator;
*/
public class WeixinSuiteTokenCreator extends TokenCreator {
private final SuiteTicketHolder ticketHolder;
private final SuiteTicketManager ticketManager;
/**
*
* @param stringStorager
* 套件ticket存取
* @param ticketManager
* 套件ticket存取
*/
public WeixinSuiteTokenCreator(SuiteTicketHolder ticketHolder) {
this.ticketHolder = ticketHolder;
public WeixinSuiteTokenCreator(SuiteTicketManager ticketManager) {
this.ticketManager = ticketManager;
}
@Override
public String key0() {
return String.format("qy_suite_token_%s", ticketHolder.getSuiteId());
return String.format("qy_suite_token_%s", ticketManager.getSuiteId());
}
@Override
public Token create() throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("suite_id", ticketHolder.getSuiteId());
obj.put("suite_secret", ticketHolder.getSuiteSecret());
obj.put("suite_ticket", ticketHolder.getTicket());
WeixinResponse response = weixinExecutor.post(URLConsts.SUITE_TOKEN_URL,
obj.toJSONString());
obj.put("suite_id", ticketManager.getSuiteId());
obj.put("suite_secret", ticketManager.getSuiteSecret());
obj.put("suite_ticket", ticketManager.getTicket());
WeixinResponse response = weixinExecutor.post(
URLConsts.SUITE_TOKEN_URL, obj.toJSONString());
obj = response.getAsJson();
Token token = new Token(obj.getString("suite_access_token"));
token.setExpiresIn(obj.getIntValue("expires_in"));
token.setOriginalResult(response.getAsString());
return token;
return new Token(obj.getString("suite_access_token"),
obj.getLongValue("expires_in") * 1000l);
}
}

View File

@ -6,7 +6,7 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.type.URLConsts;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
/**
* 微信企业号token创建(永久授权码)
@ -22,38 +22,39 @@ import com.foxinmy.weixin4j.token.TokenHolder;
*/
public class WeixinTokenSuiteCreator extends TokenCreator {
private final SuitePerCodeHolder perCodeHolder;
private final TokenHolder suiteTokenHolder;
private final SuitePerCodeManager perCodeManager;
private final TokenManager suiteTokenManager;
/**
*
* @param perCodeHolder
* @param perCodeManager
* 第三方套件永久授权码
* @param suiteTokenHolder
* @param suitetokenManager
* 第三方套件凭证token
*/
public WeixinTokenSuiteCreator(SuitePerCodeHolder perCodeHolder, TokenHolder suiteTokenHolder) {
this.perCodeHolder = perCodeHolder;
this.suiteTokenHolder = suiteTokenHolder;
public WeixinTokenSuiteCreator(SuitePerCodeManager perCodeManager,
TokenManager suiteTokenManager) {
this.perCodeManager = perCodeManager;
this.suiteTokenManager = suiteTokenManager;
}
@Override
public String key0() {
return String.format("qy_token_suite_%s_%s", perCodeHolder.getSuiteId(), perCodeHolder.getAuthCorpId());
return String.format("qy_token_suite_%s_%s",
perCodeManager.getSuiteId(), perCodeManager.getAuthCorpId());
}
@Override
public Token create() throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("suite_id", perCodeHolder.getSuiteId());
obj.put("auth_corpid", perCodeHolder.getAuthCorpId());
obj.put("permanent_code", perCodeHolder.getPermanentCode());
obj.put("suite_id", perCodeManager.getSuiteId());
obj.put("auth_corpid", perCodeManager.getAuthCorpId());
obj.put("permanent_code", perCodeManager.getPermanentCode());
WeixinResponse response = weixinExecutor
.post(String.format(URLConsts.TOKEN_SUITE_URL, suiteTokenHolder.getAccessToken()), obj.toJSONString());
.post(String.format(URLConsts.TOKEN_SUITE_URL,
suiteTokenManager.getAccessToken()), obj.toJSONString());
obj = response.getAsJson();
Token token = new Token(obj.getString("access_token"));
token.setExpiresIn(obj.getIntValue("expires_in"));
token.setOriginalResult(response.getAsString());
return token;
return new Token(obj.getString("access_token"),
obj.getLongValue("expires_in") * 1000l);
}
}

View File

@ -10,7 +10,7 @@ import com.foxinmy.weixin4j.token.TokenCreator;
/**
* 微信企业号应用提供商凭证创建
*
* @className WeixinTokenCreator
* @className WeixinProviderTokenCreator
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月10日
* @since JDK 1.6
@ -46,11 +46,10 @@ public class WeixinProviderTokenCreator extends TokenCreator {
JSONObject obj = new JSONObject();
obj.put("corpid", corpid);
obj.put("provider_secret", providersecret);
WeixinResponse response = weixinExecutor.post(URLConsts.PROVIDER_TOKEN_URL, obj.toJSONString());
WeixinResponse response = weixinExecutor.post(
URLConsts.PROVIDER_TOKEN_URL, obj.toJSONString());
obj = response.getAsJson();
Token token = new Token(obj.getString("provider_access_token"));
token.setExpiresIn(obj.getIntValue("expires_in"));
token.setOriginalResult(response.getAsString());
return token;
return new Token(obj.getString("provider_access_token"),
obj.getLongValue("expires_in") * 1000l);
}
}

View File

@ -6,7 +6,7 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.type.URLConsts;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.type.TicketType;
/**
@ -23,20 +23,21 @@ public class WeixinTicketCreator extends TokenCreator {
private final String corpid;
private final TicketType ticketType;
private final TokenHolder weixinTokenHolder;
private final TokenManager weixinTokenManager;
/**
* @param corpid
* 企业号ID
* @param ticketType
* 票据类型
* @param weixinTokenHolder
* <font color="red">企业号的access_token</font>
* @param weixinTokenManager
* <font color="red">企业号的access_token</font>
*/
public WeixinTicketCreator(String corpid, TicketType ticketType, TokenHolder weixinTokenHolder) {
public WeixinTicketCreator(String corpid, TicketType ticketType,
TokenManager weixinTokenManager) {
this.corpid = corpid;
this.ticketType = ticketType;
this.weixinTokenHolder = weixinTokenHolder;
this.weixinTokenManager = weixinTokenManager;
}
@Override
@ -48,16 +49,16 @@ public class WeixinTicketCreator extends TokenCreator {
public Token create() throws WeixinException {
WeixinResponse response = null;
if (ticketType == TicketType.jsapi) {
response = weixinExecutor
.get(String.format(URLConsts.JS_TICKET_URL, weixinTokenHolder.getToken().getAccessToken()));
response = weixinExecutor.get(String.format(
URLConsts.JS_TICKET_URL, weixinTokenManager.getCache()
.getAccessToken()));
} else {
response = weixinExecutor.get(String.format(URLConsts.SUITE_TICKET_URL,
weixinTokenHolder.getToken().getAccessToken(), ticketType.name()));
response = weixinExecutor.get(String.format(
URLConsts.SUITE_TICKET_URL, weixinTokenManager.getCache()
.getAccessToken(), ticketType.name()));
}
JSONObject result = response.getAsJson();
Token token = new Token(result.getString("ticket"));
token.setExpiresIn(result.getIntValue("expires_in"));
token.setOriginalResult(response.getAsString());
return token;
return new Token(result.getString("ticket"),
result.getLong("expires_in") * 1000l);
}
}

View File

@ -1,6 +1,6 @@
package com.foxinmy.weixin4j.qy.token;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
@ -46,10 +46,8 @@ public class WeixinTokenCreator extends TokenCreator {
String tokenUrl = String.format(URLConsts.ASSESS_TOKEN_URL, corpid,
corpsecret);
WeixinResponse response = weixinExecutor.get(tokenUrl);
Token token = response.getAsObject(new TypeReference<Token>() {
});
token.setCreateTime(System.currentTimeMillis());
token.setOriginalResult(response.getAsString());
return token;
JSONObject result = response.getAsJson();
return new Token(result.getString("access_token"),
result.getLongValue("expires_in") * 1000l);
}
}

Some files were not shown because too many files have changed in this diff Show More