From ac18a2cc5ca914995bf9b9a70c436c16f5d899a1 Mon Sep 17 00:00:00 2001 From: tanglong <842690096@qq.com> Date: Tue, 2 Jun 2026 11:55:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wecom/WecomCallbackController.java | 29 +++++++++++++++++++ .../integration/wecom/WecomClient.java | 16 ++++++++++ .../agentfoundation/service/ChatService.java | 12 ++++++++ 3 files changed, 57 insertions(+) diff --git a/src/main/java/com/company/agentfoundation/integration/wecom/WecomCallbackController.java b/src/main/java/com/company/agentfoundation/integration/wecom/WecomCallbackController.java index 5447253..d1da1d6 100644 --- a/src/main/java/com/company/agentfoundation/integration/wecom/WecomCallbackController.java +++ b/src/main/java/com/company/agentfoundation/integration/wecom/WecomCallbackController.java @@ -6,6 +6,8 @@ import com.company.agentfoundation.domain.ChatResponse; import com.company.agentfoundation.security.AgentContext; import com.company.agentfoundation.service.ChatService; import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -19,6 +21,7 @@ import java.util.List; @RestController @RequestMapping("/v1/integrations/wecom") public class WecomCallbackController { + private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class); private final FoundationProperties properties; private final ChatService chatService; private final WecomClient wecomClient; @@ -44,10 +47,13 @@ public class WecomCallbackController { @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr ) { + log.info("wecom callback verify received safeMode={} timestamp={} nonce={}", wecomCryptoService.isSafeModeEnabled(), timestamp, nonce); String payload = wecomCryptoService.isSafeModeEnabled() ? echostr : null; if (!wecomCryptoService.validateSignature(signature, timestamp, nonce, payload)) { + log.warn("wecom callback verify signature invalid timestamp={} nonce={}", timestamp, nonce); throw new IllegalArgumentException("Invalid WeCom signature"); } + log.info("wecom callback verify success safeMode={}", wecomCryptoService.isSafeModeEnabled()); return wecomCryptoService.isSafeModeEnabled() ? wecomCryptoService.decrypt(echostr) : echostr; } @@ -58,13 +64,22 @@ public class WecomCallbackController { @RequestParam("nonce") String nonce, @RequestBody String body ) throws Exception { + log.info("wecom callback message received safeMode={} timestamp={} nonce={} bodyLength={}", + wecomCryptoService.isSafeModeEnabled(), timestamp, nonce, body == null ? 0 : body.length()); WecomIncomingMessage msg = parseIncomingMessage(signature, timestamp, nonce, body); + log.info("wecom callback parsed fromUser={} toUser={} msgType={} contentPreview={}", + msg == null ? null : msg.getFromUserName(), + msg == null ? null : msg.getToUserName(), + msg == null ? null : msg.getMsgType(), + preview(msg == null ? null : msg.getContent())); if (msg == null || msg.getMsgType() == null || !"text".equalsIgnoreCase(msg.getMsgType())) { + log.info("wecom callback ignored non-text message"); return "success"; } String userText = msg.getContent() == null ? "" : msg.getContent().trim(); if (userText.isBlank()) { + log.info("wecom callback ignored blank text"); return "success"; } @@ -77,11 +92,14 @@ public class WecomCallbackController { 0.3 ); + log.info("wecom callback invoking crm agent agentId={} fromUser={}", properties.getWecom().getCrmAgentId(), msg.getFromUserName()); ChatResponse chat = chatService.chat(new AgentContext(properties.getWecom().getCrmAgentId()), req); String reply = (chat.content() == null || chat.content().isBlank()) ? "Request received, but I could not generate advice right now." : chat.content(); + log.info("wecom callback agent response traceId={} replyPreview={}", chat.traceId(), preview(reply)); wecomClient.sendText(msg.getFromUserName(), reply); + log.info("wecom callback reply sent toUser={}", msg.getFromUserName()); return "success"; } @@ -89,18 +107,29 @@ public class WecomCallbackController { if (wecomCryptoService.isSafeModeEnabled()) { WecomEncryptedEnvelope envelope = xmlMapper.readValue(body, WecomEncryptedEnvelope.class); if (envelope == null || envelope.getEncrypt() == null || envelope.getEncrypt().isBlank()) { + log.warn("wecom callback encrypted envelope missing encrypt field"); throw new IllegalArgumentException("Missing WeCom encrypted payload"); } if (!wecomCryptoService.validateSignature(signature, timestamp, nonce, envelope.getEncrypt())) { + log.warn("wecom callback encrypted signature invalid timestamp={} nonce={}", timestamp, nonce); throw new IllegalArgumentException("Invalid WeCom signature"); } String plainXml = wecomCryptoService.decrypt(envelope.getEncrypt()); + log.info("wecom callback decrypt success plainXmlLength={}", plainXml.length()); return xmlMapper.readValue(plainXml, WecomIncomingMessage.class); } if (!wecomCryptoService.validateSignature(signature, timestamp, nonce, null)) { + log.warn("wecom callback plain signature invalid timestamp={} nonce={}", timestamp, nonce); throw new IllegalArgumentException("Invalid WeCom signature"); } return xmlMapper.readValue(body, WecomIncomingMessage.class); } + + private String preview(String text) { + if (text == null || text.isBlank()) { + return ""; + } + return text.length() <= 80 ? text : text.substring(0, 80) + "..."; + } } diff --git a/src/main/java/com/company/agentfoundation/integration/wecom/WecomClient.java b/src/main/java/com/company/agentfoundation/integration/wecom/WecomClient.java index d37ff2f..624748e 100644 --- a/src/main/java/com/company/agentfoundation/integration/wecom/WecomClient.java +++ b/src/main/java/com/company/agentfoundation/integration/wecom/WecomClient.java @@ -1,6 +1,8 @@ package com.company.agentfoundation.integration.wecom; import com.company.agentfoundation.config.FoundationProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; @@ -9,6 +11,7 @@ import java.time.Instant; @Service public class WecomClient { + private static final Logger log = LoggerFactory.getLogger(WecomClient.class); private final FoundationProperties properties; private final WebClient webClient; @@ -21,6 +24,7 @@ public class WecomClient { } public void sendText(String toUser, String content) { + log.info("wecom sendText start toUser={} agentId={} contentPreview={}", toUser, properties.getWecom().getAgentId(), preview(content)); String token = getAccessToken(); WecomSendMessageRequest req = new WecomSendMessageRequest(); req.setToUser(toUser); @@ -38,12 +42,15 @@ public class WecomClient { .block(); if (response == null || !response.success()) { + log.error("wecom sendText failed toUser={} err={}", toUser, response == null ? "null" : response.errmsg()); throw new IllegalStateException("WeCom send failed: " + (response == null ? "null" : response.errmsg())); } + log.info("wecom sendText success toUser={}", toUser); } private String getAccessToken() { if (cachedToken != null && Instant.now().isBefore(tokenExpireAt)) { + log.info("wecom gettoken use cached token expireAt={}", tokenExpireAt); return cachedToken; } @@ -57,12 +64,21 @@ public class WecomClient { .block(); if (response == null || !response.success() || response.accessToken() == null) { + log.error("wecom gettoken failed err={}", response == null ? "null" : response.errmsg()); throw new IllegalStateException("WeCom gettoken failed: " + (response == null ? "null" : response.errmsg())); } cachedToken = response.accessToken(); int expires = response.expiresIn() == null ? 7200 : response.expiresIn(); tokenExpireAt = Instant.now().plusSeconds(Math.max(300, expires - 120)); + log.info("wecom gettoken success expireAt={}", tokenExpireAt); return cachedToken; } + + private String preview(String text) { + if (text == null || text.isBlank()) { + return ""; + } + return text.length() <= 80 ? text : text.substring(0, 80) + "..."; + } } diff --git a/src/main/java/com/company/agentfoundation/service/ChatService.java b/src/main/java/com/company/agentfoundation/service/ChatService.java index f498bf1..3df5a74 100644 --- a/src/main/java/com/company/agentfoundation/service/ChatService.java +++ b/src/main/java/com/company/agentfoundation/service/ChatService.java @@ -5,17 +5,21 @@ import com.company.agentfoundation.api.DeepseekClient; import com.company.agentfoundation.domain.ChatRequest; import com.company.agentfoundation.domain.ChatResponse; import com.company.agentfoundation.security.AgentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.time.Instant; import java.util.UUID; @Service public class ChatService { + private static final Logger log = LoggerFactory.getLogger(ChatService.class); private final DeepseekClient deepseekClient; private final ModelRouter modelRouter; public ChatService(DeepseekClient deepseekClient, ModelRouter modelRouter) { this.deepseekClient = deepseekClient; this.modelRouter = modelRouter; } public ChatResponse chat(AgentContext context, ChatRequest request) { String traceId = UUID.randomUUID().toString(); String model = modelRouter.routeModel(context.agentId(), request.model()); + log.info("chat start traceId={} agentId={} model={} messageCount={}", traceId, context.agentId(), model, request.messages() == null ? 0 : request.messages().size()); DeepseekChatResponse resp = deepseekClient.chat(new DeepseekChatRequest( model, request.messages().stream().map(m -> new DeepseekChatRequest.Message(m.role(), m.content())).toList(), @@ -25,6 +29,14 @@ public class ChatService { if (resp != null && resp.choices() != null && !resp.choices().isEmpty() && resp.choices().get(0).message() != null) content = resp.choices().get(0).message().content(); ChatResponse.Usage usage = null; if (resp != null && resp.usage() != null) usage = new ChatResponse.Usage(resp.usage().prompt_tokens(), resp.usage().completion_tokens(), resp.usage().total_tokens()); + log.info("chat success traceId={} totalTokens={} replyPreview={}", traceId, usage == null ? null : usage.totalTokens(), preview(content)); return new ChatResponse(traceId, context.agentId(), model, content, usage, Instant.now()); } + + private String preview(String text) { + if (text == null || text.isBlank()) { + return ""; + } + return text.length() <= 80 ? text : text.substring(0, 80) + "..."; + } }