diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageDuplicateChecker.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageDuplicateChecker.java index 21f21c5d4..1abe588b0 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageDuplicateChecker.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageDuplicateChecker.java @@ -9,10 +9,19 @@ package me.chanjar.weixin.common.util; public interface WxMessageDuplicateChecker { /** - * 检查消息ID是否重复 - * @param wxMsgId + *

公众号的排重方式

+ * + *

普通消息:关于重试的消息排重,推荐使用msgid排重。文档参考

+ *

事件消息:关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。文档参考

+ * + *

企业号的排重方式

+ * + * 官方文档完全没有写,参照公众号的方式排重。 + * + *

或者可以采取更简单的方式,如果有MsgId就用MsgId排重,如果没有就用FromUserName+CreateTime排重

+ * @param messageId messageId需要根据上面讲的方式构造 * @return 如果是重复消息,返回true,否则返回false */ - public boolean isDuplicate(Long wxMsgId); + public boolean isDuplicate(String messageId); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateChecker.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateChecker.java index f132ca541..ae0e06231 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateChecker.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateChecker.java @@ -25,7 +25,7 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec /** * 消息id->消息时间戳的map */ - private final ConcurrentHashMap msgId2Timestamp = new ConcurrentHashMap(); + private final ConcurrentHashMap msgId2Timestamp = new ConcurrentHashMap(); /** * 后台清理线程是否已经开启 @@ -65,7 +65,7 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec while (true) { Thread.sleep(clearPeriod); Long now = System.currentTimeMillis(); - for (Map.Entry entry : msgId2Timestamp.entrySet()) { + for (Map.Entry entry : msgId2Timestamp.entrySet()) { if (now - entry.getValue() > timeToLive) { msgId2Timestamp.entrySet().remove(entry); } @@ -81,12 +81,12 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec } @Override - public boolean isDuplicate(Long wxMsgId) { - if (wxMsgId == null) { + public boolean isDuplicate(String messageId) { + if (messageId == null) { return false; } checkBackgroundProcessStarted(); - Long timestamp = msgId2Timestamp.putIfAbsent(wxMsgId, System.currentTimeMillis()); + Long timestamp = msgId2Timestamp.putIfAbsent(messageId, System.currentTimeMillis()); if (timestamp == null) { // 第一次接收到这个消息 return false; diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateCheckerTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateCheckerTest.java index 55e990701..28642c44d 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateCheckerTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/WxMessageInMemoryDuplicateCheckerTest.java @@ -12,21 +12,21 @@ public class WxMessageInMemoryDuplicateCheckerTest { // 第一次检查 for (Long msgId : msgIds) { - boolean result = checker.isDuplicate(msgId); + boolean result = checker.isDuplicate(String.valueOf(msgId)); Assert.assertFalse(result); } // 过1秒再检查 Thread.sleep(1000l); for (Long msgId : msgIds) { - boolean result = checker.isDuplicate(msgId); + boolean result = checker.isDuplicate(String.valueOf(msgId)); Assert.assertTrue(result); } // 过1.5秒再检查 Thread.sleep(1500l); for (Long msgId : msgIds) { - boolean result = checker.isDuplicate(msgId); + boolean result = checker.isDuplicate(String.valueOf(msgId)); Assert.assertFalse(result); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java index 7ae9d4444..34b36ec31 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java @@ -115,7 +115,7 @@ public class WxCpMessageRouter { * @param wxMessage */ public WxCpXmlOutMessage route(final WxCpXmlMessage wxMessage) { - if (messageDuplicateChecker.isDuplicate(wxMessage.getMsgId())) { + if (isDuplicateMessage(wxMessage)) { // 如果是重复消息,那么就不做处理 return null; } @@ -177,6 +177,22 @@ public class WxCpMessageRouter { return res; } + protected boolean isDuplicateMessage(WxCpXmlMessage wxMessage) { + + String messageId = ""; + if (wxMessage.getMsgId() == null) { + messageId = wxMessage.getFromUserName() + "-" + String.valueOf(wxMessage.getCreateTime()); + } else { + messageId = String.valueOf(wxMessage.getMsgId()); + } + + if (messageDuplicateChecker.isDuplicate(messageId)) { + return true; + } + return false; + + } + /** * 对session的访问结束 * @param wxMessage diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java index 5c09b48f5..afd8d3fb4 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.mp.api; +import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.session.*; import me.chanjar.weixin.common.util.WxMessageDuplicateChecker; import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker; @@ -113,7 +114,7 @@ public class WxMpMessageRouter { * @param wxMessage */ public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage) { - if (messageDuplicateChecker.isDuplicate(wxMessage.getMsgId())) { + if (isDuplicateMessage(wxMessage)) { // 如果是重复消息,那么就不做处理 return null; } @@ -175,6 +176,22 @@ public class WxMpMessageRouter { return res; } + protected boolean isDuplicateMessage(WxMpXmlMessage wxMessage) { + + String messageId = ""; + if (wxMessage.getMsgId() == null) { + messageId = wxMessage.getFromUserName() + "-" + String.valueOf(wxMessage.getCreateTime()); + } else { + messageId = String.valueOf(wxMessage.getMsgId()); + } + + if (messageDuplicateChecker.isDuplicate(messageId)) { + return true; + } + return false; + + } + /** * 对session的访问结束 * @param wxMessage