mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
mp:location 的自动回复;关注后的自动回复
This commit is contained in:
parent
44f0bcd182
commit
69e653cd94
@ -34,4 +34,11 @@ public interface MpAutoReplyMapper extends BaseMapperX<MpAutoReplyDO> {
|
|||||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.MESSAGE.getType())
|
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.MESSAGE.getType())
|
||||||
.eq(MpAutoReplyDO::getRequestMessageType, requestMessageType));
|
.eq(MpAutoReplyDO::getRequestMessageType, requestMessageType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<MpAutoReplyDO> selectListByAppIdAndSubscribe(String appId) {
|
||||||
|
return selectList(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||||
|
.eq(MpAutoReplyDO::getAppId, appId)
|
||||||
|
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.SUBSCRIBE.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class MpConfiguration {
|
|||||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||||
public MpServiceFactory mpServiceFactory(RedisTemplateWxRedisOps redisTemplateWxRedisOps,
|
public MpServiceFactory mpServiceFactory(RedisTemplateWxRedisOps redisTemplateWxRedisOps,
|
||||||
WxMpProperties wxMpProperties,
|
WxMpProperties wxMpProperties,
|
||||||
MessageReceiveHandler logHandler,
|
MessageReceiveHandler messageReceiveHandler,
|
||||||
KfSessionHandler kfSessionHandler,
|
KfSessionHandler kfSessionHandler,
|
||||||
StoreCheckNotifyHandler storeCheckNotifyHandler,
|
StoreCheckNotifyHandler storeCheckNotifyHandler,
|
||||||
MenuHandler menuHandler,
|
MenuHandler menuHandler,
|
||||||
@ -45,10 +45,10 @@ public class MpConfiguration {
|
|||||||
UnsubscribeHandler unsubscribeHandler,
|
UnsubscribeHandler unsubscribeHandler,
|
||||||
LocationHandler locationHandler,
|
LocationHandler locationHandler,
|
||||||
ScanHandler scanHandler,
|
ScanHandler scanHandler,
|
||||||
MessageAutoReplyHandler msgHandler) {
|
MessageAutoReplyHandler messageAutoReplyHandler) {
|
||||||
return new DefaultMpServiceFactory(redisTemplateWxRedisOps, wxMpProperties,
|
return new DefaultMpServiceFactory(redisTemplateWxRedisOps, wxMpProperties,
|
||||||
logHandler, kfSessionHandler, storeCheckNotifyHandler, menuHandler,
|
messageReceiveHandler, kfSessionHandler, storeCheckNotifyHandler, menuHandler,
|
||||||
nullHandler, subscribeHandler, unsubscribeHandler, locationHandler, scanHandler, msgHandler);
|
nullHandler, subscribeHandler, unsubscribeHandler, locationHandler, scanHandler, messageAutoReplyHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ public class DefaultMpServiceFactory implements MpServiceFactory {
|
|||||||
|
|
||||||
// ========== 各种 Handler ==========
|
// ========== 各种 Handler ==========
|
||||||
|
|
||||||
private final MessageReceiveHandler logHandler;
|
private final MessageReceiveHandler messageReceiveHandler;
|
||||||
private final KfSessionHandler kfSessionHandler;
|
private final KfSessionHandler kfSessionHandler;
|
||||||
private final StoreCheckNotifyHandler storeCheckNotifyHandler;
|
private final StoreCheckNotifyHandler storeCheckNotifyHandler;
|
||||||
private final MenuHandler menuHandler;
|
private final MenuHandler menuHandler;
|
||||||
@ -58,7 +58,7 @@ public class DefaultMpServiceFactory implements MpServiceFactory {
|
|||||||
private final UnsubscribeHandler unsubscribeHandler;
|
private final UnsubscribeHandler unsubscribeHandler;
|
||||||
private final LocationHandler locationHandler;
|
private final LocationHandler locationHandler;
|
||||||
private final ScanHandler scanHandler;
|
private final ScanHandler scanHandler;
|
||||||
private final MessageAutoReplyHandler msgHandler;
|
private final MessageAutoReplyHandler messageAutoReplyHandler;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(List<MpAccountDO> list) {
|
public void init(List<MpAccountDO> list) {
|
||||||
@ -108,7 +108,7 @@ public class DefaultMpServiceFactory implements MpServiceFactory {
|
|||||||
private WxMpMessageRouter buildMpMessageRouter(WxMpService mpService) {
|
private WxMpMessageRouter buildMpMessageRouter(WxMpService mpService) {
|
||||||
WxMpMessageRouter router = new WxMpMessageRouter(mpService);
|
WxMpMessageRouter router = new WxMpMessageRouter(mpService);
|
||||||
// 记录所有事件的日志(异步执行)
|
// 记录所有事件的日志(异步执行)
|
||||||
router.rule().handler(logHandler).next();
|
router.rule().handler(messageReceiveHandler).next();
|
||||||
|
|
||||||
// 接收客服会话管理事件
|
// 接收客服会话管理事件
|
||||||
router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
|
router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
|
||||||
@ -159,7 +159,7 @@ public class DefaultMpServiceFactory implements MpServiceFactory {
|
|||||||
.event(WxConsts.EventType.SCAN).handler(scanHandler).end();
|
.event(WxConsts.EventType.SCAN).handler(scanHandler).end();
|
||||||
|
|
||||||
// 默认
|
// 默认
|
||||||
router.rule().async(false).handler(msgHandler).end();
|
router.rule().async(false).handler(messageAutoReplyHandler).end();
|
||||||
return router;
|
return router;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
package cn.iocoder.yudao.module.mp.service.handler.user;
|
package cn.iocoder.yudao.module.mp.service.handler.user;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
|
import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder;
|
||||||
|
import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
@ -8,38 +13,37 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
|||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上报地理位置的事件处理器
|
* 上报地理位置的事件处理器
|
||||||
*
|
*
|
||||||
* // TODO @芋艿:需要实现一下~
|
* 触发操作:打开微信公众号 -> 点击 + 号 -> 选择「语音」
|
||||||
|
*
|
||||||
|
* 逻辑:用户上传地理位置时,也可以触发自动回复
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LocationHandler implements WxMpMessageHandler {
|
public class LocationHandler implements WxMpMessageHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MpAutoReplyService mpAutoReplyService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||||
// if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) {
|
// 防御性编程:必须是 LOCATION 消息
|
||||||
// //TODO 接收处理用户发送的地理位置消息
|
if (ObjectUtil.notEqual(wxMessage.getMsgType(), WxConsts.XmlMsgType.LOCATION)) {
|
||||||
// try {
|
return null;
|
||||||
// String content = "感谢反馈,您的的地理位置已收到!";
|
}
|
||||||
// return new TextBuilder().build(content, wxMessage, null);
|
log.info("[handle][上报地理位置,纬度({})、经度({})、精度({})", wxMessage.getLatitude(),
|
||||||
// } catch (Exception e) {
|
wxMessage.getLongitude(), wxMessage.getPrecision());
|
||||||
// log.error("位置消息接收处理失败", e);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //上报地理位置事件
|
|
||||||
// log.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",
|
|
||||||
// wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));
|
|
||||||
|
|
||||||
//TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
|
// 自动回复
|
||||||
|
return mpAutoReplyService.replyForMessage(MpContextHolder.getAppId(), wxMessage);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mp.service.handler.user;
|
|||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
|
||||||
import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder;
|
import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder;
|
||||||
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
||||||
|
import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService;
|
||||||
import cn.iocoder.yudao.module.mp.service.user.MpUserService;
|
import cn.iocoder.yudao.module.mp.service.user.MpUserService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
@ -22,19 +23,15 @@ import java.util.Map;
|
|||||||
* 关注的事件处理器
|
* 关注的事件处理器
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*
|
|
||||||
* // TODO 芋艿:待实现
|
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SubscribeHandler implements WxMpMessageHandler {
|
public class SubscribeHandler implements WxMpMessageHandler {
|
||||||
|
|
||||||
@Resource
|
|
||||||
@Lazy // 延迟加载,解决循环依赖的问题
|
|
||||||
private MpAccountService mpAccountService;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private MpUserService mpUserService;
|
private MpUserService mpUserService;
|
||||||
|
@Resource
|
||||||
|
private MpAutoReplyService mpAutoReplyService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||||
@ -49,24 +46,10 @@ public class SubscribeHandler implements WxMpMessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 第二步,保存用户信息
|
// 第二步,保存用户信息
|
||||||
MpUserDO mpUser = null;
|
mpUserService.saveUser(MpContextHolder.getAppId(), wxMpUser);
|
||||||
if (wxMpUser != null) {
|
|
||||||
mpUser = mpUserService.saveUser(MpContextHolder.getAppId(), wxMpUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第三步,回复关注的欢迎语 TODO 芋艿:关注的欢迎语
|
// 第三步,回复关注的欢迎语
|
||||||
// return new TextBuilder().build("感谢关注", wxMessage, weixinService);
|
return mpAutoReplyService.replyForSubscribe(MpContextHolder.getAppId(), wxMessage);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理特殊请求,比如如果是扫码进来的,可以做相应处理
|
|
||||||
*/
|
|
||||||
private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage)
|
|
||||||
throws Exception {
|
|
||||||
|
|
||||||
//TODO
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,4 +19,13 @@ public interface MpAutoReplyService {
|
|||||||
*/
|
*/
|
||||||
WxMpXmlOutMessage replyForMessage(String appId, WxMpXmlMessage wxMessage);
|
WxMpXmlOutMessage replyForMessage(String appId, WxMpXmlMessage wxMessage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当用户关注时,自动回复
|
||||||
|
*
|
||||||
|
* @param appId 微信公众号 appId
|
||||||
|
* @param wxMessage 消息
|
||||||
|
* @return 回复的消息
|
||||||
|
*/
|
||||||
|
WxMpXmlOutMessage replyForSubscribe(String appId, WxMpXmlMessage wxMessage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package cn.iocoder.yudao.module.mp.service.message;
|
package cn.iocoder.yudao.module.mp.service.message;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.module.mp.builder.TextBuilder;
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO;
|
||||||
import cn.iocoder.yudao.module.mp.dal.mysql.message.MpAutoReplyMapper;
|
import cn.iocoder.yudao.module.mp.dal.mysql.message.MpAutoReplyMapper;
|
||||||
import cn.iocoder.yudao.module.mp.enums.message.MpAutoReplyMatchEnum;
|
import cn.iocoder.yudao.module.mp.enums.message.MpAutoReplyTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
||||||
import me.chanjar.weixin.common.api.WxConsts;
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@ -25,15 +28,15 @@ public class MpAutoReplyServiceImpl implements MpAutoReplyService {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private MpMessageService mpMessageService;
|
private MpMessageService mpMessageService;
|
||||||
|
@Resource
|
||||||
|
@Lazy // 延迟加载,避免循环依赖
|
||||||
|
private MpAccountService mpAccountService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private MpAutoReplyMapper mpAutoReplyMapper;
|
private MpAutoReplyMapper mpAutoReplyMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxMpXmlOutMessage replyForMessage(String appId, WxMpXmlMessage wxMessage) {
|
public WxMpXmlOutMessage replyForMessage(String appId, WxMpXmlMessage wxMessage) {
|
||||||
// if (true) {
|
|
||||||
// return new TextBuilder().build("nihao", wxMessage, null);
|
|
||||||
// }
|
|
||||||
// 第一步,匹配自动回复
|
// 第一步,匹配自动回复
|
||||||
List<MpAutoReplyDO> replies = null;
|
List<MpAutoReplyDO> replies = null;
|
||||||
// 1.1 关键字
|
// 1.1 关键字
|
||||||
@ -58,4 +61,24 @@ public class MpAutoReplyServiceImpl implements MpAutoReplyService {
|
|||||||
return mpMessageService.createFromAutoReply(wxMessage.getFromUser(), reply);
|
return mpMessageService.createFromAutoReply(wxMessage.getFromUser(), reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxMpXmlOutMessage replyForSubscribe(String appId, WxMpXmlMessage wxMessage) {
|
||||||
|
// 第一步,匹配自动回复
|
||||||
|
List<MpAutoReplyDO> replies = mpAutoReplyMapper.selectListByAppIdAndSubscribe(appId);
|
||||||
|
MpAutoReplyDO reply = CollUtil.isNotEmpty(replies) ? CollUtil.getFirst(replies)
|
||||||
|
: buildDefaultSubscribeAutoReply(appId); // 如果不存在,提供一个默认末班
|
||||||
|
|
||||||
|
// 第二步,基于自动回复,创建消息
|
||||||
|
return mpMessageService.createFromAutoReply(wxMessage.getFromUser(), reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MpAutoReplyDO buildDefaultSubscribeAutoReply(String appId) {
|
||||||
|
MpAccountDO account = mpAccountService.getAccountFromCache(appId);
|
||||||
|
Assert.notNull(account, "公众号账号({}) 不存在", appId);
|
||||||
|
// 构建默认的【关注】自动回复
|
||||||
|
return new MpAutoReplyDO().setAppId(appId).setAccountId(account.getId())
|
||||||
|
.setType(MpAutoReplyTypeEnum.SUBSCRIBE.getType())
|
||||||
|
.setResponseMessageType(WxConsts.XmlMsgType.TEXT).setResponseContent("感谢关注");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public class MpMessageServiceImpl implements MpMessageService {
|
|||||||
}
|
}
|
||||||
mpMessageMapper.insert(message);
|
mpMessageMapper.insert(message);
|
||||||
|
|
||||||
// WxConsts.MenuButtonType.VIEW
|
// WxConsts.MenuButtonType.VIEW TODO 芋艿:待测试
|
||||||
// wxMessage.getEventKey()
|
// wxMessage.getEventKey()
|
||||||
|
|
||||||
// WxConsts.MenuButtonType.CLICK
|
// WxConsts.MenuButtonType.CLICK
|
||||||
|
Loading…
Reference in New Issue
Block a user