微信实现

This commit is contained in:
zhujj 2019-01-22 14:43:52 +08:00
parent 07547eb3cf
commit 78eddfc9d1
26 changed files with 928 additions and 7 deletions

View File

@ -53,6 +53,7 @@
<module>ruoyi-vip</module> <module>ruoyi-vip</module>
<module>ruoyi-train</module> <module>ruoyi-train</module>
<module>ruoyi-cms</module> <module>ruoyi-cms</module>
<module>ruoyi-weixin</module>
<!--<module>tuoyi-test</module>--> <!--<module>tuoyi-test</module>-->
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>

View File

@ -148,13 +148,7 @@
<groupId>net.java.dev.jna</groupId> <groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId> <artifactId>jna-platform</artifactId>
</dependency> </dependency>
<!-- 微信工具类 -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.3.0</version>
<type>pom</type>
</dependency>
<!--前后端分离验证--> <!--前后端分离验证-->
<dependency> <dependency>
<groupId>com.auth0</groupId> <groupId>com.auth0</groupId>

37
ruoyi-weixin/pom.xml Normal file
View File

@ -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>

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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")
);
}
}

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,8 @@
package com.ruoyi.wx.cp.handler;
/**
* @author Binary Wang(https://github.com/binarywang)
*/
public abstract class ScanHandler extends AbstractHandler {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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