diff --git a/weixin-java-cp/INTELLIGENT_ROBOT.md b/weixin-java-cp/INTELLIGENT_ROBOT.md index f2641bd6b..dcd90e1a1 100644 --- a/weixin-java-cp/INTELLIGENT_ROBOT.md +++ b/weixin-java-cp/INTELLIGENT_ROBOT.md @@ -73,6 +73,42 @@ String sessionId = "session123"; robotService.resetSession(robotId, userid, sessionId); ``` +### 主动发送消息 + +智能机器人可以主动向用户发送消息,用于推送通知或提醒。 + +```java +WxCpIntelligentRobotSendMessageRequest request = new WxCpIntelligentRobotSendMessageRequest(); +request.setRobotId("robot_id_here"); +request.setUserid("user123"); +request.setMessage("您好,这是来自智能机器人的主动消息"); +request.setSessionId("session123"); // 可选,用于保持会话连续性 + +WxCpIntelligentRobotSendMessageResponse response = robotService.sendMessage(request); +String msgId = response.getMsgId(); +String sessionId = response.getSessionId(); +``` + +### 接收用户消息 + +当用户向智能机器人发送消息时,企业微信会通过回调接口推送消息。可以使用 `WxCpXmlMessage` 接收和解析这些消息: + +```java +// 在接收回调消息的接口中 +WxCpXmlMessage message = WxCpXmlMessage.fromEncryptedXml( + requestBody, wxCpConfigStorage, timestamp, nonce, msgSignature +); + +// 获取智能机器人相关字段 +String robotId = message.getRobotId(); // 机器人ID +String sessionId = message.getSessionId(); // 会话ID +String content = message.getContent(); // 消息内容 +String fromUser = message.getFromUserName(); // 发送用户 + +// 处理消息并回复 +// ... +``` + ### 删除智能机器人 ```java @@ -87,13 +123,19 @@ robotService.deleteRobot(robotId); - `WxCpIntelligentRobotCreateRequest`: 创建机器人请求 - `WxCpIntelligentRobotUpdateRequest`: 更新机器人请求 - `WxCpIntelligentRobotChatRequest`: 智能对话请求 +- `WxCpIntelligentRobotSendMessageRequest`: 主动发送消息请求 ### 响应类 - `WxCpIntelligentRobotCreateResponse`: 创建机器人响应 - `WxCpIntelligentRobotChatResponse`: 智能对话响应 +- `WxCpIntelligentRobotSendMessageResponse`: 主动发送消息响应 - `WxCpIntelligentRobot`: 机器人信息实体 +### 消息接收 + +- `WxCpXmlMessage`: 支持接收智能机器人回调消息,包含 `robotId` 和 `sessionId` 字段 + ### 服务接口 - `WxCpIntelligentRobotService`: 智能机器人服务接口 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 f68092918..bc5f3f191 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 @@ -64,4 +64,14 @@ public interface WxCpIntelligentRobotService { */ void resetSession(String robotId, String userid, String sessionId) throws WxErrorException; + /** + * 智能机器人主动发送消息 + * 官方文档: https://developer.work.weixin.qq.com/document/path/100719 + * + * @param request 发送消息请求参数 + * @return 发送消息响应 + * @throws WxErrorException 微信接口异常 + */ + WxCpIntelligentRobotSendMessageResponse sendMessage(WxCpIntelligentRobotSendMessageRequest request) throws WxErrorException; + } \ No newline at end of file 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 c3bb23b38..8a12fa4ff 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 @@ -61,4 +61,10 @@ public void resetSession(String robotId, String userid, String sessionId) throws this.cpService.post(RESET_SESSION, jsonObject.toString()); } + @Override + public WxCpIntelligentRobotSendMessageResponse sendMessage(WxCpIntelligentRobotSendMessageRequest request) throws WxErrorException { + String responseText = this.cpService.post(SEND_MESSAGE, request.toJson()); + return WxCpIntelligentRobotSendMessageResponse.fromJson(responseText); + } + } \ No newline at end of file diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotSendMessageRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotSendMessageRequest.java new file mode 100644 index 000000000..405c67daf --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotSendMessageRequest.java @@ -0,0 +1,56 @@ +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; + +/** + * 智能机器人发送消息请求 + * 官方文档: https://developer.work.weixin.qq.com/document/path/100719 + * + * @author Binary Wang + */ +@Data +public class WxCpIntelligentRobotSendMessageRequest implements Serializable { + private static final long serialVersionUID = -1L; + + /** + * 机器人ID,必填 + */ + @SerializedName("robot_id") + private String robotId; + + /** + * 接收消息的用户ID,必填 + */ + @SerializedName("userid") + private String userid; + + /** + * 消息内容,必填 + */ + @SerializedName("message") + private String message; + + /** + * 会话ID,可选,用于保持会话连续性 + */ + @SerializedName("session_id") + private String sessionId; + + /** + * 消息ID,可选 + */ + @SerializedName("msg_id") + private String msgId; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + public static WxCpIntelligentRobotSendMessageRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpIntelligentRobotSendMessageRequest.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotSendMessageResponse.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotSendMessageResponse.java new file mode 100644 index 000000000..8098d2037 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/intelligentrobot/WxCpIntelligentRobotSendMessageResponse.java @@ -0,0 +1,42 @@ +package me.chanjar.weixin.cp.bean.intelligentrobot; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 智能机器人发送消息响应 + * 官方文档: https://developer.work.weixin.qq.com/document/path/100719 + * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxCpIntelligentRobotSendMessageResponse extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -1L; + + /** + * 消息ID + */ + @SerializedName("msg_id") + private String msgId; + + /** + * 会话ID + */ + @SerializedName("session_id") + private String sessionId; + + public static WxCpIntelligentRobotSendMessageResponse fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpIntelligentRobotSendMessageResponse.class); + } + + @Override + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java index c5e55220e..d15eda882 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java @@ -253,6 +253,24 @@ public class WxCpXmlMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String linkId; + /** + * 智能机器人ID + * 接收智能机器人消息时使用 + * https://developer.work.weixin.qq.com/document/path/100719 + */ + @XStreamAlias("RobotId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String robotId; + + /** + * 智能机器人会话ID + * 接收智能机器人消息时使用,用于保持会话连续性 + * https://developer.work.weixin.qq.com/document/path/100719 + */ + @XStreamAlias("SessionId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String sessionId; + /** * 通讯录变更事件. * 请参考常量 me.chanjar.weixin.cp.constant.WxCpConsts.ContactChangeType diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java index 91314e587..ad4d4f33f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java @@ -1666,5 +1666,11 @@ interface IntelligentRobot { * 重置智能机器人会话 */ String RESET_SESSION = "/cgi-bin/intelligent_robot/reset_session"; + + /** + * 智能机器人主动发送消息 + * 官方文档: https://developer.work.weixin.qq.com/document/path/100719 + */ + String SEND_MESSAGE = "/cgi-bin/intelligent_robot/send_message"; } } 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 2765b4991..85104ee73 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 @@ -85,4 +85,38 @@ public void testServiceIntegration() { assert this.wxCpService.getIntelligentRobotService() != null; assert this.wxCpService.getIntelligentRobotService() instanceof WxCpIntelligentRobotServiceImpl; } + + @Test + public void testSendMessageRequest() { + // 测试主动发送消息请求对象创建 + WxCpIntelligentRobotSendMessageRequest request = new WxCpIntelligentRobotSendMessageRequest(); + request.setRobotId("robot123"); + request.setUserid("user123"); + request.setMessage("您好,这是来自智能机器人的主动消息"); + request.setSessionId("session123"); + request.setMsgId("msg123"); + + // 验证JSON序列化 + String json = request.toJson(); + assert json.contains("robot123"); + assert json.contains("您好,这是来自智能机器人的主动消息"); + assert json.contains("session123"); + + // 验证反序列化 + WxCpIntelligentRobotSendMessageRequest fromJson = WxCpIntelligentRobotSendMessageRequest.fromJson(json); + assert fromJson.getRobotId().equals("robot123"); + assert fromJson.getMessage().equals("您好,这是来自智能机器人的主动消息"); + assert fromJson.getSessionId().equals("session123"); + } + + @Test + public void testSendMessageResponse() { + // 测试主动发送消息响应对象 + String responseJson = "{\"errcode\":0,\"errmsg\":\"ok\",\"msg_id\":\"msg123\",\"session_id\":\"session123\"}"; + WxCpIntelligentRobotSendMessageResponse response = WxCpIntelligentRobotSendMessageResponse.fromJson(responseJson); + + assert response.getMsgId().equals("msg123"); + assert response.getSessionId().equals("session123"); + assert response.getErrcode() == 0; + } } \ No newline at end of file diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessageTest.java index ae4fbba8f..94874519c 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessageTest.java @@ -471,4 +471,30 @@ public void testMsgIdStringAndNumericFormats() { WxCpXmlMessage wxMessageString = WxCpXmlMessage.fromXml(xmlWithString); assertEquals(wxMessageString.getMsgId(), "CAIQg/PKxgYY2sC9tpuAgAMg9/zKaw=="); } + + /** + * Test intelligent robot message parsing + * 测试智能机器人消息解析 + */ + public void testIntelligentRobotMessage() { + String xml = "" + + "" + + "" + + "1348831860" + + "" + + "" + + "msg123456" + + "" + + "" + + ""; + WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml); + assertEquals(wxMessage.getToUserName(), "toUser"); + assertEquals(wxMessage.getFromUserName(), "fromUser"); + assertEquals(wxMessage.getCreateTime(), Long.valueOf(1348831860)); + assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.TEXT); + assertEquals(wxMessage.getContent(), "你好,智能机器人"); + assertEquals(wxMessage.getMsgId(), "msg123456"); + assertEquals(wxMessage.getRobotId(), "robot_id_123"); + assertEquals(wxMessage.getSessionId(), "session_id_456"); + } }