微信实现
This commit is contained in:
parent
07547eb3cf
commit
78eddfc9d1
1
pom.xml
1
pom.xml
|
|
@ -53,6 +53,7 @@
|
|||
<module>ruoyi-vip</module>
|
||||
<module>ruoyi-train</module>
|
||||
<module>ruoyi-cms</module>
|
||||
<module>ruoyi-weixin</module>
|
||||
<!--<module>tuoyi-test</module>-->
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
|
|
|||
|
|
@ -148,13 +148,7 @@
|
|||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
</dependency>
|
||||
<!-- 微信工具类 -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<!--前后端分离验证-->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
<?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">
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-weixin</artifactId>
|
||||
|
||||
<properties>
|
||||
<weixin-java-cp.version>3.3.0</weixin-java-cp.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-cp</artifactId>
|
||||
<version>${weixin-java-cp.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.20</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<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 WxCpMessageRouter getRouter(Integer agentId) {
|
||||
return routers.get(agentId);
|
||||
}
|
||||
|
||||
public static Map<Integer, WxCpService> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<AppConfig> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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<WxCpDepart> departAllList() {
|
||||
this.logger.info("\n获取组织机构");
|
||||
try {
|
||||
final WxCpService wxCpService = WxCpConfiguration.getCpService(999999);
|
||||
WxCpDepartmentService departmentService = wxCpService.getDepartmentService();
|
||||
List<WxCpDepart> 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<WxCpDepart> update() {
|
||||
this.logger.info("\n获取组织机构");
|
||||
try {
|
||||
final WxCpService wxCpService = WxCpConfiguration.getCpService(999999);
|
||||
WxCpDepartmentService departmentService = wxCpService.getDepartmentService();
|
||||
List<WxCpDepart> list = departmentService.list(null);
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
this.logger.info("\n获取组织机构出错" + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@GetMapping("/delete")
|
||||
public List<WxCpDepart> delete() {
|
||||
this.logger.info("\n获取组织机构");
|
||||
try {
|
||||
final WxCpService wxCpService = WxCpConfiguration.getCpService(999999);
|
||||
WxCpDepartmentService departmentService = wxCpService.getDepartmentService();
|
||||
List<WxCpDepart> list = departmentService.list(null);
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
this.logger.info("\n获取组织机构出错" + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 出错页面控制器
|
||||
* Created by Binary Wang on 2018/8/25.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/error")
|
||||
public class ErrorController {
|
||||
|
||||
@GetMapping(value = "/404")
|
||||
public String error404() {
|
||||
return "error";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/500")
|
||||
public String error500() {
|
||||
return "error";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 配置错误状态与对应访问路径
|
||||
* Created by Binary Wang on 2018/8/25.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
*/
|
||||
@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")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
@ -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<String, Object> context, WxCpService cpService,
|
||||
WxSessionManager sessionManager) {
|
||||
String content = "收到通讯录变更事件,内容:" + JsonUtils.toJson(wxMessage);
|
||||
this.logger.info(content);
|
||||
|
||||
return new TextBuilder().build(content, wxMessage, cpService);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<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) {
|
||||
this.logger.error("位置消息接收处理失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//上报地理位置事件
|
||||
this.logger.info("\n上报地理位置,纬度 : {}\n经度 : {}\n精度 : {}",
|
||||
wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));
|
||||
|
||||
//TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String, Object> context, WxCpService cpService,
|
||||
WxSessionManager sessionManager) {
|
||||
this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage));
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String, Object> 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String, Object> context, WxCpService cpService,
|
||||
WxSessionManager sessionManager) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.ruoyi.wx.cp.handler;
|
||||
|
||||
/**
|
||||
* @author Binary Wang(https://github.com/binarywang)
|
||||
*/
|
||||
public abstract class ScanHandler extends AbstractHandler {
|
||||
|
||||
}
|
||||
|
|
@ -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<String, Object> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String, Object> context, WxCpService cpService,
|
||||
WxSessionManager sessionManager) {
|
||||
String openId = wxMessage.getFromUserName();
|
||||
this.logger.info("取消关注用户 OPENID: " + openId);
|
||||
// TODO 可以更新本地数据库为取消关注状态
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue