feat: 新增wechat模块

This commit is contained in:
ageerle
2025-04-30 11:29:23 +08:00
parent b1ff44df4b
commit cd490aa0e5
23 changed files with 745 additions and 25 deletions

View File

@@ -0,0 +1,9 @@
package org.ruoyi.handler;
import me.chanjar.weixin.cp.message.WxCpMessageHandler;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public abstract class AbstractHandler implements WxCpMessageHandler {
}

View File

@@ -0,0 +1,34 @@
package org.ruoyi.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.ruoyi.builder.TextBuilder;
import org.ruoyi.common.core.utils.JsonUtils;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 通讯录变更事件处理器.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
@Component
public class ContactChangeHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
String content = "收到通讯录变更事件,内容:" + JsonUtils.toJson(wxMessage);
log.info(content);
return new TextBuilder().build(content, wxMessage, cpService);
}
}

View File

@@ -0,0 +1,29 @@
package org.ruoyi.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import java.util.Map;
/**
* <pre>
*
* Created by Binary Wang on 2018/8/27.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
public class EnterAgentHandler extends AbstractHandler {
private static final int TEST_AGENT = 1000002;
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException {
// do something
return null;
}
}

View File

@@ -0,0 +1,44 @@
package org.ruoyi.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.ruoyi.builder.TextBuilder;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
@Component
public class LocationHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.LOCATION)) {
//TODO 接收处理用户发送的地理位置消息
try {
String content = "感谢反馈,您的的地理位置已收到!";
return new TextBuilder().build(content, wxMessage, null);
} catch (Exception e) {
log.error("位置消息接收处理失败", e);
return null;
}
}
//上报地理位置事件
log.info("\n上报地理位置纬度 : {}\n经度 : {}\n精度 : {}",
wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));
//TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
return null;
}
}

View File

@@ -0,0 +1,26 @@
package org.ruoyi.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.ruoyi.common.core.utils.JsonUtils;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
@Component
public class LogHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
log.info("\n接收到请求消息内容{}", JsonUtils.toJson(wxMessage));
return null;
}
}

View File

@@ -0,0 +1,34 @@
package org.ruoyi.handler;
import me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Component
public class MenuHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
String msg = String.format("type:%s, event:%s, key:%s",
wxMessage.getMsgType(), wxMessage.getEvent(),
wxMessage.getEventKey());
if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) {
return null;
}
return WxCpXmlOutMessage.TEXT().content(msg)
.fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())
.build();
}
}

View File

@@ -0,0 +1,43 @@
package org.ruoyi.handler;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.ruoyi.builder.TextBuilder;
import org.ruoyi.service.IChatVxService;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Component
@RequiredArgsConstructor
public class MsgHandler extends AbstractHandler {
private final IChatVxService chatVxService;
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
final String msgType = wxMessage.getMsgType();
if (msgType == null) {
// 如果msgType没有就自己根据具体报文内容做处理
}
if (!msgType.equals(WxConsts.XmlMsgType.EVENT)) {
//TODO 可以选择将消息保存到本地
}
//TODO 组装回复消息
String content = chatVxService.chat(wxMessage.getContent());
return new TextBuilder().build(content, wxMessage, cpService);
}
}

View File

@@ -0,0 +1,23 @@
package org.ruoyi.handler;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Component
public class NullHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
return null;
}
}

View File

@@ -0,0 +1,8 @@
package org.ruoyi.handler;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public abstract class ScanHandler extends AbstractHandler {
}

View File

@@ -0,0 +1,63 @@
package org.ruoyi.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.ruoyi.builder.TextBuilder;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
@Component
public class SubscribeHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) throws WxErrorException {
log.info("新关注用户 OPENID: " + wxMessage.getFromUserName());
// 获取微信用户基本信息
WxCpUser userWxInfo = cpService.getUserService().getById(wxMessage.getFromUserName());
if (userWxInfo != null) {
// TODO 可以添加关注用户到本地
}
WxCpXmlOutMessage responseResult = null;
try {
responseResult = handleSpecial(wxMessage);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
if (responseResult != null) {
return responseResult;
}
try {
return new TextBuilder().build("感谢关注", wxMessage, cpService);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
/**
* 处理特殊请求,比如如果是扫码进来的,可以做相应处理
*/
private WxCpXmlOutMessage handleSpecial(WxCpXmlMessage wxMessage) {
//TODO
return null;
}
}

View File

@@ -0,0 +1,28 @@
package org.ruoyi.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
@Component
public class UnsubscribeHandler extends AbstractHandler {
@Override
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,
WxSessionManager sessionManager) {
String openId = wxMessage.getFromUserName();
log.info("取消关注用户 OPENID: " + openId);
// TODO 可以更新本地数据库为取消关注状态
return null;
}
}