From 78eddfc9d118f48fc4c02c8448ad782d1e1d53c4 Mon Sep 17 00:00:00 2001 From: zhujj Date: Tue, 22 Jan 2019 14:43:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + ruoyi-framework/pom.xml | 8 +- ruoyi-weixin/pom.xml | 37 +++++ .../com/ruoyi/wx/cp/WxCpDemoApplication.java | 15 ++ .../ruoyi/wx/cp/builder/AbstractBuilder.java | 16 ++ .../com/ruoyi/wx/cp/builder/ImageBuilder.java | 25 +++ .../com/ruoyi/wx/cp/builder/TextBuilder.java | 22 +++ .../ruoyi/wx/cp/config/WxCpConfiguration.java | 145 ++++++++++++++++++ .../ruoyi/wx/cp/config/WxCpProperties.java | 59 +++++++ .../wx/cp/controller/WxPortalController.java | 88 +++++++++++ .../cp/controller/WxUserGroupController.java | 90 +++++++++++ .../ruoyi/wx/cp/error/ErrorController.java | 29 ++++ .../wx/cp/error/ErrorPageConfiguration.java | 27 ++++ .../ruoyi/wx/cp/handler/AbstractHandler.java | 13 ++ .../wx/cp/handler/ContactChangeHandler.java | 31 ++++ .../wx/cp/handler/EnterAgentHandler.java | 29 ++++ .../ruoyi/wx/cp/handler/LocationHandler.java | 43 ++++++ .../com/ruoyi/wx/cp/handler/LogHandler.java | 25 +++ .../com/ruoyi/wx/cp/handler/MenuHandler.java | 35 +++++ .../com/ruoyi/wx/cp/handler/MsgHandler.java | 36 +++++ .../com/ruoyi/wx/cp/handler/NullHandler.java | 24 +++ .../com/ruoyi/wx/cp/handler/ScanHandler.java | 8 + .../ruoyi/wx/cp/handler/SubscribeHandler.java | 62 ++++++++ .../wx/cp/handler/UnsubscribeHandler.java | 27 ++++ .../java/com/ruoyi/wx/cp/utils/JsonUtils.java | 28 ++++ .../src/main/resources/application-weixin.yml | 12 ++ 26 files changed, 928 insertions(+), 7 deletions(-) create mode 100644 ruoyi-weixin/pom.xml create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/WxCpDemoApplication.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/AbstractBuilder.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/ImageBuilder.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/TextBuilder.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpConfiguration.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpProperties.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxPortalController.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxUserGroupController.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorController.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorPageConfiguration.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/AbstractHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ContactChangeHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/EnterAgentHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LocationHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LogHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MenuHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MsgHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/NullHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ScanHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/SubscribeHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/UnsubscribeHandler.java create mode 100644 ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/utils/JsonUtils.java create mode 100644 ruoyi-weixin/src/main/resources/application-weixin.yml diff --git a/pom.xml b/pom.xml index 04b8304c0..06e7d505c 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,7 @@ ruoyi-vip ruoyi-train ruoyi-cms + ruoyi-weixin pom diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index c56bd47a9..cd7a93264 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -148,13 +148,7 @@ net.java.dev.jna jna-platform - - - com.github.binarywang - wx-java - 3.3.0 - pom - + com.auth0 diff --git a/ruoyi-weixin/pom.xml b/ruoyi-weixin/pom.xml new file mode 100644 index 000000000..71adaae93 --- /dev/null +++ b/ruoyi-weixin/pom.xml @@ -0,0 +1,37 @@ + + + + ruoyi + com.ruoyi + 3.1 + + 4.0.0 + + ruoyi-weixin + + + 3.3.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + com.github.binarywang + weixin-java-cp + ${weixin-java-cp.version} + + + + org.projectlombok + lombok + 1.16.20 + provided + + + + \ No newline at end of file diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/WxCpDemoApplication.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/WxCpDemoApplication.java new file mode 100644 index 000000000..2d895e3b6 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/WxCpDemoApplication.java @@ -0,0 +1,15 @@ +package com.ruoyi.wx.cp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@SpringBootApplication +public class WxCpDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(WxCpDemoApplication.class, args); + } +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/AbstractBuilder.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/AbstractBuilder.java new file mode 100644 index 000000000..00f2f002d --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/AbstractBuilder.java @@ -0,0 +1,16 @@ +package com.ruoyi.wx.cp.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class AbstractBuilder { + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + public abstract WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, WxCpService service); +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/ImageBuilder.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/ImageBuilder.java new file mode 100644 index 000000000..54e4b8339 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/ImageBuilder.java @@ -0,0 +1,25 @@ +package com.ruoyi.wx.cp.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutImageMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +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-weixin/src/main/java/com/ruoyi/wx/cp/builder/TextBuilder.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/TextBuilder.java new file mode 100644 index 000000000..51a13b0fd --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/builder/TextBuilder.java @@ -0,0 +1,22 @@ +package com.ruoyi.wx.cp.builder; + +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +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-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpConfiguration.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpConfiguration.java new file mode 100644 index 000000000..b21840bb7 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpConfiguration.java @@ -0,0 +1,145 @@ +package com.ruoyi.wx.cp.config; + +import java.util.Map; +import java.util.stream.Collectors; + +import com.ruoyi.wx.cp.handler.UnsubscribeHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.ruoyi.wx.cp.handler.ContactChangeHandler; +import com.ruoyi.wx.cp.handler.EnterAgentHandler; +import com.ruoyi.wx.cp.handler.LocationHandler; +import com.ruoyi.wx.cp.handler.LogHandler; +import com.ruoyi.wx.cp.handler.MenuHandler; +import com.ruoyi.wx.cp.handler.MsgHandler; +import com.ruoyi.wx.cp.handler.NullHandler; +import com.ruoyi.wx.cp.handler.SubscribeHandler; +import com.google.common.collect.Maps; +import lombok.val; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.cp.WxCpConsts; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; +import me.chanjar.weixin.cp.message.WxCpMessageRouter; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Configuration +@EnableConfigurationProperties(WxCpProperties.class) +public class WxCpConfiguration { + private LogHandler logHandler; + private NullHandler nullHandler; + private LocationHandler locationHandler; + private MenuHandler menuHandler; + private MsgHandler msgHandler; + private UnsubscribeHandler unsubscribeHandler; + private SubscribeHandler subscribeHandler; + + private WxCpProperties properties; + + private static Map routers = Maps.newHashMap(); + private static Map 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 getRouters() { + return routers; + } + + public static WxCpMessageRouter getRouter(Integer agentId) { + return routers.get(agentId); + } + + public static Map getCpServices() { + return cpServices; + } + + public static WxCpService getCpService(Integer agentId) { + return cpServices.get(agentId); + } + + @Bean + public Object wxCpServices() { + cpServices = this.properties.getAppConfigs().stream().map(a -> { + val configStorage = new WxCpInMemoryConfigStorage(); + 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)); + + return Boolean.TRUE; + } + + 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(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(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-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpProperties.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpProperties.java new file mode 100644 index 000000000..0ebc5993d --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/config/WxCpProperties.java @@ -0,0 +1,59 @@ +package com.ruoyi.wx.cp.config; + +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import com.ruoyi.wx.cp.utils.JsonUtils; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "wechat.cp") +public class WxCpProperties { + /** + * 设置微信企业号的corpId + */ + private String corpId; + + /** + * 设置微信企业号的corpSecret + */ + private String corpSecret; + + private List appConfigs; + + @Getter + @Setter + public static class AppConfig { + /** + * 设置微信企业应用的AgentId + */ + private Integer agentId; + + /** + * 设置微信企业应用的Secret + */ + private String secret; + + /** + * 设置微信企业号的token + */ + private String token; + + /** + * 设置微信企业号的EncodingAESKey + */ + private String aesKey; + + } + + @Override + public String toString() { + return JsonUtils.toJson(this); + } +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxPortalController.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxPortalController.java new file mode 100644 index 000000000..0af60d5e3 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxPortalController.java @@ -0,0 +1,88 @@ +package com.ruoyi.wx.cp.controller; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.ruoyi.wx.cp.config.WxCpConfiguration; +import com.ruoyi.wx.cp.utils.JsonUtils; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@RestController +@RequestMapping("/wx/cp/portal/{agentId}") +public class WxPortalController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @GetMapping(produces = "text/plain;charset=utf-8") + public String authGet(@PathVariable Integer agentId, + @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) { + this.logger.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("未找到对应agentId=[%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(@PathVariable Integer agentId, + @RequestBody String requestBody, + @RequestParam("msg_signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce) { + this.logger.info("\n接收微信请求:[signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + signature, timestamp, nonce, requestBody); + + final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId); + WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(), + timestamp, nonce, signature); + this.logger.debug("\n消息解密后内容为:\n{} ", JsonUtils.toJson(inMessage)); + WxCpXmlOutMessage outMessage = this.route(agentId, inMessage); + if (outMessage == null) { + return ""; + } + + String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage()); + this.logger.debug("\n组装回复信息:{}", out); + return out; + } + + private WxCpXmlOutMessage route(Integer agentId, WxCpXmlMessage message) { + try { + return WxCpConfiguration.getRouters().get(agentId).route(message); + } catch (Exception e) { + this.logger.error(e.getMessage(), e); + } + + return null; + } + + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxUserGroupController.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxUserGroupController.java new file mode 100644 index 000000000..3b54e2261 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/controller/WxUserGroupController.java @@ -0,0 +1,90 @@ +package com.ruoyi.wx.cp.controller; + +import com.ruoyi.wx.cp.config.WxCpConfiguration; +import com.ruoyi.wx.cp.config.WxCpProperties; +import com.ruoyi.wx.cp.utils.JsonUtils; +import me.chanjar.weixin.cp.api.WxCpDepartmentService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.WxCpDepart; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; +import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@RestController +@RequestMapping("/wx/cp/user/group") +public class WxUserGroupController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + + private WxCpProperties properties; + + @GetMapping("/departAllList") + public List departAllList() { + this.logger.info("\n获取组织机构"); + try { + final WxCpService wxCpService = WxCpConfiguration.getCpService(999999); + WxCpDepartmentService departmentService = wxCpService.getDepartmentService(); + List list = departmentService.list(null); + return list; + } catch (Exception e) { + this.logger.info("\n获取组织机构出错" + e.getMessage()); + } + return null; + } + + @GetMapping("/insert") + public Object insert(WxCpDepart wxCpDepart) { + this.logger.info("\n获取组织机构"); + try { + WxCpDepartmentService departmentService = WxCpConfiguration.getCpService(999999).getDepartmentService(); + Integer integer = departmentService.create(wxCpDepart); + return integer; + } catch (Exception e) { + this.logger.info("\n获取组织机构出错" + e.getMessage()); + } + return null; + } + + @GetMapping("/update") + public List update() { + this.logger.info("\n获取组织机构"); + try { + final WxCpService wxCpService = WxCpConfiguration.getCpService(999999); + WxCpDepartmentService departmentService = wxCpService.getDepartmentService(); + List list = departmentService.list(null); + return list; + } catch (Exception e) { + this.logger.info("\n获取组织机构出错" + e.getMessage()); + } + return null; + } + + @GetMapping("/delete") + public List delete() { + this.logger.info("\n获取组织机构"); + try { + final WxCpService wxCpService = WxCpConfiguration.getCpService(999999); + WxCpDepartmentService departmentService = wxCpService.getDepartmentService(); + List list = departmentService.list(null); + return list; + } catch (Exception e) { + this.logger.info("\n获取组织机构出错" + e.getMessage()); + } + return null; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorController.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorController.java new file mode 100644 index 000000000..e8ca444ca --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorController.java @@ -0,0 +1,29 @@ +package com.ruoyi.wx.cp.error; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + *
+ * 出错页面控制器
+ * Created by Binary Wang on 2018/8/25.
+ * 
+ * + * @author Binary Wang + */ +@Controller +@RequestMapping("/error") +public class ErrorController { + + @GetMapping(value = "/404") + public String error404() { + return "error"; + } + + @GetMapping(value = "/500") + public String error500() { + return "error"; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorPageConfiguration.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorPageConfiguration.java new file mode 100644 index 000000000..cbf011760 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/error/ErrorPageConfiguration.java @@ -0,0 +1,27 @@ +package com.ruoyi.wx.cp.error; + +import org.springframework.boot.web.server.ErrorPage; +import org.springframework.boot.web.server.ErrorPageRegistrar; +import org.springframework.boot.web.server.ErrorPageRegistry; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +/** + *
+ * 配置错误状态与对应访问路径
+ * Created by Binary Wang on 2018/8/25.
+ * 
+ * + * @author Binary Wang + */ +@Component +public class ErrorPageConfiguration implements ErrorPageRegistrar { + @Override + public void registerErrorPages(ErrorPageRegistry errorPageRegistry) { + errorPageRegistry.addErrorPages( + new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"), + new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500") + ); + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/AbstractHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/AbstractHandler.java new file mode 100644 index 000000000..b0cdc35e7 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/AbstractHandler.java @@ -0,0 +1,13 @@ +package com.ruoyi.wx.cp.handler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import me.chanjar.weixin.cp.message.WxCpMessageHandler; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class AbstractHandler implements WxCpMessageHandler { + protected Logger logger = LoggerFactory.getLogger(getClass()); +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ContactChangeHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ContactChangeHandler.java new file mode 100644 index 000000000..267040db2 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ContactChangeHandler.java @@ -0,0 +1,31 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import com.ruoyi.wx.cp.builder.TextBuilder; +import org.springframework.stereotype.Component; + +import com.ruoyi.wx.cp.utils.JsonUtils; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * 通讯录变更事件处理器. + * + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class ContactChangeHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + String content = "收到通讯录变更事件,内容:" + JsonUtils.toJson(wxMessage); + this.logger.info(content); + + return new TextBuilder().build(content, wxMessage, cpService); + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/EnterAgentHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/EnterAgentHandler.java new file mode 100644 index 000000000..ae0008da8 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/EnterAgentHandler.java @@ -0,0 +1,29 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +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.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + *
+ *
+ * Created by Binary Wang on 2018/8/27.
+ * 
+ * + * @author Binary Wang + */ +@Slf4j +public class EnterAgentHandler extends AbstractHandler { + private static final int TEST_AGENT = 1000002; + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException { + // do something + return null; + } +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LocationHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LocationHandler.java new file mode 100644 index 000000000..4c7c20ea8 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LocationHandler.java @@ -0,0 +1,43 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import com.ruoyi.wx.cp.builder.TextBuilder; +import org.springframework.stereotype.Component; + +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.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class LocationHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map 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) { + this.logger.error("位置消息接收处理失败", e); + return null; + } + } + + //上报地理位置事件 + this.logger.info("\n上报地理位置,纬度 : {}\n经度 : {}\n精度 : {}", + wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision())); + + //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 + + return null; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LogHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LogHandler.java new file mode 100644 index 000000000..e4ec42439 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/LogHandler.java @@ -0,0 +1,25 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import org.springframework.stereotype.Component; + +import com.ruoyi.wx.cp.utils.JsonUtils; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class LogHandler extends AbstractHandler { + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage)); + return null; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MenuHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MenuHandler.java new file mode 100644 index 000000000..a2b030749 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MenuHandler.java @@ -0,0 +1,35 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import org.springframework.stereotype.Component; + +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.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class MenuHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map 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-weixin/src/main/java/com/ruoyi/wx/cp/handler/MsgHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MsgHandler.java new file mode 100644 index 000000000..2db6ab23d --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/MsgHandler.java @@ -0,0 +1,36 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import com.ruoyi.wx.cp.builder.TextBuilder; +import org.springframework.stereotype.Component; + +import com.ruoyi.wx.cp.utils.JsonUtils; +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.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class MsgHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + + if (!wxMessage.getMsgType().equals(WxConsts.XmlMsgType.EVENT)) { + //TODO 可以选择将消息保存到本地 + } + + //TODO 组装回复消息 + String content = "收到信息内容:" + JsonUtils.toJson(wxMessage); + + return new TextBuilder().build(content, wxMessage, cpService); + + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/NullHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/NullHandler.java new file mode 100644 index 000000000..80411a77b --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/NullHandler.java @@ -0,0 +1,24 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import org.springframework.stereotype.Component; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class NullHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ScanHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ScanHandler.java new file mode 100644 index 000000000..48631c1e6 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/ScanHandler.java @@ -0,0 +1,8 @@ +package com.ruoyi.wx.cp.handler; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public abstract class ScanHandler extends AbstractHandler { + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/SubscribeHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/SubscribeHandler.java new file mode 100644 index 000000000..52bce1228 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/SubscribeHandler.java @@ -0,0 +1,62 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import com.ruoyi.wx.cp.builder.TextBuilder; +import org.springframework.stereotype.Component; + +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.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class SubscribeHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) throws WxErrorException { + + this.logger.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) { + this.logger.error(e.getMessage(), e); + } + + if (responseResult != null) { + return responseResult; + } + + try { + return new TextBuilder().build("感谢关注", wxMessage, cpService); + } catch (Exception e) { + this.logger.error(e.getMessage(), e); + } + + return null; + } + + /** + * 处理特殊请求,比如如果是扫码进来的,可以做相应处理 + */ + private WxCpXmlOutMessage handleSpecial(WxCpXmlMessage wxMessage) { + //TODO + return null; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/UnsubscribeHandler.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/UnsubscribeHandler.java new file mode 100644 index 000000000..1172ef4ae --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/handler/UnsubscribeHandler.java @@ -0,0 +1,27 @@ +package com.ruoyi.wx.cp.handler; + +import java.util.Map; + +import org.springframework.stereotype.Component; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +@Component +public class UnsubscribeHandler extends AbstractHandler { + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, + WxSessionManager sessionManager) { + String openId = wxMessage.getFromUserName(); + this.logger.info("取消关注用户 OPENID: " + openId); + // TODO 可以更新本地数据库为取消关注状态 + return null; + } + +} diff --git a/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/utils/JsonUtils.java b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/utils/JsonUtils.java new file mode 100644 index 000000000..b9a5ed822 --- /dev/null +++ b/ruoyi-weixin/src/main/java/com/ruoyi/wx/cp/utils/JsonUtils.java @@ -0,0 +1,28 @@ +package com.ruoyi.wx.cp.utils; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * @author Binary Wang(https://github.com/binarywang) + */ +public class JsonUtils { + private static final ObjectMapper JSON = new ObjectMapper(); + + static { + JSON.setSerializationInclusion(Include.NON_NULL); + JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE); + } + + public static String toJson(Object obj) { + try { + return JSON.writeValueAsString(obj); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + return null; + } +} diff --git a/ruoyi-weixin/src/main/resources/application-weixin.yml b/ruoyi-weixin/src/main/resources/application-weixin.yml new file mode 100644 index 000000000..4a57ad0c1 --- /dev/null +++ b/ruoyi-weixin/src/main/resources/application-weixin.yml @@ -0,0 +1,12 @@ +wechat: + cp: + corpId: wwffb70143e94111eb + appConfigs: + - agentId: 999999 + secret: yeL6mZp5IFIkfQ3wWMGFI8G-L4a6BEF194fnRzhvCy0 + token: 111 + aesKey: 111 + - agentId: 1000002 + secret: 1111 + token: 111 + aesKey: 111 \ No newline at end of file