From 275a1b10f671cedbb72d0170f3a68a1ed4efa9dd Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 1 Jan 2023 21:58:26 +0800 Subject: [PATCH] =?UTF-8?q?mp=EF=BC=9A=E5=A2=9E=E5=8A=A0=20MpServiceFactor?= =?UTF-8?q?y=20=E7=AE=A1=E7=90=86=E5=88=9B=E5=BB=BA=E7=9A=84=20MpService~?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/account/MpAccountController.java | 4 +- .../dal/dataobject/account/MpAccountDO.java | 9 - .../mp/dal/mysql/account/MpAccountMapper.java | 6 + .../framework/mp/config/MpConfiguration.java | 46 +++++ .../mp/core/DefaultMpServiceFactory.java | 158 +++++++++++++++++ .../framework/mp/core/MpServiceFactory.java | 38 +++++ .../module/mp/framework/package-info.java | 8 +- .../WxMpMessageRouterConfiguration.java | 106 ------------ .../mq/costomer/MpConfigRefreshConsumer.java | 29 ++++ .../costomer/WxConfigDataRefreshConsumer.java | 29 ---- ...ssage.java => MpConfigRefreshMessage.java} | 4 +- ...ataProducer.java => MpConfigProducer.java} | 8 +- ...ountService.java => MpAccountService.java} | 11 +- .../service/account/MpAccountServiceImpl.java | 159 ++++++++++++++++++ .../service/account/WxAccountServiceImpl.java | 157 ----------------- .../fansmsgres}/NullHandler.java | 10 +- .../handler/DefaultMessageHandler.java} | 20 ++- .../handler/KfSessionHandler.java | 14 +- .../handler/LocationHandler.java | 12 +- .../mp/{ => service}/handler/LogHandler.java | 13 +- .../mp/{ => service}/handler/MenuHandler.java | 7 +- .../mp/{ => service}/handler/ScanHandler.java | 5 +- .../handler/StoreCheckNotifyHandler.java | 5 +- .../handler/SubscribeHandler.java | 20 ++- .../handler/UnsubscribeHandler.java | 18 +- 25 files changed, 539 insertions(+), 357 deletions(-) create mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/config/MpConfiguration.java create mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/DefaultMpServiceFactory.java create mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/MpServiceFactory.java delete mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java create mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/MpConfigRefreshConsumer.java delete mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/{WxConfigDataRefreshMessage.java => MpConfigRefreshMessage.java} (72%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/{WxMpConfigDataProducer.java => MpConfigProducer.java} (63%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/{WxAccountService.java => MpAccountService.java} (94%) create mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java delete mode 100644 yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{handler => service/fansmsgres}/NullHandler.java (61%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{handler/MsgHandler.java => service/handler/DefaultMessageHandler.java} (94%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/KfSessionHandler.java (56%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/LocationHandler.java (80%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/LogHandler.java (66%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/MenuHandler.java (88%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/ScanHandler.java (89%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/StoreCheckNotifyHandler.java (88%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/SubscribeHandler.java (93%) rename yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/{ => service}/handler/UnsubscribeHandler.java (80%) diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/MpAccountController.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/MpAccountController.java index a044e889ce..34ff08de8b 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/MpAccountController.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/MpAccountController.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.mp.controller.admin.account.vo.*; import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -25,7 +25,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; public class MpAccountController { @Resource - private WxAccountService wxAccountService; + private MpAccountService wxAccountService; @PostMapping("/create") @ApiOperation("创建公众号账户") diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/MpAccountDO.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/MpAccountDO.java index adefbfc576..877027556f 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/MpAccountDO.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/MpAccountDO.java @@ -63,13 +63,4 @@ public class MpAccountDO extends BaseDO { */ private String remark; - // TODO 芋艿:需要迁移走 - public WxMpConfigStorage toWxMpConfigStorage(RedisTemplateWxRedisOps redisTemplateWxRedisOps, WxMpProperties wxMpProperties) { - WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(redisTemplateWxRedisOps, wxMpProperties.getConfigStorage().getKeyPrefix()); - wxMpRedisConfig.setAppId(appId); - wxMpRedisConfig.setSecret(appSecret); - wxMpRedisConfig.setToken(token); - wxMpRedisConfig.setAesKey(aesKey); - return wxMpRedisConfig; - } } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/account/MpAccountMapper.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/account/MpAccountMapper.java index 7f03c2ccfa..268bacc3bd 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/account/MpAccountMapper.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/account/MpAccountMapper.java @@ -6,6 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; @Mapper public interface MpAccountMapper extends BaseMapperX { @@ -18,4 +21,7 @@ public interface MpAccountMapper extends BaseMapperX { .orderByDesc(MpAccountDO::getId)); } + @Select("SELECT COUNT(*) FROM mp_account WHERE update_time > #{maxUpdateTime}") + Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); + } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/config/MpConfiguration.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/config/MpConfiguration.java new file mode 100644 index 0000000000..c568a3a069 --- /dev/null +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/config/MpConfiguration.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mp.framework.mp.config; + +import cn.iocoder.yudao.module.mp.framework.mp.core.DefaultMpServiceFactory; +import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory; +import cn.iocoder.yudao.module.mp.service.fansmsgres.NullHandler; +import cn.iocoder.yudao.module.mp.service.handler.*; +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; + +/** + * 微信公众号的配置类 + * + * @author 芋道源码 + */ +@Configuration +public class MpConfiguration { + + @Bean + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + public RedisTemplateWxRedisOps redisTemplateWxRedisOps(StringRedisTemplate stringRedisTemplate) { + return new RedisTemplateWxRedisOps(stringRedisTemplate); + } + + @Bean + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + public MpServiceFactory mpServiceFactory(RedisTemplateWxRedisOps redisTemplateWxRedisOps, + WxMpProperties wxMpProperties, + LogHandler logHandler, + KfSessionHandler kfSessionHandler, + StoreCheckNotifyHandler storeCheckNotifyHandler, + MenuHandler menuHandler, + NullHandler nullHandler, + SubscribeHandler subscribeHandler, + UnsubscribeHandler unsubscribeHandler, + LocationHandler locationHandler, + ScanHandler scanHandler, + DefaultMessageHandler msgHandler) { + return new DefaultMpServiceFactory(redisTemplateWxRedisOps, wxMpProperties, + logHandler, kfSessionHandler, storeCheckNotifyHandler, menuHandler, + nullHandler, subscribeHandler, unsubscribeHandler, locationHandler, scanHandler, msgHandler); + } + +} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/DefaultMpServiceFactory.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/DefaultMpServiceFactory.java new file mode 100644 index 0000000000..09ff871bd9 --- /dev/null +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/DefaultMpServiceFactory.java @@ -0,0 +1,158 @@ +package cn.iocoder.yudao.module.mp.framework.mp.core; + +import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; +import cn.iocoder.yudao.module.mp.service.fansmsgres.NullHandler; +import cn.iocoder.yudao.module.mp.service.handler.*; +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; +import me.chanjar.weixin.mp.constant.WxMpEventConstants; + +import java.util.List; +import java.util.Map; + +/** + * 默认的 {@link MpServiceFactory} 实现类 + * + * @author 芋道源码 + */ +@Slf4j +@RequiredArgsConstructor +public class DefaultMpServiceFactory implements MpServiceFactory { + + /** + * 微信 appId 与 WxMpService 的映射 + */ + private volatile Map mpServices; + /** + * 微信 appId 与 WxMpMessageRouter 的映射 + */ + private volatile Map mpMessageRouters; + + private final RedisTemplateWxRedisOps redisTemplateWxRedisOps; + private final WxMpProperties mpProperties; + + // ========== 各种 Handler ========== + + private final LogHandler logHandler; + private final KfSessionHandler kfSessionHandler; + private final StoreCheckNotifyHandler storeCheckNotifyHandler; + private final MenuHandler menuHandler; + private final NullHandler nullHandler; + private final SubscribeHandler subscribeHandler; + private final UnsubscribeHandler unsubscribeHandler; + private final LocationHandler locationHandler; + private final ScanHandler scanHandler; + private final DefaultMessageHandler msgHandler; + + @Override + public void init(List list) { + Map mpServices = Maps.newHashMap(); + Map mpMessageRouters = Maps.newHashMap(); + // 处理 list + list.forEach(account -> { + // 构建 WxMpService 对象 + WxMpService mpService = buildMpService(account); + mpServices.put(account.getAppId(), mpService); + // 构建 WxMpMessageRouter 对象 + WxMpMessageRouter mpMessageRouter = buildMpMessageRouter(mpService); + mpMessageRouters.put(account.getAppId(), mpMessageRouter); + }); + + // 设置到缓存 + this.mpServices = mpServices; + this.mpMessageRouters = mpMessageRouters; + } + + @Override + public WxMpService getMpService(String appId) { + return mpServices.get(appId); + } + + @Override + public WxMpMessageRouter getMpMessageRouter(String appId) { + return mpMessageRouters.get(appId); + } + + private WxMpService buildMpService(MpAccountDO account) { + // 第一步,创建 WxMpRedisConfigImpl 对象 + // TODO 芋艿:需要确认下,redis key 的存储结构 + WxMpRedisConfigImpl configStorage = new WxMpRedisConfigImpl( + redisTemplateWxRedisOps, mpProperties.getConfigStorage().getKeyPrefix()); + configStorage.setAppId(account.getAppId()); + configStorage.setSecret(account.getAppSecret()); + configStorage.setToken(account.getToken()); + configStorage.setAesKey(account.getAesKey()); + + // 第二步,创建 WxMpService 对象 + WxMpService service = new WxMpServiceImpl(); + service.setWxMpConfigStorage(configStorage); + return null; + } + + private WxMpMessageRouter buildMpMessageRouter(WxMpService mpService) { + final WxMpMessageRouter newRouter = new WxMpMessageRouter(mpService); + // 记录所有事件的日志(异步执行) + newRouter.rule().handler(logHandler).next(); + + // 接收客服会话管理事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) + .handler(kfSessionHandler).end(); + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) + .handler(kfSessionHandler) + .end(); + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) + .handler(kfSessionHandler).end(); + + // 门店审核事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxMpEventConstants.POI_CHECK_NOTIFY) + .handler(storeCheckNotifyHandler).end(); + + // 自定义菜单事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.MenuButtonType.CLICK).handler(menuHandler).end(); + + // 点击菜单连接事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.MenuButtonType.VIEW).handler(nullHandler).end(); + + // 关注事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.SUBSCRIBE).handler(subscribeHandler) + .end(); + + // 取消关注事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.UNSUBSCRIBE) + .handler(unsubscribeHandler).end(); + + // 上报地理位置事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.LOCATION).handler(locationHandler) + .end(); + + // 接收地理位置消息 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION) + .handler(locationHandler).end(); + + // 扫码事件 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxConsts.EventType.SCAN).handler(scanHandler).end(); + + // 默认 + newRouter.rule().async(false).handler(msgHandler).end(); + return newRouter; + } + +} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/MpServiceFactory.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/MpServiceFactory.java new file mode 100644 index 0000000000..ba8dd87e30 --- /dev/null +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/MpServiceFactory.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mp.framework.mp.core; + +import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import me.chanjar.weixin.mp.api.WxMpService; + +import java.util.List; + +/** + * {@link WxMpService} 工厂接口 + * + * @author 芋道源码 + */ +public interface MpServiceFactory { + + /** + * 基于微信公众号的账号,初始化对应的 WxMpService 与 WxMpMessageRouter 实例 + * + * @param list 公众号的账号列表 + */ + void init(List list); + + /** + * 获得 appId 对应的 WxMpService 实例 + * + * @param appId 微信公众号 appId + * @return WxMpService 实例 + */ + WxMpService getMpService(String appId); + + /** + * 获得 appId 对应的 WxMpMessageRouter 实例 + * + * @param appId 微信公众号 appId + * @return WxMpMessageRouter 实例 + */ + WxMpMessageRouter getMpMessageRouter(String appId); +} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/package-info.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/package-info.java index f4ed18f3f4..112ecdd26e 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/package-info.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/package-info.java @@ -1,6 +1,6 @@ /** - * @date 2022/6/20 - * @author feng-dan - * @version 1.0 + * 属于 mp 模块的 framework 封装 + * + * @author 芋道源码 */ -package cn.iocoder.yudao.module.mp.framework; \ No newline at end of file +package cn.iocoder.yudao.module.mp.framework; diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java deleted file mode 100644 index 3fc8d37055..0000000000 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java +++ /dev/null @@ -1,106 +0,0 @@ -package cn.iocoder.yudao.module.mp.framework.weixin; - - -import cn.iocoder.yudao.module.mp.handler.*; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.chanjar.weixin.common.api.WxConsts; -import me.chanjar.weixin.mp.api.WxMpMessageRouter; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.constant.WxMpEventConstants; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * @author fengdan - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class WxMpMessageRouterConfiguration { - - @Resource - private WxMpService wxMpService; - @Resource - private LogHandler logHandler; - @Resource - private KfSessionHandler kfSessionHandler; - @Resource - private StoreCheckNotifyHandler storeCheckNotifyHandler; - @Resource - private MenuHandler menuHandler; - @Resource - private NullHandler nullHandler; - @Resource - private SubscribeHandler subscribeHandler; - @Resource - private UnsubscribeHandler unsubscribeHandler; - @Resource - private LocationHandler locationHandler; - @Resource - private ScanHandler scanHandler; - @Resource - private MsgHandler msgHandler; - - @Bean - public WxMpMessageRouter messageRouter() { - final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); - // 记录所有事件的日志 (异步执行) - newRouter.rule().handler(logHandler).next(); - - // 接收客服会话管理事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) - .handler(kfSessionHandler).end(); - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) - .handler(kfSessionHandler) - .end(); - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) - .handler(kfSessionHandler).end(); - - // 门店审核事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.POI_CHECK_NOTIFY) - .handler(storeCheckNotifyHandler).end(); - - // 自定义菜单事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.MenuButtonType.CLICK).handler(menuHandler).end(); - - // 点击菜单连接事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.MenuButtonType.VIEW).handler(nullHandler).end(); - - // 关注事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.SUBSCRIBE).handler(subscribeHandler) - .end(); - - // 取消关注事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.UNSUBSCRIBE) - .handler(unsubscribeHandler).end(); - - // 上报地理位置事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.LOCATION).handler(locationHandler) - .end(); - - // 接收地理位置消息 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION) - .handler(locationHandler).end(); - - // 扫码事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.SCAN).handler(scanHandler).end(); - - // 默认 - newRouter.rule().async(false).handler(msgHandler).end(); - - return newRouter; - } -} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/MpConfigRefreshConsumer.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/MpConfigRefreshConsumer.java new file mode 100644 index 0000000000..1b9caed872 --- /dev/null +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/MpConfigRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mp.mq.costomer; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.mp.mq.message.MpConfigRefreshMessage; +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link MpConfigRefreshMessage} 的消费者 + * + * @author lyz + */ +@Component +@Slf4j +public class MpConfigRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private MpAccountService wxAccountService; + + @Override + public void onMessage(MpConfigRefreshMessage message) { + log.info("[onMessage][收到 MpConfig 刷新消息]"); + wxAccountService.initLocalCache(); + } + +} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java deleted file mode 100644 index 2f0863b600..0000000000 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.mp.mq.costomer; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage; -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link WxConfigDataRefreshMessage} 的消费者 - * - * @author lyz - */ -@Component -@Slf4j -public class WxConfigDataRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private WxAccountService wxAccountService; - - @Override - public void onMessage(WxConfigDataRefreshMessage message) { - log.info("[onMessage][收到 WxConfigData 刷新消息]"); - wxAccountService.initLoadWxMpConfigStorages(); - } - -} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/MpConfigRefreshMessage.java similarity index 72% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/MpConfigRefreshMessage.java index 48382605c0..13bcc73352 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/MpConfigRefreshMessage.java @@ -9,11 +9,11 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class WxConfigDataRefreshMessage extends AbstractChannelMessage { +public class MpConfigRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { - return "wechat-mp.wx-config-data.refresh"; + return "mp.config-data.refresh"; } } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/MpConfigProducer.java similarity index 63% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/MpConfigProducer.java index d765b9aa7a..f64d33cd49 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/MpConfigProducer.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.mp.mq.producer; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; -import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage; +import cn.iocoder.yudao.module.mp.mq.message.MpConfigRefreshMessage; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -10,16 +10,16 @@ import javax.annotation.Resource; * 微信配置数据相关消息的 Producer */ @Component -public class WxMpConfigDataProducer { +public class MpConfigProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link WxConfigDataRefreshMessage} 消息 + * 发送 {@link MpConfigRefreshMessage} 消息 */ public void sendDictDataRefreshMessage() { - WxConfigDataRefreshMessage message = new WxConfigDataRefreshMessage(); + MpConfigRefreshMessage message = new MpConfigRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountService.java similarity index 94% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountService.java index c832e69471..b242c30a33 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountService.java @@ -14,7 +14,12 @@ import javax.validation.Valid; * * @author 芋道源码 */ -public interface WxAccountService { +public interface MpAccountService { + + /** + * 初始化缓存 + */ + void initLocalCache(); /** * 创建公众号账户 @@ -64,8 +69,4 @@ public interface WxAccountService { */ MpAccountDO findBy(SFunction field, Object val); - /** - * 初始化 - */ - void initLoadWxMpConfigStorages(); } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java new file mode 100644 index 0000000000..e6b6b77e2a --- /dev/null +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java @@ -0,0 +1,159 @@ +package cn.iocoder.yudao.module.mp.service.account; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO; +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO; +import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; +import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; +import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper; +import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory; +import cn.iocoder.yudao.module.mp.mq.producer.MpConfigProducer; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; + + +/** + * 公众号账户 Service 实现类 + * + * @author fengdan + */ +@Slf4j +@Service +@Validated +public class MpAccountServiceImpl implements MpAccountService { + + /** + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 + */ + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; + + /** + * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + @Getter + private volatile LocalDateTime maxUpdateTime; + + @Resource + private MpAccountMapper mpAccountMapper; + + @Resource + @Lazy // 延迟加载,解决循环依赖的问题 + private MpServiceFactory mpServiceFactory; + + @Resource + private MpConfigProducer mpConfigDataProducer; + + @Override + @PostConstruct + public void initLocalCache() { + initLocalCacheIfUpdate(null); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initLocalCacheIfUpdate(this.maxUpdateTime); + } + + /** + * 刷新本地缓存 + * + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 + */ + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 注意:忽略自动多租户,因为要全局初始化缓存 + TenantUtils.executeIgnore(() -> { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && mpAccountMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; + } + List accounts = mpAccountMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size()); + + // 第二步:构建缓存。创建或更新支付 Client + mpServiceFactory.init(accounts); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(accounts, MpAccountDO::getUpdateTime); + }); + } + + @Override + public Long createAccount(MpAccountCreateReqVO createReqVO) { + // TODO 芋艿:校验唯一性 + // 插入 + MpAccountDO wxAccount = MpAccountConvert.INSTANCE.convert(createReqVO); + mpAccountMapper.insert(wxAccount); + + // TODO 芋艿:刷新的方式 + mpConfigDataProducer.sendDictDataRefreshMessage(); + // 返回 + return wxAccount.getId(); + } + + @Override + public void updateAccount(MpAccountUpdateReqVO updateReqVO) { + // TODO 芋艿:校验唯一性 + // 校验存在 + validateWxAccountExists(updateReqVO.getId()); + // 更新 + MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO); + mpAccountMapper.updateById(updateObj); + + // TODO 芋艿:刷新的方式 + mpConfigDataProducer.sendDictDataRefreshMessage(); + } + + @Override + public void deleteAccount(Long id) { + // 校验存在 + validateWxAccountExists(id); + // 删除 + mpAccountMapper.deleteById(id); + + // TODO 芋艿:刷新的方式 + mpConfigDataProducer.sendDictDataRefreshMessage(); + } + + private void validateWxAccountExists(Long id) { + if (mpAccountMapper.selectById(id) == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.WX_ACCOUNT_NOT_EXISTS); + } + } + + @Override + public MpAccountDO getAccount(Long id) { + return mpAccountMapper.selectById(id); + } + + @Override + public PageResult getAccountPage(MpAccountPageReqVO pageReqVO) { + return mpAccountMapper.selectPage(pageReqVO); + } + + @Override + public MpAccountDO findBy(SFunction field, Object val) { + return mpAccountMapper.selectOne(field, val); + } + +} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java deleted file mode 100644 index 094d5b3754..0000000000 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java +++ /dev/null @@ -1,157 +0,0 @@ -package cn.iocoder.yudao.module.mp.service.account; - -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO; -import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; -import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO; -import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; -import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; -import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper; -import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.mp.mq.producer.WxMpConfigDataProducer; -import com.baomidou.mybatisplus.core.toolkit.support.SFunction; -import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; -import lombok.extern.slf4j.Slf4j; -import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.config.WxMpConfigStorage; -import org.springframework.context.annotation.Lazy; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * 公众号账户 Service 实现类 - * - * @author fengdan - */ -@Slf4j -@Service -@Validated -public class WxAccountServiceImpl implements WxAccountService { - - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; - - @Resource - private MpAccountMapper wxAccountMapper; - @Resource - private WxMpConfigDataProducer wxMpConfigDataProducer; - @Resource - private StringRedisTemplate stringRedisTemplate; - @Resource - private WxMpService wxMpService; - @Resource - private WxMpProperties wxMpProperties; - @Resource - @Lazy // 注入自己,所以延迟加载 - private WxAccountService self; - - @Override - public Long createAccount(MpAccountCreateReqVO createReqVO) { - // TODO 芋艿:校验唯一性 - // 插入 - MpAccountDO wxAccount = MpAccountConvert.INSTANCE.convert(createReqVO); - wxAccountMapper.insert(wxAccount); - - // TODO 芋艿:刷新的方式 - wxMpConfigDataProducer.sendDictDataRefreshMessage(); - // 返回 - return wxAccount.getId(); - } - - @Override - public void updateAccount(MpAccountUpdateReqVO updateReqVO) { - // TODO 芋艿:校验唯一性 - // 校验存在 - validateWxAccountExists(updateReqVO.getId()); - // 更新 - MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO); - wxAccountMapper.updateById(updateObj); - - // TODO 芋艿:刷新的方式 - wxMpConfigDataProducer.sendDictDataRefreshMessage(); - } - - @Override - public void deleteAccount(Long id) { - // 校验存在 - validateWxAccountExists(id); - // 删除 - wxAccountMapper.deleteById(id); - - // TODO 芋艿:刷新的方式 - wxMpConfigDataProducer.sendDictDataRefreshMessage(); - } - - private void validateWxAccountExists(Long id) { - if (wxAccountMapper.selectById(id) == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.WX_ACCOUNT_NOT_EXISTS); - } - } - - @Override - public MpAccountDO getAccount(Long id) { - return wxAccountMapper.selectById(id); - } - - @Override - public PageResult getAccountPage(MpAccountPageReqVO pageReqVO) { - return wxAccountMapper.selectPage(pageReqVO); - } - - @Override - public MpAccountDO findBy(SFunction field, Object val) { - return wxAccountMapper.selectOne(field, val); - } - - @PostConstruct - @TenantIgnore - @Override - public void initLoadWxMpConfigStorages() { - // TODO 芋艿:刷新的方式 - List wxAccountList = this.wxAccountMapper.selectList(); - if (CollectionUtils.isEmpty(wxAccountList)) { - log.info("未读取到公众号配置,请在管理后台添加"); - return; - } - log.info("加载到{}条公众号配置", wxAccountList.size()); - wxAccountList.forEach(account -> addAccountToRuntime(account, new RedisTemplateWxRedisOps(stringRedisTemplate))); - log.info("公众号配置加载完成"); - } - - /** - * 添加账号到当前程序,如首次添加需初始化configStorageMap - * - * @param account 公众号 - */ - private synchronized void addAccountToRuntime(MpAccountDO account, RedisTemplateWxRedisOps redisOps) { - String appId = account.getAppId(); - WxMpConfigStorage wxMpRedisConfig = account.toWxMpConfigStorage(redisOps, wxMpProperties); - try { - wxMpService.addConfigStorage(appId, wxMpRedisConfig); - } catch (NullPointerException e) { - log.info("需初始化configStorageMap..."); - Map configStorages = new HashMap<>(4); - configStorages.put(appId, wxMpRedisConfig); - wxMpService.setMultiConfigStorages(configStorages, appId); - } - } - - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - self.initLoadWxMpConfigStorages(); - } - - -} diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/NullHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/fansmsgres/NullHandler.java similarity index 61% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/NullHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/fansmsgres/NullHandler.java index abc907622c..82e9b8913f 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/NullHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/fansmsgres/NullHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.fansmsgres; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpMessageHandler; @@ -9,13 +9,15 @@ import org.springframework.stereotype.Component; import java.util.Map; +/** + * 点击菜单连接的事件处理器 + */ @Component public class NullHandler implements WxMpMessageHandler { @Override - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, - Map context, WxMpService wxMpService, - WxSessionManager sessionManager) { + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, + WxMpService wxMpService, WxSessionManager sessionManager) { return null; } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/DefaultMessageHandler.java similarity index 94% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/DefaultMessageHandler.java index 87d2b2c8a3..6bd87663d8 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/DefaultMessageHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import cn.hutool.core.io.FileUtil; import cn.hutool.http.HtmlUtil; @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.mp.builder.TextBuilder; import cn.iocoder.yudao.module.mp.controller.admin.fansmsg.vo.WxFansMsgCreateReqVO; import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; import cn.iocoder.yudao.module.mp.service.fansmsg.WxFansMsgService; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; @@ -21,6 +21,7 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -28,11 +29,18 @@ import java.io.File; import java.io.UnsupportedEncodingException; import java.util.Map; +/** + * 默认所有消息的事件处理器 + * + * // TODO 芋艿:待实现 + */ @Component @Slf4j -public class MsgHandler implements WxMpMessageHandler { - @Autowired - private WxAccountService wxAccountService; +public class DefaultMessageHandler implements WxMpMessageHandler { + + @Resource + @Lazy // 延迟加载,解决循环依赖的问题 + private MpAccountService mpAccountService; @Autowired private WxFansMsgService wxFansMsgService; @@ -55,7 +63,7 @@ public class MsgHandler implements WxMpMessageHandler { WxMpUser wxmpUser = weixinService.getUserService() .userInfo(wxMessage.getFromUser(), null); if (wxmpUser != null) { - MpAccountDO wxAccount = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); + MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); if (wxAccount != null) { if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.TEXT)) { diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/KfSessionHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/KfSessionHandler.java similarity index 56% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/KfSessionHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/KfSessionHandler.java index 47150d48d8..a432fcb007 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/KfSessionHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/KfSessionHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpMessageHandler; @@ -9,14 +9,18 @@ import org.springframework.stereotype.Component; import java.util.Map; +/** + * 接收客服会话管理的事件处理器 + * + * @author 芋道源码 + */ @Component public class KfSessionHandler implements WxMpMessageHandler { @Override - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, - Map context, WxMpService wxMpService, - WxSessionManager sessionManager) { - //TODO 对会话做处理 + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, + WxMpService wxMpService, WxSessionManager sessionManager) { + // TODO 对会话做处理 return null; } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LocationHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LocationHandler.java similarity index 80% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LocationHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LocationHandler.java index af5a22b62e..3cfefbb56d 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LocationHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LocationHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import cn.iocoder.yudao.module.mp.builder.TextBuilder; import lombok.extern.slf4j.Slf4j; @@ -13,14 +13,18 @@ import java.util.Map; import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; +/** + * 上报地理位置的事件处理器 + * + * // TODO @芋艿:需要实现一下~ + */ @Component @Slf4j public class LocationHandler implements WxMpMessageHandler { @Override - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, - Map context, WxMpService wxMpService, - WxSessionManager sessionManager) { + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, + WxMpService wxMpService, WxSessionManager sessionManager) { if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { //TODO 接收处理用户发送的地理位置消息 try { diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LogHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LogHandler.java similarity index 66% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LogHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LogHandler.java index 58ae131cda..4e08f3c5bb 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LogHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LogHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import lombok.extern.slf4j.Slf4j; @@ -11,13 +11,18 @@ import org.springframework.stereotype.Component; import java.util.Map; +/** + * 保存微信消息的事件处理器 + * + * // TODO 芋艿:实现一下 + */ @Component @Slf4j public class LogHandler implements WxMpMessageHandler { + @Override - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, - Map context, WxMpService wxMpService, - WxSessionManager sessionManager) { + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, + WxMpService wxMpService, WxSessionManager sessionManager) { log.info("接收到请求消息,内容:{}", JsonUtils.toJsonString(wxMessage)); return null; } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MenuHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/MenuHandler.java similarity index 88% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MenuHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/MenuHandler.java index 2eacfb0687..9146b7f23a 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MenuHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/MenuHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpMessageHandler; @@ -11,6 +11,11 @@ import java.util.Map; import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; +/** + * 自定义菜单的事件处理器 + * + * // TODO 芋艿:待实现 + */ @Component public class MenuHandler implements WxMpMessageHandler { diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/ScanHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/ScanHandler.java similarity index 89% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/ScanHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/ScanHandler.java index 20d0c0ee99..030e8578ce 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/ScanHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/ScanHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; @@ -10,6 +10,9 @@ import org.springframework.stereotype.Component; import java.util.Map; +/** + * 扫码的事件处理器 + */ @Component public class ScanHandler implements WxMpMessageHandler { diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/StoreCheckNotifyHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/StoreCheckNotifyHandler.java similarity index 88% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/StoreCheckNotifyHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/StoreCheckNotifyHandler.java index 52715c511b..9eb838ef22 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/StoreCheckNotifyHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/StoreCheckNotifyHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpMessageHandler; @@ -10,8 +10,7 @@ import org.springframework.stereotype.Component; import java.util.Map; /** - * 门店审核事件处理 - * + * 门店审核事件的事件处理器 */ @Component public class StoreCheckNotifyHandler implements WxMpMessageHandler { diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/SubscribeHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/SubscribeHandler.java similarity index 93% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/SubscribeHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/SubscribeHandler.java index 606fa32c28..d189187bbb 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/SubscribeHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/SubscribeHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import cn.hutool.core.date.DateUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; import cn.iocoder.yudao.module.mp.dal.dataobject.accountfans.WxAccountFansDO; import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO; import cn.iocoder.yudao.module.mp.dal.dataobject.texttemplate.WxTextTemplateDO; -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; import cn.iocoder.yudao.module.mp.service.accountfans.WxAccountFansService; import cn.iocoder.yudao.module.mp.service.accountfanstag.WxAccountFansTagService; import cn.iocoder.yudao.module.mp.service.subscribetext.WxSubscribeTextService; @@ -23,11 +23,18 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import java.io.UnsupportedEncodingException; import java.util.Map; +/** + * 关注的事件处理器 + * + * // TODO 芋艿:待实现 + */ @Component @Slf4j public class SubscribeHandler implements WxMpMessageHandler { @@ -35,8 +42,9 @@ public class SubscribeHandler implements WxMpMessageHandler { @Autowired private WxTextTemplateService wxTextTemplateService; - @Autowired - private WxAccountService wxAccountService; + @Resource + @Lazy // 延迟加载,解决循环依赖的问题 + private MpAccountService mpAccountService; @Autowired private WxSubscribeTextService wxSubscribeTextService; @@ -60,7 +68,7 @@ public class SubscribeHandler implements WxMpMessageHandler { .userInfo(wxMessage.getFromUser(), null); if (wxmpUser != null) { // 可以添加关注用户到本地数据库 - MpAccountDO wxAccount = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); + MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); if (wxAccount != null) { WxAccountFansDO wxAccountFans = wxAccountFansService.findBy(WxAccountFansDO::getOpenid, wxmpUser.getOpenId()); if (wxAccountFans == null) {//insert @@ -128,7 +136,7 @@ public class SubscribeHandler implements WxMpMessageHandler { try { String content = "感谢关注!";//默认 - MpAccountDO wxAccount = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); + MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); if (wxAccount != null) { WxSubscribeTextDO wxSubscribeText = wxSubscribeTextService.findBy(WxSubscribeTextDO::getWxAccountId, String.valueOf(wxAccount.getId())); if (wxSubscribeText != null) { diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/UnsubscribeHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/UnsubscribeHandler.java similarity index 80% rename from yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/UnsubscribeHandler.java rename to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/UnsubscribeHandler.java index b9d81f4460..74e1b6355f 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/UnsubscribeHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/UnsubscribeHandler.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.module.mp.handler; +package cn.iocoder.yudao.module.mp.service.handler; import cn.iocoder.yudao.module.mp.controller.admin.accountfans.vo.WxAccountFansUpdateReqVO; import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; import cn.iocoder.yudao.module.mp.dal.dataobject.accountfans.WxAccountFansDO; -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; import cn.iocoder.yudao.module.mp.service.accountfans.WxAccountFansService; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.session.WxSessionManager; @@ -12,16 +12,24 @@ import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import java.util.Map; +/** + * 取消关注的事件处理器 + * + * // TODO 芋艿:待实现 + */ @Component @Slf4j public class UnsubscribeHandler implements WxMpMessageHandler { - @Autowired - private WxAccountService wxAccountService; + @Resource + @Lazy // 延迟加载,解决循环依赖的问题 + private MpAccountService mpAccountService; @Autowired private WxAccountFansService wxAccountFansService; @@ -34,7 +42,7 @@ public class UnsubscribeHandler implements WxMpMessageHandler { log.info("取消关注用户 OPENID: " + openId); // TODO 可以更新本地数据库为取消关注状态 - MpAccountDO wxAccountDO = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); + MpAccountDO wxAccountDO = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); if (wxAccountDO != null) { WxAccountFansDO wxAccountFansDO = wxAccountFansService.findBy(WxAccountFansDO::getOpenid, openId); if (wxAccountFansDO != null) {