From 87fd7b502ba861dbec7a80876bf24bde249fd5da Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 04:59:12 +0000 Subject: [PATCH 1/3] Initial plan From 93417276dcacebeedbb290cc3cf355676e090131 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 05:07:02 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BC=81=E4=B8=9A?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=99=BA=E8=83=BD=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?JSON=E5=9B=9E=E8=B0=83=E6=B6=88=E6=81=AF=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=B9=B6=E8=A1=A5=E5=85=85=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/binarywang/WxJava/sessions/07e83fbe-cc11-4b67-82ec-6cb21fb184a3 Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- weixin-java-cp/INTELLIGENT_ROBOT.md | 11 +- .../WxCpIntelligentRobotMessage.java | 196 ++++++++++++++++++ .../WxCpIntelligentRobotMessageTest.java | 76 +++++++ 3 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessage.java create mode 100644 weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessageTest.java diff --git a/weixin-java-cp/INTELLIGENT_ROBOT.md b/weixin-java-cp/INTELLIGENT_ROBOT.md index dcd90e1a1a..093a55660b 100644 --- a/weixin-java-cp/INTELLIGENT_ROBOT.md +++ b/weixin-java-cp/INTELLIGENT_ROBOT.md @@ -109,6 +109,15 @@ String fromUser = message.getFromUserName(); // 发送用户 // ... ``` +对于智能机器人 API 模式的 JSON 回调消息,可使用 `WxCpIntelligentRobotMessage` 解析: + +```java +WxCpIntelligentRobotMessage callbackMessage = WxCpIntelligentRobotMessage.fromJson(jsonBody); +String botId = callbackMessage.getAiBotId(); +String userId = callbackMessage.getFrom().getUserid(); +String msgType = callbackMessage.getMsgType(); +``` + ### 删除智能机器人 ```java @@ -146,4 +155,4 @@ robotService.deleteRobot(robotId); 1. 需要确保企业微信应用具有智能机器人相关权限 2. 智能机器人功能可能需要特定的企业微信版本支持 3. 会话ID可以用于保持对话的连续性,提升用户体验 -4. 机器人状态: 0表示停用,1表示启用 \ No newline at end of file +4. 机器人状态: 0表示停用,1表示启用 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessage.java new file mode 100644 index 0000000000..d485b59d69 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessage.java @@ -0,0 +1,196 @@ +package me.chanjar.weixin.cp.bean.intelligentrobot; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 企业微信智能机器人回调消息. + * + *

官方文档: https://developer.work.weixin.qq.com/document/path/100719

+ */ +@Data +public class WxCpIntelligentRobotMessage implements Serializable { + private static final long serialVersionUID = -1L; + + /** + * 本次回调的唯一性标志. + */ + @SerializedName("msgid") + private String msgId; + + /** + * 智能机器人id. + */ + @SerializedName("aibotid") + private String aiBotId; + + /** + * 会话id,仅群聊类型时返回. + */ + @SerializedName("chatid") + private String chatId; + + /** + * 会话类型,single/group. + */ + @SerializedName("chattype") + private String chatType; + + /** + * 消息发送者. + */ + @SerializedName("from") + private From from; + + /** + * 支持主动回复消息的临时url. + */ + @SerializedName("response_url") + private String responseUrl; + + /** + * 消息类型. + */ + @SerializedName("msgtype") + private String msgType; + + @SerializedName("text") + private Text text; + + @SerializedName("image") + private Image image; + + @SerializedName("mixed") + private Mixed mixed; + + @SerializedName("voice") + private Voice voice; + + @SerializedName("file") + private FileInfo file; + + @SerializedName("video") + private Video video; + + @SerializedName("quote") + private Quote quote; + + @SerializedName("stream") + private Stream stream; + + public static WxCpIntelligentRobotMessage fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpIntelligentRobotMessage.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + @Data + public static class From implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("userid") + private String userid; + } + + @Data + public static class Text implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("content") + private String content; + } + + @Data + public static class Image implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("url") + private String url; + } + + @Data + public static class Voice implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("content") + private String content; + } + + @Data + public static class FileInfo implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("url") + private String url; + } + + @Data + public static class Video implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("url") + private String url; + } + + @Data + public static class Stream implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("id") + private String id; + } + + @Data + public static class Mixed implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("msg_item") + private List msgItem; + } + + @Data + public static class MixedItem implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("msgtype") + private String msgType; + + @SerializedName("text") + private Text text; + + @SerializedName("image") + private Image image; + } + + @Data + public static class Quote implements Serializable { + private static final long serialVersionUID = -1L; + + @SerializedName("msgtype") + private String msgType; + + @SerializedName("text") + private Text text; + + @SerializedName("image") + private Image image; + + @SerializedName("mixed") + private Mixed mixed; + + @SerializedName("voice") + private Voice voice; + + @SerializedName("file") + private FileInfo file; + + @SerializedName("video") + private Video video; + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessageTest.java new file mode 100644 index 0000000000..f8f8791d0d --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotMessageTest.java @@ -0,0 +1,76 @@ +package me.chanjar.weixin.cp.bean.intelligentrobot; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; + +/** + * 智能机器人回调消息测试. + */ +public class WxCpIntelligentRobotMessageTest { + + @Test + public void testFromJsonWithTextMessage() { + String json = "{" + + "\"msgid\":\"msg_1\"," + + "\"aibotid\":\"bot_1\"," + + "\"chatid\":\"chat_1\"," + + "\"chattype\":\"group\"," + + "\"from\":{\"userid\":\"zhangsan\"}," + + "\"response_url\":\"https://example.com/reply\"," + + "\"msgtype\":\"text\"," + + "\"text\":{\"content\":\"@robot hello\"}" + + "}"; + + WxCpIntelligentRobotMessage message = WxCpIntelligentRobotMessage.fromJson(json); + assertEquals(message.getMsgId(), "msg_1"); + assertEquals(message.getAiBotId(), "bot_1"); + assertEquals(message.getChatId(), "chat_1"); + assertEquals(message.getChatType(), "group"); + assertNotNull(message.getFrom()); + assertEquals(message.getFrom().getUserid(), "zhangsan"); + assertEquals(message.getResponseUrl(), "https://example.com/reply"); + assertEquals(message.getMsgType(), "text"); + assertNotNull(message.getText()); + assertEquals(message.getText().getContent(), "@robot hello"); + assertNull(message.getMixed()); + assertNull(message.getStream()); + } + + @Test + public void testFromJsonWithMixedAndQuote() { + String json = "{" + + "\"msgid\":\"msg_2\"," + + "\"aibotid\":\"bot_2\"," + + "\"chattype\":\"single\"," + + "\"from\":{\"userid\":\"lisi\"}," + + "\"msgtype\":\"mixed\"," + + "\"mixed\":{\"msg_item\":[" + + "{\"msgtype\":\"text\",\"text\":{\"content\":\"hello\"}}," + + "{\"msgtype\":\"image\",\"image\":{\"url\":\"https://example.com/1.png\"}}" + + "]}," + + "\"quote\":{\"msgtype\":\"text\",\"text\":{\"content\":\"quoted\"}}" + + "}"; + + WxCpIntelligentRobotMessage message = WxCpIntelligentRobotMessage.fromJson(json); + assertEquals(message.getMsgType(), "mixed"); + assertNotNull(message.getMixed()); + assertNotNull(message.getMixed().getMsgItem()); + assertEquals(message.getMixed().getMsgItem().size(), 2); + assertEquals(message.getMixed().getMsgItem().get(0).getMsgType(), "text"); + assertEquals(message.getMixed().getMsgItem().get(0).getText().getContent(), "hello"); + assertEquals(message.getMixed().getMsgItem().get(1).getMsgType(), "image"); + assertEquals(message.getMixed().getMsgItem().get(1).getImage().getUrl(), "https://example.com/1.png"); + assertNotNull(message.getQuote()); + assertEquals(message.getQuote().getMsgType(), "text"); + assertEquals(message.getQuote().getText().getContent(), "quoted"); + + String serialized = message.toJson(); + WxCpIntelligentRobotMessage deserialized = WxCpIntelligentRobotMessage.fromJson(serialized); + assertEquals(deserialized.getAiBotId(), "bot_2"); + assertEquals(deserialized.getFrom().getUserid(), "lisi"); + assertEquals(deserialized.getMixed().getMsgItem().size(), 2); + } +} From 2782478a0e55d7e4ca9be3ffbe2a7d3a3faa0a20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 May 2026 01:55:02 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=E4=B8=BA=E6=99=BA=E8=83=BD=E6=9C=BA?= =?UTF-8?q?=E5=99=A8=E4=BA=BA=E5=9B=9E=E8=B0=83=E6=A8=A1=E5=9E=8B=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E6=9C=8D=E5=8A=A1=E8=B0=83=E7=94=A8=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/binarywang/WxJava/sessions/153a6a9d-1d0b-4a49-a3c4-493265b9b6fa Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- weixin-java-cp/INTELLIGENT_ROBOT.md | 3 ++- .../weixin/cp/api/WxCpIntelligentRobotService.java | 10 +++++++++- .../api/impl/WxCpIntelligentRobotServiceImpl.java | 7 ++++++- .../impl/WxCpIntelligentRobotServiceImplTest.java | 13 ++++++++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/weixin-java-cp/INTELLIGENT_ROBOT.md b/weixin-java-cp/INTELLIGENT_ROBOT.md index 093a55660b..18dd0c677f 100644 --- a/weixin-java-cp/INTELLIGENT_ROBOT.md +++ b/weixin-java-cp/INTELLIGENT_ROBOT.md @@ -112,7 +112,8 @@ String fromUser = message.getFromUserName(); // 发送用户 对于智能机器人 API 模式的 JSON 回调消息,可使用 `WxCpIntelligentRobotMessage` 解析: ```java -WxCpIntelligentRobotMessage callbackMessage = WxCpIntelligentRobotMessage.fromJson(jsonBody); +WxCpIntelligentRobotMessage callbackMessage = + robotService.parseCallbackMessage(jsonBody); String botId = callbackMessage.getAiBotId(); String userId = callbackMessage.getFrom().getUserid(); String msgType = callbackMessage.getMsgType(); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpIntelligentRobotService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpIntelligentRobotService.java index bc5f3f1915..58f4373ceb 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpIntelligentRobotService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpIntelligentRobotService.java @@ -74,4 +74,12 @@ public interface WxCpIntelligentRobotService { */ WxCpIntelligentRobotSendMessageResponse sendMessage(WxCpIntelligentRobotSendMessageRequest request) throws WxErrorException; -} \ No newline at end of file + /** + * 解析智能机器人 API 模式回调消息. + * + * @param callbackMessageJson 回调消息JSON + * @return 解析后的回调消息对象 + */ + WxCpIntelligentRobotMessage parseCallbackMessage(String callbackMessageJson); + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImpl.java index 8a12fa4ff4..aba1ee85c4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImpl.java @@ -67,4 +67,9 @@ public WxCpIntelligentRobotSendMessageResponse sendMessage(WxCpIntelligentRobotS return WxCpIntelligentRobotSendMessageResponse.fromJson(responseText); } -} \ No newline at end of file + @Override + public WxCpIntelligentRobotMessage parseCallbackMessage(String callbackMessageJson) { + return WxCpIntelligentRobotMessage.fromJson(callbackMessageJson); + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImplTest.java index 85104ee73a..843bf6aac0 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpIntelligentRobotServiceImplTest.java @@ -119,4 +119,15 @@ public void testSendMessageResponse() { assert response.getSessionId().equals("session123"); assert response.getErrcode() == 0; } -} \ No newline at end of file + + @Test + public void testParseCallbackMessage() { + String callbackJson = "{\"msgid\":\"msg_1\",\"aibotid\":\"bot_1\",\"chattype\":\"single\"," + + "\"from\":{\"userid\":\"user_1\"},\"msgtype\":\"text\",\"text\":{\"content\":\"hello\"}}"; + WxCpIntelligentRobotMessage message = this.wxCpService.getIntelligentRobotService().parseCallbackMessage(callbackJson); + assert message.getMsgId().equals("msg_1"); + assert message.getAiBotId().equals("bot_1"); + assert message.getFrom().getUserid().equals("user_1"); + assert message.getText().getContent().equals("hello"); + } +}