issue #91 添加企业号JS_API的支持

This commit is contained in:
Daniel Qian
2015-01-27 14:45:11 +08:00
parent 6d383fa90e
commit 5b49c63d14
18 changed files with 232 additions and 42 deletions

View File

@@ -0,0 +1,12 @@
package me.chanjar.weixin.common.api;
import me.chanjar.weixin.common.exception.WxErrorException;
/**
* WxErrorException处理器
*/
public interface WxErrorExceptionHandler {
public void handle(WxErrorException e);
}

View File

@@ -0,0 +1,27 @@
package me.chanjar.weixin.common.api;
/**
* <pre>
* 消息重复检查器
* 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次
* </pre>
*/
public interface WxMessageDuplicateChecker {
/**
* <h2>公众号的排重方式</h2>
*
* <p>普通消息关于重试的消息排重推荐使用msgid排重。<a href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html">文档参考</a>。</p>
* <p>事件消息关于重试的消息排重推荐使用FromUserName + CreateTime 排重。<a href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html">文档参考</a></p>
*
* <h2>企业号的排重方式</h2>
*
* 官方文档完全没有写,参照公众号的方式排重。
*
* <p>或者可以采取更简单的方式如果有MsgId就用MsgId排重如果没有就用FromUserName+CreateTime排重</p>
* @param messageId messageId需要根据上面讲的方式构造
* @return 如果是重复消息返回true否则返回false
*/
public boolean isDuplicate(String messageId);
}

View File

@@ -0,0 +1,98 @@
package me.chanjar.weixin.common.api;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* <pre>
* 默认消息重复检查器
* 将每个消息id保存在内存里每隔5秒清理已经过期的消息id每个消息id的过期时间是15秒
* </pre>
*/
public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker {
/**
* 一个消息ID在内存的过期时间15秒
*/
private final Long timeToLive;
/**
* 每隔多少周期检查消息ID是否过期5秒
*/
private final Long clearPeriod;
/**
* 消息id->消息时间戳的map
*/
private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<String, Long>();
/**
* 后台清理线程是否已经开启
*/
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
/**
* WxMsgIdInMemoryDuplicateChecker构造函数
* <pre>
* 一个消息ID在内存的过期时间15秒
* 每隔多少周期检查消息ID是否过期5秒
* </pre>
*/
public WxMessageInMemoryDuplicateChecker() {
this.timeToLive = 15 * 1000l;
this.clearPeriod = 5 * 1000l;
}
/**
* WxMsgIdInMemoryDuplicateChecker构造函数
* @param timeToLive 一个消息ID在内存的过期时间毫秒
* @param clearPeriod 每隔多少周期检查消息ID是否过期毫秒
*/
public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {
this.timeToLive = timeToLive;
this.clearPeriod = clearPeriod;
}
protected void checkBackgroundProcessStarted() {
if (backgroundProcessStarted.getAndSet(true)) {
return;
}
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
Thread.sleep(clearPeriod);
Long now = System.currentTimeMillis();
for (Map.Entry<String, Long> entry : msgId2Timestamp.entrySet()) {
if (now - entry.getValue() > timeToLive) {
msgId2Timestamp.entrySet().remove(entry);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
}
@Override
public boolean isDuplicate(String messageId) {
if (messageId == null) {
return false;
}
checkBackgroundProcessStarted();
Long timestamp = msgId2Timestamp.putIfAbsent(messageId, System.currentTimeMillis());
if (timestamp == null) {
// 第一次接收到这个消息
return false;
}
return true;
}
}