From cd490aa0e5c208c90d00fabba3d4951fc8837aee Mon Sep 17 00:00:00 2001 From: ageerle <ageerle@163.com> Date: 星期三, 30 四月 2025 11:29:23 +0800 Subject: [PATCH] feat: 新增wechat模块 --- ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/SubscribeHandler.java | 63 ++++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LocationHandler.java | 44 +++ ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/impl/ChatVxServiceImpl.java | 37 ++ ruoyi-modules/ruoyi-wechat/pom.xml | 28 ++ ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/IChatVxService.java | 19 + ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/TextBuilder.java | 22 + ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/EnterAgentHandler.java | 29 ++ ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java | 18 - ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/AbstractHandler.java | 9 ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/UnsubscribeHandler.java | 28 ++ ruoyi-modules/pom.xml | 1 ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MsgHandler.java | 43 +++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/controller/wxcplogin/WxPortalController.java | 86 ++++++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ScanHandler.java | 8 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/ISseService.java | 7 ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MenuHandler.java | 34 ++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpConfiguration.java | 130 ++++++++++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/AbstractBuilder.java | 12 ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LogHandler.java | 26 ++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpProperties.java | 45 +++ ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/ImageBuilder.java | 24 + ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/NullHandler.java | 23 + ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ContactChangeHandler.java | 34 ++ 23 files changed, 745 insertions(+), 25 deletions(-) diff --git a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/IChatVxService.java b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/IChatVxService.java new file mode 100644 index 0000000..60ed4ff --- /dev/null +++ b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/IChatVxService.java @@ -0,0 +1,19 @@ +package org.ruoyi.service; + +/** + * 浼佷笟寰俊鑱婂ぉ绠$悊Service鎺ュ彛 + * + * @author ageerle + * @date 2025-04-08 + */ +public interface IChatVxService { + + + /** + * 浼佷笟寰俊搴旂敤鍥炲 + * @param prompt 鎻愮ず璇� + * @return 鍥炲鍐呭 + */ + String chat(String prompt); + +} diff --git a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/impl/ChatVxServiceImpl.java b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/impl/ChatVxServiceImpl.java new file mode 100644 index 0000000..7b013b5 --- /dev/null +++ b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/service/impl/ChatVxServiceImpl.java @@ -0,0 +1,37 @@ +package org.ruoyi.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.ruoyi.common.chat.entity.chat.ChatCompletion; +import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; +import org.ruoyi.common.chat.entity.chat.Message; +import org.ruoyi.common.chat.openai.OpenAiStreamClient; +import org.ruoyi.service.IChatVxService; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Slf4j +@RequiredArgsConstructor +public class ChatVxServiceImpl implements IChatVxService { + + private final OpenAiStreamClient openAiStreamClient; + + @Override + public String chat(String prompt) { + List<Message> messageList = new ArrayList<>(); + Message message = Message.builder().role(Message.Role.USER).content(prompt).build(); + messageList.add(message); + ChatCompletion chatCompletion = ChatCompletion + .builder() + .messages(messageList) + .model("gpt-4o-mini") + .stream(false) + .build(); + ChatCompletionResponse chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion); + return chatCompletionResponse.getChoices().get(0).getMessage().getContent().toString(); + } + +} diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml index 1b3ff0c..044e0bc 100644 --- a/ruoyi-modules/pom.xml +++ b/ruoyi-modules/pom.xml @@ -21,6 +21,7 @@ <module>ruoyi-chat</module> <module>ruoyi-system</module> <module>ruoyi-generator</module> + <module>ruoyi-wechat</module> </modules> <properties> diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/ISseService.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/ISseService.java index c025642..1fb66ba 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/ISseService.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/ISseService.java @@ -48,11 +48,4 @@ UploadFileResponse upload(MultipartFile file); - /** - * 浼佷笟搴旂敤鍥炲 - * @param prompt 鎻愮ず璇� - * @return 鍥炲鍐呭 - */ - String wxCpChat(String prompt); - } diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java index eb0ae4e..b6759f5 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java @@ -14,8 +14,6 @@ import org.ruoyi.chat.util.SSEUtil; import org.ruoyi.common.chat.config.LocalCache; import org.ruoyi.common.chat.entity.Tts.TextToSpeech; -import org.ruoyi.common.chat.entity.chat.ChatCompletion; -import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; import org.ruoyi.common.chat.entity.chat.Message; import org.ruoyi.common.chat.entity.files.UploadFileResponse; import org.ruoyi.common.chat.entity.whisper.WhisperResponse; @@ -269,22 +267,6 @@ e.printStackTrace(); } return file; - } - - - @Override - public String wxCpChat(String prompt) { - List<Message> messageList = new ArrayList<>(); - Message message = Message.builder().role(Message.Role.USER).content(prompt).build(); - messageList.add(message); - ChatCompletion chatCompletion = ChatCompletion - .builder() - .messages(messageList) - .model("gpt-4o-mini") - .stream(false) - .build(); - ChatCompletionResponse chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion); - return chatCompletionResponse.getChoices().get(0).getMessage().getContent().toString(); } } diff --git a/ruoyi-modules/ruoyi-wechat/pom.xml b/ruoyi-modules/ruoyi-wechat/pom.xml new file mode 100644 index 0000000..8a71665 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/pom.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.ruoyi</groupId> + <artifactId>ruoyi-modules</artifactId> + <version>${revision}</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <artifactId>ruoyi-wechat</artifactId> + + <properties> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>org.ruoyi</groupId> + <artifactId>ruoyi-chat-api</artifactId> + </dependency> + </dependencies> + +</project> diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/AbstractBuilder.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/AbstractBuilder.java new file mode 100644 index 0000000..6e97f5d --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/AbstractBuilder.java @@ -0,0 +1,12 @@ +package org.ruoyi.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +public abstract class AbstractBuilder { + public abstract WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, WxCpService service); +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/ImageBuilder.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/ImageBuilder.java new file mode 100644 index 0000000..f6786b0 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/ImageBuilder.java @@ -0,0 +1,24 @@ +package org.ruoyi.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutImageMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +public class ImageBuilder extends AbstractBuilder { + + @Override + public WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, + WxCpService service) { + + WxCpXmlOutImageMessage m = WxCpXmlOutMessage.IMAGE().mediaId(content) + .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) + .build(); + + return m; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/TextBuilder.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/TextBuilder.java new file mode 100644 index 0000000..707471e --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/builder/TextBuilder.java @@ -0,0 +1,22 @@ +package org.ruoyi.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutTextMessage; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +public class TextBuilder extends AbstractBuilder { + + @Override + public WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, + WxCpService service) { + WxCpXmlOutTextMessage m = WxCpXmlOutMessage.TEXT().content(content) + .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) + .build(); + return m; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpConfiguration.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpConfiguration.java new file mode 100644 index 0000000..8a5f0fb --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpConfiguration.java @@ -0,0 +1,130 @@ +package org.ruoyi.config; + + +import com.google.common.collect.Maps; +import jakarta.annotation.PostConstruct; +import lombok.val; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; +import me.chanjar.weixin.cp.constant.WxCpConsts; +import me.chanjar.weixin.cp.message.WxCpMessageHandler; +import me.chanjar.weixin.cp.message.WxCpMessageRouter; +import org.ruoyi.handler.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 鍗曞疄渚嬮厤缃� + * + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Configuration +@EnableConfigurationProperties(WxCpProperties.class) +public class WxCpConfiguration { + private final LogHandler logHandler; + private NullHandler nullHandler; + private LocationHandler locationHandler; + private MenuHandler menuHandler; + private MsgHandler msgHandler; + private final UnsubscribeHandler unsubscribeHandler; + private SubscribeHandler subscribeHandler; + private WxCpProperties properties; + + private static Map<Integer, WxCpMessageRouter> routers = Maps.newHashMap(); + private static Map<Integer, WxCpService> cpServices = Maps.newHashMap(); + + @Autowired + public WxCpConfiguration(LogHandler logHandler, NullHandler nullHandler, LocationHandler locationHandler, + MenuHandler menuHandler, MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler, + SubscribeHandler subscribeHandler, WxCpProperties properties) { + this.logHandler = logHandler; + this.nullHandler = nullHandler; + this.locationHandler = locationHandler; + this.menuHandler = menuHandler; + this.msgHandler = msgHandler; + this.unsubscribeHandler = unsubscribeHandler; + this.subscribeHandler = subscribeHandler; + this.properties = properties; + } + + + public static Map<Integer, WxCpMessageRouter> getRouters() { + return routers; + } + + public static WxCpService getCpService(Integer agentId) { + return cpServices.get(agentId); + } + + @PostConstruct + public void initServices() { + cpServices = this.properties.getAppConfigs().stream().map(a -> { + val configStorage = new WxCpDefaultConfigImpl(); + configStorage.setCorpId(this.properties.getCorpId()); + configStorage.setAgentId(a.getAgentId()); + configStorage.setCorpSecret(a.getSecret()); + configStorage.setToken(a.getToken()); + configStorage.setAesKey(a.getAesKey()); + val service = new WxCpServiceImpl(); + service.setWxCpConfigStorage(configStorage); + routers.put(a.getAgentId(), this.newRouter(service)); + return service; + }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getAgentId(), a -> a)); + } + + private WxCpMessageRouter newRouter(WxCpService wxCpService) { + final val newRouter = new WxCpMessageRouter(wxCpService); + + // 璁板綍鎵�鏈変簨浠剁殑鏃ュ織 锛堝紓姝ユ墽琛岋級 + newRouter.rule().handler(this.logHandler).next(); + + // 鑷畾涔夎彍鍗曚簨浠� + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end(); + + // 鐐瑰嚮鑿滃崟閾炬帴浜嬩欢锛堣繖閲屼娇鐢ㄤ簡涓�涓┖鐨勫鐞嗗櫒锛屽彲浠ユ牴鎹嚜宸遍渶瑕佽繘琛屾墿灞曪級 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end(); + + // 鍏虫敞浜嬩欢 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler) + .end(); + + // 鍙栨秷鍏虫敞浜嬩欢 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.UNSUBSCRIBE) + .handler((WxCpMessageHandler) this.unsubscribeHandler).end(); + + // 涓婃姤鍦扮悊浣嶇疆浜嬩欢 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.LOCATION).handler(this.locationHandler) + .end(); + + // 鎺ユ敹鍦扮悊浣嶇疆娑堟伅 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION) + .handler(this.locationHandler).end(); + + // 鎵爜浜嬩欢锛堣繖閲屼娇鐢ㄤ簡涓�涓┖鐨勫鐞嗗櫒锛屽彲浠ユ牴鎹嚜宸遍渶瑕佽繘琛屾墿灞曪級 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.SCAN).handler((WxCpMessageHandler) this.nullHandler).end(); + + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end(); + + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end(); + + // 榛樿 + newRouter.rule().async(false).handler(this.msgHandler).end(); + + return newRouter; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpProperties.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpProperties.java new file mode 100644 index 0000000..51077d6 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/config/WxCpProperties.java @@ -0,0 +1,45 @@ +package org.ruoyi.config; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import java.util.List; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Data +public class WxCpProperties { + /** + * 璁剧疆浼佷笟寰俊鐨刢orpId + */ + private String corpId; + + private List<AppConfig> appConfigs; + + @Getter + @Setter + public static class AppConfig { + /** + * 璁剧疆浼佷笟寰俊搴旂敤鐨凙gentId + */ + private Integer agentId; + + /** + * 璁剧疆浼佷笟寰俊搴旂敤鐨凷ecret + */ + private String secret; + + /** + * 璁剧疆浼佷笟寰俊搴旂敤鐨則oken + */ + private String token; + + /** + * 璁剧疆浼佷笟寰俊搴旂敤鐨凟ncodingAESKey + */ + private String aesKey; + + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/controller/wxcplogin/WxPortalController.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/controller/wxcplogin/WxPortalController.java new file mode 100644 index 0000000..2857bc2 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/controller/wxcplogin/WxPortalController.java @@ -0,0 +1,86 @@ +package org.ruoyi.controller.wxcplogin; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; +import org.apache.commons.lang3.StringUtils; +import org.ruoyi.common.core.utils.JsonUtils; + +import org.ruoyi.config.WxCpConfiguration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@RestController +@RequestMapping("/wx/cp") +@Slf4j +public class WxPortalController { + + @Value("${wechat.cp.appConfigs[0].agentId}") + private Integer agentId; + + + @GetMapping(produces = "text/plain;charset=utf-8") + public String authGet( + @RequestParam(name = "msg_signature", required = false) String signature, + @RequestParam(name = "timestamp", required = false) String timestamp, + @RequestParam(name = "nonce", required = false) String nonce, + @RequestParam(name = "echostr", required = false) String echostr) { + log.info("\n鎺ユ敹鍒版潵鑷井淇℃湇鍔″櫒鐨勮璇佹秷鎭細signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", + signature, timestamp, nonce, echostr); + + if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { + throw new IllegalArgumentException("璇锋眰鍙傛暟闈炴硶锛岃鏍稿疄!"); + } + + final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId); + if (wxCpService == null) { + throw new IllegalArgumentException(String.format("鏈壘鍒板搴攁gentId=[%d]鐨勯厤缃紝璇锋牳瀹烇紒", agentId)); + } + + if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) { + return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr); + } + + return "闈炴硶璇锋眰"; + } + + @PostMapping(produces = "application/xml; charset=UTF-8") + public String post( + @RequestBody String requestBody, + @RequestParam("msg_signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce) { + log.info("\n鎺ユ敹寰俊璇锋眰锛歔signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + signature, timestamp, nonce, requestBody); + + final WxCpService wxCpService = WxCpConfiguration.getCpService(1000002); + WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(), + timestamp, nonce, signature); + log.debug("\n娑堟伅瑙e瘑鍚庡唴瀹逛负锛歕n{} ", JsonUtils.toJson(inMessage)); + WxCpXmlOutMessage outMessage = this.route(1000002, inMessage); + if (outMessage == null) { + return ""; + } + + String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage()); + log.debug("\n缁勮鍥炲淇℃伅锛歿}", out); + return out; + } + + private WxCpXmlOutMessage route(Integer agentId, WxCpXmlMessage message) { + try { + return WxCpConfiguration.getRouters().get(agentId).route(message); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + return null; + } + + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/AbstractHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/AbstractHandler.java new file mode 100644 index 0000000..7ec2b0c --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/AbstractHandler.java @@ -0,0 +1,9 @@ +package org.ruoyi.handler; + +import me.chanjar.weixin.cp.message.WxCpMessageHandler; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +public abstract class AbstractHandler implements WxCpMessageHandler { +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ContactChangeHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ContactChangeHandler.java new file mode 100644 index 0000000..178229d --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ContactChangeHandler.java @@ -0,0 +1,34 @@ +package org.ruoyi.handler; + + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.ruoyi.builder.TextBuilder; +import org.ruoyi.common.core.utils.JsonUtils; + +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 閫氳褰曞彉鏇翠簨浠跺鐞嗗櫒. + * + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Slf4j +@Component +public class ContactChangeHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + String content = "鏀跺埌閫氳褰曞彉鏇翠簨浠讹紝鍐呭锛�" + JsonUtils.toJson(wxMessage); + log.info(content); + + return new TextBuilder().build(content, wxMessage, cpService); + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/EnterAgentHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/EnterAgentHandler.java new file mode 100644 index 0000000..c98fe68 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/EnterAgentHandler.java @@ -0,0 +1,29 @@ +package org.ruoyi.handler; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; + +import java.util.Map; + +/** + * <pre> + * + * Created by Binary Wang on 2018/8/27. + * </pre> + * + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Slf4j +public class EnterAgentHandler extends AbstractHandler { + private static final int TEST_AGENT = 1000002; + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException { + // do something + return null; + } +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LocationHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LocationHandler.java new file mode 100644 index 0000000..56d1fb3 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LocationHandler.java @@ -0,0 +1,44 @@ +package org.ruoyi.handler; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.ruoyi.builder.TextBuilder; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Slf4j +@Component +public class LocationHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.LOCATION)) { + //TODO 鎺ユ敹澶勭悊鐢ㄦ埛鍙戦�佺殑鍦扮悊浣嶇疆娑堟伅 + try { + String content = "鎰熻阿鍙嶉锛屾偍鐨勭殑鍦扮悊浣嶇疆宸叉敹鍒帮紒"; + return new TextBuilder().build(content, wxMessage, null); + } catch (Exception e) { + log.error("浣嶇疆娑堟伅鎺ユ敹澶勭悊澶辫触", e); + return null; + } + } + + //涓婃姤鍦扮悊浣嶇疆浜嬩欢 + log.info("\n涓婃姤鍦扮悊浣嶇疆锛岀含搴� : {}\n缁忓害 : {}\n绮惧害 : {}", + wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision())); + + //TODO 鍙互灏嗙敤鎴峰湴鐞嗕綅缃俊鎭繚瀛樺埌鏈湴鏁版嵁搴擄紝浠ヤ究浠ュ悗浣跨敤 + + return null; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LogHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LogHandler.java new file mode 100644 index 0000000..ea12c40 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/LogHandler.java @@ -0,0 +1,26 @@ +package org.ruoyi.handler; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.ruoyi.common.core.utils.JsonUtils; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Slf4j +@Component +public class LogHandler extends AbstractHandler { + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + log.info("\n鎺ユ敹鍒拌姹傛秷鎭紝鍐呭锛歿}", JsonUtils.toJson(wxMessage)); + return null; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MenuHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MenuHandler.java new file mode 100644 index 0000000..803db7f --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MenuHandler.java @@ -0,0 +1,34 @@ +package org.ruoyi.handler; + +import me.chanjar.weixin.common.api.WxConsts.MenuButtonType; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Component +public class MenuHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + + String msg = String.format("type:%s, event:%s, key:%s", + wxMessage.getMsgType(), wxMessage.getEvent(), + wxMessage.getEventKey()); + if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) { + return null; + } + + return WxCpXmlOutMessage.TEXT().content(msg) + .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) + .build(); + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MsgHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MsgHandler.java new file mode 100644 index 0000000..6527371 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/MsgHandler.java @@ -0,0 +1,43 @@ +package org.ruoyi.handler; + +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; + +import org.ruoyi.builder.TextBuilder; +import org.ruoyi.service.IChatVxService; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Component +@RequiredArgsConstructor +public class MsgHandler extends AbstractHandler { + + private final IChatVxService chatVxService; + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + final String msgType = wxMessage.getMsgType(); + if (msgType == null) { + // 濡傛灉msgType娌℃湁锛屽氨鑷繁鏍规嵁鍏蜂綋鎶ユ枃鍐呭鍋氬鐞� + } + + if (!msgType.equals(WxConsts.XmlMsgType.EVENT)) { + //TODO 鍙互閫夋嫨灏嗘秷鎭繚瀛樺埌鏈湴 + } + //TODO 缁勮鍥炲娑堟伅 + String content = chatVxService.chat(wxMessage.getContent()); + + return new TextBuilder().build(content, wxMessage, cpService); + + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/NullHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/NullHandler.java new file mode 100644 index 0000000..2677d73 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/NullHandler.java @@ -0,0 +1,23 @@ +package org.ruoyi.handler; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Component +public class NullHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ScanHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ScanHandler.java new file mode 100644 index 0000000..4d9a502 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/ScanHandler.java @@ -0,0 +1,8 @@ +package org.ruoyi.handler; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +public abstract class ScanHandler extends AbstractHandler { + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/SubscribeHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/SubscribeHandler.java new file mode 100644 index 0000000..c5e42fb --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/SubscribeHandler.java @@ -0,0 +1,63 @@ +package org.ruoyi.handler; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.ruoyi.builder.TextBuilder; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Slf4j +@Component +public class SubscribeHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) throws WxErrorException { + + log.info("鏂板叧娉ㄧ敤鎴� OPENID: " + wxMessage.getFromUserName()); + + // 鑾峰彇寰俊鐢ㄦ埛鍩烘湰淇℃伅 + WxCpUser userWxInfo = cpService.getUserService().getById(wxMessage.getFromUserName()); + + if (userWxInfo != null) { + // TODO 鍙互娣诲姞鍏虫敞鐢ㄦ埛鍒版湰鍦� + } + + WxCpXmlOutMessage responseResult = null; + try { + responseResult = handleSpecial(wxMessage); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + if (responseResult != null) { + return responseResult; + } + + try { + return new TextBuilder().build("鎰熻阿鍏虫敞", wxMessage, cpService); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + return null; + } + + /** + * 澶勭悊鐗规畩璇锋眰锛屾瘮濡傚鏋滄槸鎵爜杩涙潵鐨勶紝鍙互鍋氱浉搴斿鐞� + */ + private WxCpXmlOutMessage handleSpecial(WxCpXmlMessage wxMessage) { + //TODO + return null; + } + +} diff --git a/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/UnsubscribeHandler.java b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/UnsubscribeHandler.java new file mode 100644 index 0000000..7793346 --- /dev/null +++ b/ruoyi-modules/ruoyi-wechat/src/main/java/org/ruoyi/handler/UnsubscribeHandler.java @@ -0,0 +1,28 @@ +package org.ruoyi.handler; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author <a href="https://github.com/binarywang">Binary Wang</a> + */ +@Slf4j +@Component +public class UnsubscribeHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService, + WxSessionManager sessionManager) { + String openId = wxMessage.getFromUserName(); + log.info("鍙栨秷鍏虫敞鐢ㄦ埛 OPENID: " + openId); + // TODO 鍙互鏇存柊鏈湴鏁版嵁搴撲负鍙栨秷鍏虫敞鐘舵�� + return null; + } + +} -- Gitblit v1.9.3