From 27de971e8c6bc8117e5a07db6077e4f9bc964d20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:27:35 +0000 Subject: [PATCH] Implement WeChat Intelligent Conversation support in MP module Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- .../weixin/mp/api/WxMpAiOpenService.java | 47 +++++++++++++++ .../mp/api/impl/WxMpAiOpenServiceImpl.java | 58 +++++++++++++++++++ .../mp/bean/WxMpAiConversationRequest.java | 40 +++++++++++++ .../mp/bean/WxMpAiConversationResponse.java | 44 ++++++++++++++ .../chanjar/weixin/mp/enums/WxMpApiUrl.java | 6 +- .../api/impl/WxMpAiOpenServiceImplTest.java | 28 +++++++++ 6 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationRequest.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationResponse.java diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java index 07bc1e52e..1f0939939 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java @@ -3,6 +3,8 @@ package me.chanjar.weixin.mp.api; import java.io.File; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.bean.WxMpAiConversationRequest; +import me.chanjar.weixin.mp.bean.WxMpAiConversationResponse; import me.chanjar.weixin.mp.enums.AiLangType; /** @@ -76,4 +78,49 @@ public interface WxMpAiOpenService { * @throws WxErrorException the wx error exception */ String translate(AiLangType langFrom, AiLangType langTo, String content) throws WxErrorException; + + /** + *
+ * 微信智能对话. + * 基于WeChat AI Speech平台的智能对话功能 + * + * 文档地址:https://developers.weixin.qq.com/doc/aispeech/platform/INTRODUCTION.html + *+ * + * @param query 用户输入的对话内容 + * @param sessionId 会话ID,用于保持对话上下文 + * @return 智能对话回复内容 + * @throws WxErrorException the wx error exception + */ + String intelligentConversation(String query, String sessionId) throws WxErrorException; + + /** + *
+ * 微信智能对话(带语言参数). + * 基于WeChat AI Speech平台的智能对话功能 + * + * 文档地址:https://developers.weixin.qq.com/doc/aispeech/platform/INTRODUCTION.html + *+ * + * @param query 用户输入的对话内容 + * @param sessionId 会话ID,用于保持对话上下文 + * @param lang 语言类型,默认中文 + * @return 智能对话回复内容 + * @throws WxErrorException the wx error exception + */ + String intelligentConversation(String query, String sessionId, AiLangType lang) throws WxErrorException; + + /** + *
+ * 微信智能对话(使用请求对象). + * 基于WeChat AI Speech平台的智能对话功能,支持更复杂的请求参数 + * + * 文档地址:https://developers.weixin.qq.com/doc/aispeech/platform/INTRODUCTION.html + *+ * + * @param request 智能对话请求对象 + * @return 智能对话响应对象 + * @throws WxErrorException the wx error exception + */ + WxMpAiConversationResponse intelligentConversation(WxMpAiConversationRequest request) throws WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImpl.java index 9c9bbe84c..aa483c57f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImpl.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.mp.api.impl; +import com.google.gson.JsonObject; import lombok.RequiredArgsConstructor; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; @@ -7,6 +8,8 @@ import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.json.GsonParser; import me.chanjar.weixin.mp.api.WxMpAiOpenService; import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.WxMpAiConversationRequest; +import me.chanjar.weixin.mp.bean.WxMpAiConversationResponse; import me.chanjar.weixin.mp.enums.AiLangType; import me.chanjar.weixin.mp.util.requestexecuter.voice.VoiceUploadRequestExecutor; @@ -70,4 +73,59 @@ public class WxMpAiOpenServiceImpl implements WxMpAiOpenService { return GsonParser.parse(response).get("result").getAsString(); } + + @Override + public String intelligentConversation(String query, String sessionId) throws WxErrorException { + return this.intelligentConversation(query, sessionId, AiLangType.zh_CN); + } + + @Override + public String intelligentConversation(String query, String sessionId, AiLangType lang) throws WxErrorException { + if (lang == null) { + lang = AiLangType.zh_CN; + } + + // 构建请求JSON + JsonObject request = new JsonObject(); + request.addProperty("query", query); + request.addProperty("session_id", sessionId); + request.addProperty("lang", lang.getCode()); + + final String response = this.wxMpService.post(INTELLIGENT_CONVERSATION_URL.getUrl(this.wxMpService.getWxMpConfigStorage()), + request.toString()); + + WxError error = WxError.fromJson(response, WxType.MP); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + + return GsonParser.parse(response).get("reply").getAsString(); + } + + @Override + public WxMpAiConversationResponse intelligentConversation(WxMpAiConversationRequest request) throws WxErrorException { + // 构建请求JSON + JsonObject requestJson = new JsonObject(); + requestJson.addProperty("query", request.getQuery()); + requestJson.addProperty("session_id", request.getSessionId()); + requestJson.addProperty("lang", request.getLang() != null ? request.getLang().getCode() : AiLangType.zh_CN.getCode()); + + final String response = this.wxMpService.post(INTELLIGENT_CONVERSATION_URL.getUrl(this.wxMpService.getWxMpConfigStorage()), + requestJson.toString()); + + WxError error = WxError.fromJson(response, WxType.MP); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + + WxMpAiConversationResponse result = WxMpAiConversationResponse.fromJson(response); + if (result.getReply() == null) { + result.setReply(GsonParser.parse(response).get("reply").getAsString()); + } + if (result.getSessionId() == null) { + result.setSessionId(request.getSessionId()); + } + + return result; + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationRequest.java new file mode 100644 index 000000000..f38dffc84 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationRequest.java @@ -0,0 +1,40 @@ +package me.chanjar.weixin.mp.bean; + +import lombok.Data; +import me.chanjar.weixin.mp.enums.AiLangType; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * 微信智能对话请求对象 + * + * @author Binary Wang + */ +@Data +public class WxMpAiConversationRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户输入的对话内容 + */ + private String query; + + /** + * 会话ID,用于保持对话上下文 + */ + private String sessionId; + + /** + * 语言类型,默认中文 + */ + private AiLangType lang = AiLangType.zh_CN; + + public String toJson() { + return WxMpGsonBuilder.create().toJson(this); + } + + public static WxMpAiConversationRequest fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpAiConversationRequest.class); + } +} \ No newline at end of file diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationResponse.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationResponse.java new file mode 100644 index 000000000..905f704e5 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpAiConversationResponse.java @@ -0,0 +1,44 @@ +package me.chanjar.weixin.mp.bean; + +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * 微信智能对话响应对象 + * + * @author Binary Wang + */ +@Data +public class WxMpAiConversationResponse implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 智能对话回复内容 + */ + private String reply; + + /** + * 会话ID + */ + private String sessionId; + + /** + * 错误码 + */ + private Integer errcode; + + /** + * 错误消息 + */ + private String errmsg; + + public String toJson() { + return WxMpGsonBuilder.create().toJson(this); + } + + public static WxMpAiConversationResponse fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpAiConversationResponse.class); + } +} \ No newline at end of file diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java index dc317bd40..d3df0fa05 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java @@ -469,7 +469,11 @@ public interface WxMpApiUrl { /** * queryrecoresultfortext. */ - VOICE_QUERY_RESULT_URL(API_DEFAULT_HOST_URL, "/cgi-bin/media/voice/queryrecoresultfortext"); + VOICE_QUERY_RESULT_URL(API_DEFAULT_HOST_URL, "/cgi-bin/media/voice/queryrecoresultfortext"), + /** + * 智能对话. + */ + INTELLIGENT_CONVERSATION_URL(API_DEFAULT_HOST_URL, "/cgi-bin/aispeech/conversation"); private final String prefix; private final String path; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImplTest.java index 9cf770ac5..dd73de562 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpAiOpenServiceImplTest.java @@ -8,6 +8,8 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.test.ApiTestModule; +import me.chanjar.weixin.mp.bean.WxMpAiConversationRequest; +import me.chanjar.weixin.mp.bean.WxMpAiConversationResponse; import me.chanjar.weixin.mp.enums.AiLangType; import static org.assertj.core.api.Assertions.assertThat; @@ -45,4 +47,30 @@ public class WxMpAiOpenServiceImplTest { final String result = this.wxService.getAiOpenService().translate(AiLangType.zh_CN, AiLangType.en_US, "微信文档很坑爹"); assertThat(result).isNotEmpty(); } + + @Test + public void testIntelligentConversation() throws WxErrorException { + String sessionId = "test_session_" + System.currentTimeMillis(); + final String result = this.wxService.getAiOpenService().intelligentConversation("你好", sessionId); + assertThat(result).isNotEmpty(); + } + + @Test + public void testIntelligentConversationWithLang() throws WxErrorException { + String sessionId = "test_session_" + System.currentTimeMillis(); + final String result = this.wxService.getAiOpenService().intelligentConversation("你好,请介绍一下微信", sessionId, AiLangType.zh_CN); + assertThat(result).isNotEmpty(); + } + + @Test + public void testIntelligentConversationWithRequest() throws WxErrorException { + WxMpAiConversationRequest request = new WxMpAiConversationRequest(); + request.setQuery("微信智能对话功能怎么使用?"); + request.setSessionId("test_session_bean_" + System.currentTimeMillis()); + request.setLang(AiLangType.zh_CN); + + final WxMpAiConversationResponse result = this.wxService.getAiOpenService().intelligentConversation(request); + assertThat(result).isNotNull(); + assertThat(result.getReply()).isNotEmpty(); + } }