重复两次

This commit is contained in:
tanglong 2026-06-12 13:54:57 +08:00
parent 8a14ae619f
commit cfe5bfdf6f
2 changed files with 43 additions and 0 deletions

View File

@ -13,15 +13,21 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RestController
@RequestMapping("/v1/integrations/wecom")
public class WecomCallbackController {
private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class);
private static final long MESSAGE_DEDUP_TTL_SECONDS = 600;
private final FoundationProperties properties;
private final WecomClient wecomClient;
private final WecomCryptoService wecomCryptoService;
private final AgentOrchestratorService agentOrchestratorService;
private final XmlMapper xmlMapper = new XmlMapper();
private final Map<String, Long> processedMessages = new ConcurrentHashMap<>();
public WecomCallbackController(
FoundationProperties properties,
@ -79,6 +85,11 @@ public class WecomCallbackController {
return "success";
}
if (isDuplicateMessage(msg)) {
log.info("wecom callback duplicate message ignored fromUser={} msgId={}", msg.getFromUserName(), msg.getMsgId());
return "success";
}
log.info("wecom callback invoking agent orchestrator agentId={} fromUser={}", properties.getWecom().getCrmAgentId(), msg.getFromUserName());
String reply = agentOrchestratorService.handleMessage(properties.getWecom().getCrmAgentId(), msg.getFromUserName(), userText);
reply = (reply == null || reply.isBlank())
@ -113,6 +124,30 @@ public class WecomCallbackController {
return xmlMapper.readValue(body, WecomIncomingMessage.class);
}
private boolean isDuplicateMessage(WecomIncomingMessage msg) {
evictExpiredMessages();
String key = messageDedupKey(msg);
Long previous = processedMessages.putIfAbsent(key, Instant.now().getEpochSecond());
return previous != null;
}
private String messageDedupKey(WecomIncomingMessage msg) {
if (msg.getMsgId() != null && !msg.getMsgId().isBlank()) {
return msg.getMsgId();
}
return "%s:%s:%s:%s".formatted(
msg.getFromUserName(),
msg.getToUserName(),
msg.getCreateTime(),
msg.getContent()
);
}
private void evictExpiredMessages() {
long expireBefore = Instant.now().minusSeconds(MESSAGE_DEDUP_TTL_SECONDS).getEpochSecond();
processedMessages.entrySet().removeIf(entry -> entry.getValue() < expireBefore);
}
private String preview(String text) {
if (text == null || text.isBlank()) {
return "";

View File

@ -15,6 +15,10 @@ public class WecomIncomingMessage {
private String msgType;
@JacksonXmlProperty(localName = "Content")
private String content;
@JacksonXmlProperty(localName = "CreateTime")
private Long createTime;
@JacksonXmlProperty(localName = "MsgId")
private String msgId;
public String getToUserName() { return toUserName; }
public void setToUserName(String toUserName) { this.toUserName = toUserName; }
@ -24,4 +28,8 @@ public class WecomIncomingMessage {
public void setMsgType(String msgType) { this.msgType = msgType; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public Long getCreateTime() { return createTime; }
public void setCreateTime(Long createTime) { this.createTime = createTime; }
public String getMsgId() { return msgId; }
public void setMsgId(String msgId) { this.msgId = msgId; }
}