Commit 275a1b10f671cedbb72d0170f3a68a1ed4efa9dd
1 parent
627cb395
mp:增加 MpServiceFactory 管理创建的 MpService~
Showing
23 changed files
with
431 additions
and
249 deletions
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; |
| 5 | 5 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.*; |
| 6 | 6 | import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; |
| 7 | 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 8 | -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; | |
| 8 | +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | |
| 9 | 9 | import io.swagger.annotations.Api; |
| 10 | 10 | import io.swagger.annotations.ApiImplicitParam; |
| 11 | 11 | import io.swagger.annotations.ApiOperation; |
| ... | ... | @@ -25,7 +25,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 25 | 25 | public class MpAccountController { |
| 26 | 26 | |
| 27 | 27 | @Resource |
| 28 | - private WxAccountService wxAccountService; | |
| 28 | + private MpAccountService wxAccountService; | |
| 29 | 29 | |
| 30 | 30 | @PostMapping("/create") |
| 31 | 31 | @ApiOperation("创建公众号账户") | ... | ... |
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 { |
| 63 | 63 | */ |
| 64 | 64 | private String remark; |
| 65 | 65 | |
| 66 | - // TODO 芋艿:需要迁移走 | |
| 67 | - public WxMpConfigStorage toWxMpConfigStorage(RedisTemplateWxRedisOps redisTemplateWxRedisOps, WxMpProperties wxMpProperties) { | |
| 68 | - WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(redisTemplateWxRedisOps, wxMpProperties.getConfigStorage().getKeyPrefix()); | |
| 69 | - wxMpRedisConfig.setAppId(appId); | |
| 70 | - wxMpRedisConfig.setSecret(appSecret); | |
| 71 | - wxMpRedisConfig.setToken(token); | |
| 72 | - wxMpRedisConfig.setAesKey(aesKey); | |
| 73 | - return wxMpRedisConfig; | |
| 74 | - } | |
| 75 | 66 | } | ... | ... |
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; |
| 6 | 6 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; |
| 7 | 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 8 | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | +import org.apache.ibatis.annotations.Select; | |
| 10 | + | |
| 11 | +import java.time.LocalDateTime; | |
| 9 | 12 | |
| 10 | 13 | @Mapper |
| 11 | 14 | public interface MpAccountMapper extends BaseMapperX<MpAccountDO> { |
| ... | ... | @@ -18,4 +21,7 @@ public interface MpAccountMapper extends BaseMapperX<MpAccountDO> { |
| 18 | 21 | .orderByDesc(MpAccountDO::getId)); |
| 19 | 22 | } |
| 20 | 23 | |
| 24 | + @Select("SELECT COUNT(*) FROM mp_account WHERE update_time > #{maxUpdateTime}") | |
| 25 | + Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | |
| 26 | + | |
| 21 | 27 | } | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/config/MpConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mp.framework.mp.config; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.mp.framework.mp.core.DefaultMpServiceFactory; | |
| 4 | +import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory; | |
| 5 | +import cn.iocoder.yudao.module.mp.service.fansmsgres.NullHandler; | |
| 6 | +import cn.iocoder.yudao.module.mp.service.handler.*; | |
| 7 | +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; | |
| 8 | +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; | |
| 9 | +import org.springframework.context.annotation.Bean; | |
| 10 | +import org.springframework.context.annotation.Configuration; | |
| 11 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 微信公众号的配置类 | |
| 15 | + * | |
| 16 | + * @author 芋道源码 | |
| 17 | + */ | |
| 18 | +@Configuration | |
| 19 | +public class MpConfiguration { | |
| 20 | + | |
| 21 | + @Bean | |
| 22 | + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") | |
| 23 | + public RedisTemplateWxRedisOps redisTemplateWxRedisOps(StringRedisTemplate stringRedisTemplate) { | |
| 24 | + return new RedisTemplateWxRedisOps(stringRedisTemplate); | |
| 25 | + } | |
| 26 | + | |
| 27 | + @Bean | |
| 28 | + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") | |
| 29 | + public MpServiceFactory mpServiceFactory(RedisTemplateWxRedisOps redisTemplateWxRedisOps, | |
| 30 | + WxMpProperties wxMpProperties, | |
| 31 | + LogHandler logHandler, | |
| 32 | + KfSessionHandler kfSessionHandler, | |
| 33 | + StoreCheckNotifyHandler storeCheckNotifyHandler, | |
| 34 | + MenuHandler menuHandler, | |
| 35 | + NullHandler nullHandler, | |
| 36 | + SubscribeHandler subscribeHandler, | |
| 37 | + UnsubscribeHandler unsubscribeHandler, | |
| 38 | + LocationHandler locationHandler, | |
| 39 | + ScanHandler scanHandler, | |
| 40 | + DefaultMessageHandler msgHandler) { | |
| 41 | + return new DefaultMpServiceFactory(redisTemplateWxRedisOps, wxMpProperties, | |
| 42 | + logHandler, kfSessionHandler, storeCheckNotifyHandler, menuHandler, | |
| 43 | + nullHandler, subscribeHandler, unsubscribeHandler, locationHandler, scanHandler, msgHandler); | |
| 44 | + } | |
| 45 | + | |
| 46 | +} | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/DefaultMpServiceFactory.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mp.framework.mp.core; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | |
| 4 | +import cn.iocoder.yudao.module.mp.service.fansmsgres.NullHandler; | |
| 5 | +import cn.iocoder.yudao.module.mp.service.handler.*; | |
| 6 | +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; | |
| 7 | +import com.google.common.collect.Maps; | |
| 8 | +import lombok.RequiredArgsConstructor; | |
| 9 | +import lombok.extern.slf4j.Slf4j; | |
| 10 | +import me.chanjar.weixin.common.api.WxConsts; | |
| 11 | +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; | |
| 12 | +import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |
| 13 | +import me.chanjar.weixin.mp.api.WxMpService; | |
| 14 | +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; | |
| 15 | +import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; | |
| 16 | +import me.chanjar.weixin.mp.constant.WxMpEventConstants; | |
| 17 | + | |
| 18 | +import java.util.List; | |
| 19 | +import java.util.Map; | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * 默认的 {@link MpServiceFactory} 实现类 | |
| 23 | + * | |
| 24 | + * @author 芋道源码 | |
| 25 | + */ | |
| 26 | +@Slf4j | |
| 27 | +@RequiredArgsConstructor | |
| 28 | +public class DefaultMpServiceFactory implements MpServiceFactory { | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 微信 appId 与 WxMpService 的映射 | |
| 32 | + */ | |
| 33 | + private volatile Map<String, WxMpService> mpServices; | |
| 34 | + /** | |
| 35 | + * 微信 appId 与 WxMpMessageRouter 的映射 | |
| 36 | + */ | |
| 37 | + private volatile Map<String, WxMpMessageRouter> mpMessageRouters; | |
| 38 | + | |
| 39 | + private final RedisTemplateWxRedisOps redisTemplateWxRedisOps; | |
| 40 | + private final WxMpProperties mpProperties; | |
| 41 | + | |
| 42 | + // ========== 各种 Handler ========== | |
| 43 | + | |
| 44 | + private final LogHandler logHandler; | |
| 45 | + private final KfSessionHandler kfSessionHandler; | |
| 46 | + private final StoreCheckNotifyHandler storeCheckNotifyHandler; | |
| 47 | + private final MenuHandler menuHandler; | |
| 48 | + private final NullHandler nullHandler; | |
| 49 | + private final SubscribeHandler subscribeHandler; | |
| 50 | + private final UnsubscribeHandler unsubscribeHandler; | |
| 51 | + private final LocationHandler locationHandler; | |
| 52 | + private final ScanHandler scanHandler; | |
| 53 | + private final DefaultMessageHandler msgHandler; | |
| 54 | + | |
| 55 | + @Override | |
| 56 | + public void init(List<MpAccountDO> list) { | |
| 57 | + Map<String, WxMpService> mpServices = Maps.newHashMap(); | |
| 58 | + Map<String, WxMpMessageRouter> mpMessageRouters = Maps.newHashMap(); | |
| 59 | + // 处理 list | |
| 60 | + list.forEach(account -> { | |
| 61 | + // 构建 WxMpService 对象 | |
| 62 | + WxMpService mpService = buildMpService(account); | |
| 63 | + mpServices.put(account.getAppId(), mpService); | |
| 64 | + // 构建 WxMpMessageRouter 对象 | |
| 65 | + WxMpMessageRouter mpMessageRouter = buildMpMessageRouter(mpService); | |
| 66 | + mpMessageRouters.put(account.getAppId(), mpMessageRouter); | |
| 67 | + }); | |
| 68 | + | |
| 69 | + // 设置到缓存 | |
| 70 | + this.mpServices = mpServices; | |
| 71 | + this.mpMessageRouters = mpMessageRouters; | |
| 72 | + } | |
| 73 | + | |
| 74 | + @Override | |
| 75 | + public WxMpService getMpService(String appId) { | |
| 76 | + return mpServices.get(appId); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public WxMpMessageRouter getMpMessageRouter(String appId) { | |
| 81 | + return mpMessageRouters.get(appId); | |
| 82 | + } | |
| 83 | + | |
| 84 | + private WxMpService buildMpService(MpAccountDO account) { | |
| 85 | + // 第一步,创建 WxMpRedisConfigImpl 对象 | |
| 86 | + // TODO 芋艿:需要确认下,redis key 的存储结构 | |
| 87 | + WxMpRedisConfigImpl configStorage = new WxMpRedisConfigImpl( | |
| 88 | + redisTemplateWxRedisOps, mpProperties.getConfigStorage().getKeyPrefix()); | |
| 89 | + configStorage.setAppId(account.getAppId()); | |
| 90 | + configStorage.setSecret(account.getAppSecret()); | |
| 91 | + configStorage.setToken(account.getToken()); | |
| 92 | + configStorage.setAesKey(account.getAesKey()); | |
| 93 | + | |
| 94 | + // 第二步,创建 WxMpService 对象 | |
| 95 | + WxMpService service = new WxMpServiceImpl(); | |
| 96 | + service.setWxMpConfigStorage(configStorage); | |
| 97 | + return null; | |
| 98 | + } | |
| 99 | + | |
| 100 | + private WxMpMessageRouter buildMpMessageRouter(WxMpService mpService) { | |
| 101 | + final WxMpMessageRouter newRouter = new WxMpMessageRouter(mpService); | |
| 102 | + // 记录所有事件的日志(异步执行) | |
| 103 | + newRouter.rule().handler(logHandler).next(); | |
| 104 | + | |
| 105 | + // 接收客服会话管理事件 | |
| 106 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 107 | + .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) | |
| 108 | + .handler(kfSessionHandler).end(); | |
| 109 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 110 | + .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) | |
| 111 | + .handler(kfSessionHandler) | |
| 112 | + .end(); | |
| 113 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 114 | + .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) | |
| 115 | + .handler(kfSessionHandler).end(); | |
| 116 | + | |
| 117 | + // 门店审核事件 | |
| 118 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 119 | + .event(WxMpEventConstants.POI_CHECK_NOTIFY) | |
| 120 | + .handler(storeCheckNotifyHandler).end(); | |
| 121 | + | |
| 122 | + // 自定义菜单事件 | |
| 123 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 124 | + .event(WxConsts.MenuButtonType.CLICK).handler(menuHandler).end(); | |
| 125 | + | |
| 126 | + // 点击菜单连接事件 | |
| 127 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 128 | + .event(WxConsts.MenuButtonType.VIEW).handler(nullHandler).end(); | |
| 129 | + | |
| 130 | + // 关注事件 | |
| 131 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 132 | + .event(WxConsts.EventType.SUBSCRIBE).handler(subscribeHandler) | |
| 133 | + .end(); | |
| 134 | + | |
| 135 | + // 取消关注事件 | |
| 136 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 137 | + .event(WxConsts.EventType.UNSUBSCRIBE) | |
| 138 | + .handler(unsubscribeHandler).end(); | |
| 139 | + | |
| 140 | + // 上报地理位置事件 | |
| 141 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 142 | + .event(WxConsts.EventType.LOCATION).handler(locationHandler) | |
| 143 | + .end(); | |
| 144 | + | |
| 145 | + // 接收地理位置消息 | |
| 146 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION) | |
| 147 | + .handler(locationHandler).end(); | |
| 148 | + | |
| 149 | + // 扫码事件 | |
| 150 | + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 151 | + .event(WxConsts.EventType.SCAN).handler(scanHandler).end(); | |
| 152 | + | |
| 153 | + // 默认 | |
| 154 | + newRouter.rule().async(false).handler(msgHandler).end(); | |
| 155 | + return newRouter; | |
| 156 | + } | |
| 157 | + | |
| 158 | +} | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/mp/core/MpServiceFactory.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mp.framework.mp.core; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | |
| 4 | +import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |
| 5 | +import me.chanjar.weixin.mp.api.WxMpService; | |
| 6 | + | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * {@link WxMpService} 工厂接口 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +public interface MpServiceFactory { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 基于微信公众号的账号,初始化对应的 WxMpService 与 WxMpMessageRouter 实例 | |
| 18 | + * | |
| 19 | + * @param list 公众号的账号列表 | |
| 20 | + */ | |
| 21 | + void init(List<MpAccountDO> list); | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 获得 appId 对应的 WxMpService 实例 | |
| 25 | + * | |
| 26 | + * @param appId 微信公众号 appId | |
| 27 | + * @return WxMpService 实例 | |
| 28 | + */ | |
| 29 | + WxMpService getMpService(String appId); | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 获得 appId 对应的 WxMpMessageRouter 实例 | |
| 33 | + * | |
| 34 | + * @param appId 微信公众号 appId | |
| 35 | + * @return WxMpMessageRouter 实例 | |
| 36 | + */ | |
| 37 | + WxMpMessageRouter getMpMessageRouter(String appId); | |
| 38 | +} | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/package-info.java
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java deleted
| 1 | -package cn.iocoder.yudao.module.mp.framework.weixin; | |
| 2 | - | |
| 3 | - | |
| 4 | -import cn.iocoder.yudao.module.mp.handler.*; | |
| 5 | -import lombok.RequiredArgsConstructor; | |
| 6 | -import lombok.extern.slf4j.Slf4j; | |
| 7 | -import me.chanjar.weixin.common.api.WxConsts; | |
| 8 | -import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |
| 9 | -import me.chanjar.weixin.mp.api.WxMpService; | |
| 10 | -import me.chanjar.weixin.mp.constant.WxMpEventConstants; | |
| 11 | -import org.springframework.context.annotation.Bean; | |
| 12 | -import org.springframework.stereotype.Component; | |
| 13 | - | |
| 14 | -import javax.annotation.Resource; | |
| 15 | - | |
| 16 | -/** | |
| 17 | - * @author fengdan | |
| 18 | - */ | |
| 19 | -@Slf4j | |
| 20 | -@Component | |
| 21 | -@RequiredArgsConstructor | |
| 22 | -public class WxMpMessageRouterConfiguration { | |
| 23 | - | |
| 24 | - @Resource | |
| 25 | - private WxMpService wxMpService; | |
| 26 | - @Resource | |
| 27 | - private LogHandler logHandler; | |
| 28 | - @Resource | |
| 29 | - private KfSessionHandler kfSessionHandler; | |
| 30 | - @Resource | |
| 31 | - private StoreCheckNotifyHandler storeCheckNotifyHandler; | |
| 32 | - @Resource | |
| 33 | - private MenuHandler menuHandler; | |
| 34 | - @Resource | |
| 35 | - private NullHandler nullHandler; | |
| 36 | - @Resource | |
| 37 | - private SubscribeHandler subscribeHandler; | |
| 38 | - @Resource | |
| 39 | - private UnsubscribeHandler unsubscribeHandler; | |
| 40 | - @Resource | |
| 41 | - private LocationHandler locationHandler; | |
| 42 | - @Resource | |
| 43 | - private ScanHandler scanHandler; | |
| 44 | - @Resource | |
| 45 | - private MsgHandler msgHandler; | |
| 46 | - | |
| 47 | - @Bean | |
| 48 | - public WxMpMessageRouter messageRouter() { | |
| 49 | - final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); | |
| 50 | - // 记录所有事件的日志 (异步执行) | |
| 51 | - newRouter.rule().handler(logHandler).next(); | |
| 52 | - | |
| 53 | - // 接收客服会话管理事件 | |
| 54 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 55 | - .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) | |
| 56 | - .handler(kfSessionHandler).end(); | |
| 57 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 58 | - .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) | |
| 59 | - .handler(kfSessionHandler) | |
| 60 | - .end(); | |
| 61 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 62 | - .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) | |
| 63 | - .handler(kfSessionHandler).end(); | |
| 64 | - | |
| 65 | - // 门店审核事件 | |
| 66 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 67 | - .event(WxMpEventConstants.POI_CHECK_NOTIFY) | |
| 68 | - .handler(storeCheckNotifyHandler).end(); | |
| 69 | - | |
| 70 | - // 自定义菜单事件 | |
| 71 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 72 | - .event(WxConsts.MenuButtonType.CLICK).handler(menuHandler).end(); | |
| 73 | - | |
| 74 | - // 点击菜单连接事件 | |
| 75 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 76 | - .event(WxConsts.MenuButtonType.VIEW).handler(nullHandler).end(); | |
| 77 | - | |
| 78 | - // 关注事件 | |
| 79 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 80 | - .event(WxConsts.EventType.SUBSCRIBE).handler(subscribeHandler) | |
| 81 | - .end(); | |
| 82 | - | |
| 83 | - // 取消关注事件 | |
| 84 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 85 | - .event(WxConsts.EventType.UNSUBSCRIBE) | |
| 86 | - .handler(unsubscribeHandler).end(); | |
| 87 | - | |
| 88 | - // 上报地理位置事件 | |
| 89 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 90 | - .event(WxConsts.EventType.LOCATION).handler(locationHandler) | |
| 91 | - .end(); | |
| 92 | - | |
| 93 | - // 接收地理位置消息 | |
| 94 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION) | |
| 95 | - .handler(locationHandler).end(); | |
| 96 | - | |
| 97 | - // 扫码事件 | |
| 98 | - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) | |
| 99 | - .event(WxConsts.EventType.SCAN).handler(scanHandler).end(); | |
| 100 | - | |
| 101 | - // 默认 | |
| 102 | - newRouter.rule().async(false).handler(msgHandler).end(); | |
| 103 | - | |
| 104 | - return newRouter; | |
| 105 | - } | |
| 106 | -} |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/MpConfigRefreshConsumer.java
| 1 | 1 | package cn.iocoder.yudao.module.mp.mq.costomer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; |
| 4 | -import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage; | |
| 5 | -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; | |
| 4 | +import cn.iocoder.yudao.module.mp.mq.message.MpConfigRefreshMessage; | |
| 5 | +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | |
| 6 | 6 | import lombok.extern.slf4j.Slf4j; |
| 7 | 7 | import org.springframework.stereotype.Component; |
| 8 | 8 | |
| 9 | 9 | import javax.annotation.Resource; |
| 10 | 10 | |
| 11 | 11 | /** |
| 12 | - * 针对 {@link WxConfigDataRefreshMessage} 的消费者 | |
| 12 | + * 针对 {@link MpConfigRefreshMessage} 的消费者 | |
| 13 | 13 | * |
| 14 | 14 | * @author lyz |
| 15 | 15 | */ |
| 16 | 16 | @Component |
| 17 | 17 | @Slf4j |
| 18 | -public class WxConfigDataRefreshConsumer extends AbstractChannelMessageListener<WxConfigDataRefreshMessage> { | |
| 18 | +public class MpConfigRefreshConsumer extends AbstractChannelMessageListener<MpConfigRefreshMessage> { | |
| 19 | 19 | |
| 20 | 20 | @Resource |
| 21 | - private WxAccountService wxAccountService; | |
| 21 | + private MpAccountService wxAccountService; | |
| 22 | 22 | |
| 23 | 23 | @Override |
| 24 | - public void onMessage(WxConfigDataRefreshMessage message) { | |
| 25 | - log.info("[onMessage][收到 WxConfigData 刷新消息]"); | |
| 26 | - wxAccountService.initLoadWxMpConfigStorages(); | |
| 24 | + public void onMessage(MpConfigRefreshMessage message) { | |
| 25 | + log.info("[onMessage][收到 MpConfig 刷新消息]"); | |
| 26 | + wxAccountService.initLocalCache(); | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | } | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java renamed to 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; |
| 9 | 9 | */ |
| 10 | 10 | @Data |
| 11 | 11 | @EqualsAndHashCode(callSuper = true) |
| 12 | -public class WxConfigDataRefreshMessage extends AbstractChannelMessage { | |
| 12 | +public class MpConfigRefreshMessage extends AbstractChannelMessage { | |
| 13 | 13 | |
| 14 | 14 | @Override |
| 15 | 15 | public String getChannel() { |
| 16 | - return "wechat-mp.wx-config-data.refresh"; | |
| 16 | + return "mp.config-data.refresh"; | |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | } | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/MpConfigProducer.java
| 1 | 1 | package cn.iocoder.yudao.module.mp.mq.producer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; |
| 4 | -import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage; | |
| 4 | +import cn.iocoder.yudao.module.mp.mq.message.MpConfigRefreshMessage; | |
| 5 | 5 | import org.springframework.stereotype.Component; |
| 6 | 6 | |
| 7 | 7 | import javax.annotation.Resource; |
| ... | ... | @@ -10,16 +10,16 @@ import javax.annotation.Resource; |
| 10 | 10 | * 微信配置数据相关消息的 Producer |
| 11 | 11 | */ |
| 12 | 12 | @Component |
| 13 | -public class WxMpConfigDataProducer { | |
| 13 | +public class MpConfigProducer { | |
| 14 | 14 | |
| 15 | 15 | @Resource |
| 16 | 16 | private RedisMQTemplate redisMQTemplate; |
| 17 | 17 | |
| 18 | 18 | /** |
| 19 | - * 发送 {@link WxConfigDataRefreshMessage} 消息 | |
| 19 | + * 发送 {@link MpConfigRefreshMessage} 消息 | |
| 20 | 20 | */ |
| 21 | 21 | public void sendDictDataRefreshMessage() { |
| 22 | - WxConfigDataRefreshMessage message = new WxConfigDataRefreshMessage(); | |
| 22 | + MpConfigRefreshMessage message = new MpConfigRefreshMessage(); | |
| 23 | 23 | redisMQTemplate.send(message); |
| 24 | 24 | } |
| 25 | 25 | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java renamed to 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; |
| 14 | 14 | * |
| 15 | 15 | * @author 芋道源码 |
| 16 | 16 | */ |
| 17 | -public interface WxAccountService { | |
| 17 | +public interface MpAccountService { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 初始化缓存 | |
| 21 | + */ | |
| 22 | + void initLocalCache(); | |
| 18 | 23 | |
| 19 | 24 | /** |
| 20 | 25 | * 创建公众号账户 |
| ... | ... | @@ -64,8 +69,4 @@ public interface WxAccountService { |
| 64 | 69 | */ |
| 65 | 70 | MpAccountDO findBy(SFunction<MpAccountDO, ?> field, Object val); |
| 66 | 71 | |
| 67 | - /** | |
| 68 | - * 初始化 | |
| 69 | - */ | |
| 70 | - void initLoadWxMpConfigStorages(); | |
| 71 | 72 | } | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java
| ... | ... | @@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.mp.service.account; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 6 | +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | |
| 6 | 7 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; |
| 8 | 9 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO; |
| ... | ... | @@ -10,25 +11,20 @@ import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; |
| 10 | 11 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 11 | 12 | import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper; |
| 12 | 13 | import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants; |
| 13 | -import cn.iocoder.yudao.module.mp.mq.producer.WxMpConfigDataProducer; | |
| 14 | +import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory; | |
| 15 | +import cn.iocoder.yudao.module.mp.mq.producer.MpConfigProducer; | |
| 14 | 16 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; |
| 15 | -import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; | |
| 17 | +import lombok.Getter; | |
| 16 | 18 | import lombok.extern.slf4j.Slf4j; |
| 17 | -import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; | |
| 18 | -import me.chanjar.weixin.mp.api.WxMpService; | |
| 19 | -import me.chanjar.weixin.mp.config.WxMpConfigStorage; | |
| 20 | 19 | import org.springframework.context.annotation.Lazy; |
| 21 | -import org.springframework.data.redis.core.StringRedisTemplate; | |
| 22 | 20 | import org.springframework.scheduling.annotation.Scheduled; |
| 23 | 21 | import org.springframework.stereotype.Service; |
| 24 | -import org.springframework.util.CollectionUtils; | |
| 25 | 22 | import org.springframework.validation.annotation.Validated; |
| 26 | 23 | |
| 27 | 24 | import javax.annotation.PostConstruct; |
| 28 | 25 | import javax.annotation.Resource; |
| 29 | -import java.util.HashMap; | |
| 26 | +import java.time.LocalDateTime; | |
| 30 | 27 | import java.util.List; |
| 31 | -import java.util.Map; | |
| 32 | 28 | |
| 33 | 29 | |
| 34 | 30 | /** |
| ... | ... | @@ -39,33 +35,78 @@ import java.util.Map; |
| 39 | 35 | @Slf4j |
| 40 | 36 | @Service |
| 41 | 37 | @Validated |
| 42 | -public class WxAccountServiceImpl implements WxAccountService { | |
| 38 | +public class MpAccountServiceImpl implements MpAccountService { | |
| 43 | 39 | |
| 40 | + /** | |
| 41 | + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | |
| 42 | + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | |
| 43 | + */ | |
| 44 | 44 | private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; |
| 45 | 45 | |
| 46 | + /** | |
| 47 | + * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 | |
| 48 | + */ | |
| 49 | + @Getter | |
| 50 | + private volatile LocalDateTime maxUpdateTime; | |
| 51 | + | |
| 46 | 52 | @Resource |
| 47 | - private MpAccountMapper wxAccountMapper; | |
| 48 | - @Resource | |
| 49 | - private WxMpConfigDataProducer wxMpConfigDataProducer; | |
| 50 | - @Resource | |
| 51 | - private StringRedisTemplate stringRedisTemplate; | |
| 52 | - @Resource | |
| 53 | - private WxMpService wxMpService; | |
| 53 | + private MpAccountMapper mpAccountMapper; | |
| 54 | + | |
| 54 | 55 | @Resource |
| 55 | - private WxMpProperties wxMpProperties; | |
| 56 | + @Lazy // 延迟加载,解决循环依赖的问题 | |
| 57 | + private MpServiceFactory mpServiceFactory; | |
| 58 | + | |
| 56 | 59 | @Resource |
| 57 | - @Lazy // 注入自己,所以延迟加载 | |
| 58 | - private WxAccountService self; | |
| 60 | + private MpConfigProducer mpConfigDataProducer; | |
| 61 | + | |
| 62 | + @Override | |
| 63 | + @PostConstruct | |
| 64 | + public void initLocalCache() { | |
| 65 | + initLocalCacheIfUpdate(null); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | |
| 69 | + public void schedulePeriodicRefresh() { | |
| 70 | + initLocalCacheIfUpdate(this.maxUpdateTime); | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 刷新本地缓存 | |
| 75 | + * | |
| 76 | + * @param maxUpdateTime 最大更新时间 | |
| 77 | + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | |
| 78 | + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | |
| 79 | + */ | |
| 80 | + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | |
| 81 | + // 注意:忽略自动多租户,因为要全局初始化缓存 | |
| 82 | + TenantUtils.executeIgnore(() -> { | |
| 83 | + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | |
| 84 | + // 如果没有增量的数据变化,则不进行本地缓存的刷新 | |
| 85 | + if (maxUpdateTime != null | |
| 86 | + && mpAccountMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | |
| 87 | + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | |
| 88 | + return; | |
| 89 | + } | |
| 90 | + List<MpAccountDO> accounts = mpAccountMapper.selectList(); | |
| 91 | + log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size()); | |
| 92 | + | |
| 93 | + // 第二步:构建缓存。创建或更新支付 Client | |
| 94 | + mpServiceFactory.init(accounts); | |
| 95 | + | |
| 96 | + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | |
| 97 | + this.maxUpdateTime = CollectionUtils.getMaxValue(accounts, MpAccountDO::getUpdateTime); | |
| 98 | + }); | |
| 99 | + } | |
| 59 | 100 | |
| 60 | 101 | @Override |
| 61 | 102 | public Long createAccount(MpAccountCreateReqVO createReqVO) { |
| 62 | 103 | // TODO 芋艿:校验唯一性 |
| 63 | 104 | // 插入 |
| 64 | 105 | MpAccountDO wxAccount = MpAccountConvert.INSTANCE.convert(createReqVO); |
| 65 | - wxAccountMapper.insert(wxAccount); | |
| 106 | + mpAccountMapper.insert(wxAccount); | |
| 66 | 107 | |
| 67 | 108 | // TODO 芋艿:刷新的方式 |
| 68 | - wxMpConfigDataProducer.sendDictDataRefreshMessage(); | |
| 109 | + mpConfigDataProducer.sendDictDataRefreshMessage(); | |
| 69 | 110 | // 返回 |
| 70 | 111 | return wxAccount.getId(); |
| 71 | 112 | } |
| ... | ... | @@ -77,10 +118,10 @@ public class WxAccountServiceImpl implements WxAccountService { |
| 77 | 118 | validateWxAccountExists(updateReqVO.getId()); |
| 78 | 119 | // 更新 |
| 79 | 120 | MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO); |
| 80 | - wxAccountMapper.updateById(updateObj); | |
| 121 | + mpAccountMapper.updateById(updateObj); | |
| 81 | 122 | |
| 82 | 123 | // TODO 芋艿:刷新的方式 |
| 83 | - wxMpConfigDataProducer.sendDictDataRefreshMessage(); | |
| 124 | + mpConfigDataProducer.sendDictDataRefreshMessage(); | |
| 84 | 125 | } |
| 85 | 126 | |
| 86 | 127 | @Override |
| ... | ... | @@ -88,70 +129,31 @@ public class WxAccountServiceImpl implements WxAccountService { |
| 88 | 129 | // 校验存在 |
| 89 | 130 | validateWxAccountExists(id); |
| 90 | 131 | // 删除 |
| 91 | - wxAccountMapper.deleteById(id); | |
| 132 | + mpAccountMapper.deleteById(id); | |
| 92 | 133 | |
| 93 | 134 | // TODO 芋艿:刷新的方式 |
| 94 | - wxMpConfigDataProducer.sendDictDataRefreshMessage(); | |
| 135 | + mpConfigDataProducer.sendDictDataRefreshMessage(); | |
| 95 | 136 | } |
| 96 | 137 | |
| 97 | 138 | private void validateWxAccountExists(Long id) { |
| 98 | - if (wxAccountMapper.selectById(id) == null) { | |
| 139 | + if (mpAccountMapper.selectById(id) == null) { | |
| 99 | 140 | throw ServiceExceptionUtil.exception(ErrorCodeConstants.WX_ACCOUNT_NOT_EXISTS); |
| 100 | 141 | } |
| 101 | 142 | } |
| 102 | 143 | |
| 103 | 144 | @Override |
| 104 | 145 | public MpAccountDO getAccount(Long id) { |
| 105 | - return wxAccountMapper.selectById(id); | |
| 146 | + return mpAccountMapper.selectById(id); | |
| 106 | 147 | } |
| 107 | 148 | |
| 108 | 149 | @Override |
| 109 | 150 | public PageResult<MpAccountDO> getAccountPage(MpAccountPageReqVO pageReqVO) { |
| 110 | - return wxAccountMapper.selectPage(pageReqVO); | |
| 151 | + return mpAccountMapper.selectPage(pageReqVO); | |
| 111 | 152 | } |
| 112 | 153 | |
| 113 | 154 | @Override |
| 114 | 155 | public MpAccountDO findBy(SFunction<MpAccountDO, ?> field, Object val) { |
| 115 | - return wxAccountMapper.selectOne(field, val); | |
| 116 | - } | |
| 117 | - | |
| 118 | - @PostConstruct | |
| 119 | - @TenantIgnore | |
| 120 | - @Override | |
| 121 | - public void initLoadWxMpConfigStorages() { | |
| 122 | - // TODO 芋艿:刷新的方式 | |
| 123 | - List<MpAccountDO> wxAccountList = this.wxAccountMapper.selectList(); | |
| 124 | - if (CollectionUtils.isEmpty(wxAccountList)) { | |
| 125 | - log.info("未读取到公众号配置,请在管理后台添加"); | |
| 126 | - return; | |
| 127 | - } | |
| 128 | - log.info("加载到{}条公众号配置", wxAccountList.size()); | |
| 129 | - wxAccountList.forEach(account -> addAccountToRuntime(account, new RedisTemplateWxRedisOps(stringRedisTemplate))); | |
| 130 | - log.info("公众号配置加载完成"); | |
| 131 | - } | |
| 132 | - | |
| 133 | - /** | |
| 134 | - * 添加账号到当前程序,如首次添加需初始化configStorageMap | |
| 135 | - * | |
| 136 | - * @param account 公众号 | |
| 137 | - */ | |
| 138 | - private synchronized void addAccountToRuntime(MpAccountDO account, RedisTemplateWxRedisOps redisOps) { | |
| 139 | - String appId = account.getAppId(); | |
| 140 | - WxMpConfigStorage wxMpRedisConfig = account.toWxMpConfigStorage(redisOps, wxMpProperties); | |
| 141 | - try { | |
| 142 | - wxMpService.addConfigStorage(appId, wxMpRedisConfig); | |
| 143 | - } catch (NullPointerException e) { | |
| 144 | - log.info("需初始化configStorageMap..."); | |
| 145 | - Map<String, WxMpConfigStorage> configStorages = new HashMap<>(4); | |
| 146 | - configStorages.put(appId, wxMpRedisConfig); | |
| 147 | - wxMpService.setMultiConfigStorages(configStorages, appId); | |
| 148 | - } | |
| 156 | + return mpAccountMapper.selectOne(field, val); | |
| 149 | 157 | } |
| 150 | 158 | |
| 151 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | |
| 152 | - public void schedulePeriodicRefresh() { | |
| 153 | - self.initLoadWxMpConfigStorages(); | |
| 154 | - } | |
| 155 | - | |
| 156 | - | |
| 157 | 159 | } | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/NullHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/fansmsgres/NullHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.fansmsgres; | |
| 2 | 2 | |
| 3 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; |
| 4 | 4 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; |
| ... | ... | @@ -9,13 +9,15 @@ import org.springframework.stereotype.Component; |
| 9 | 9 | |
| 10 | 10 | import java.util.Map; |
| 11 | 11 | |
| 12 | +/** | |
| 13 | + * 点击菜单连接的事件处理器 | |
| 14 | + */ | |
| 12 | 15 | @Component |
| 13 | 16 | public class NullHandler implements WxMpMessageHandler { |
| 14 | 17 | |
| 15 | 18 | @Override |
| 16 | - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |
| 17 | - Map<String, Object> context, WxMpService wxMpService, | |
| 18 | - WxSessionManager sessionManager) { | |
| 19 | + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, | |
| 20 | + WxMpService wxMpService, WxSessionManager sessionManager) { | |
| 19 | 21 | return null; |
| 20 | 22 | } |
| 21 | 23 | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/DefaultMessageHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.io.FileUtil; |
| 4 | 4 | import cn.hutool.http.HtmlUtil; |
| ... | ... | @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi; |
| 8 | 8 | import cn.iocoder.yudao.module.mp.builder.TextBuilder; |
| 9 | 9 | import cn.iocoder.yudao.module.mp.controller.admin.fansmsg.vo.WxFansMsgCreateReqVO; |
| 10 | 10 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 11 | -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; | |
| 11 | +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | |
| 12 | 12 | import cn.iocoder.yudao.module.mp.service.fansmsg.WxFansMsgService; |
| 13 | 13 | import lombok.extern.slf4j.Slf4j; |
| 14 | 14 | import me.chanjar.weixin.common.api.WxConsts; |
| ... | ... | @@ -21,6 +21,7 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; |
| 21 | 21 | import me.chanjar.weixin.mp.bean.result.WxMpUser; |
| 22 | 22 | import org.apache.commons.lang3.StringUtils; |
| 23 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
| 24 | +import org.springframework.context.annotation.Lazy; | |
| 24 | 25 | import org.springframework.stereotype.Component; |
| 25 | 26 | |
| 26 | 27 | import javax.annotation.Resource; |
| ... | ... | @@ -28,11 +29,18 @@ import java.io.File; |
| 28 | 29 | import java.io.UnsupportedEncodingException; |
| 29 | 30 | import java.util.Map; |
| 30 | 31 | |
| 32 | +/** | |
| 33 | + * 默认所有消息的事件处理器 | |
| 34 | + * | |
| 35 | + * // TODO 芋艿:待实现 | |
| 36 | + */ | |
| 31 | 37 | @Component |
| 32 | 38 | @Slf4j |
| 33 | -public class MsgHandler implements WxMpMessageHandler { | |
| 34 | - @Autowired | |
| 35 | - private WxAccountService wxAccountService; | |
| 39 | +public class DefaultMessageHandler implements WxMpMessageHandler { | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + @Lazy // 延迟加载,解决循环依赖的问题 | |
| 43 | + private MpAccountService mpAccountService; | |
| 36 | 44 | |
| 37 | 45 | @Autowired |
| 38 | 46 | private WxFansMsgService wxFansMsgService; |
| ... | ... | @@ -55,7 +63,7 @@ public class MsgHandler implements WxMpMessageHandler { |
| 55 | 63 | WxMpUser wxmpUser = weixinService.getUserService() |
| 56 | 64 | .userInfo(wxMessage.getFromUser(), null); |
| 57 | 65 | if (wxmpUser != null) { |
| 58 | - MpAccountDO wxAccount = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 66 | + MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 59 | 67 | if (wxAccount != null) { |
| 60 | 68 | |
| 61 | 69 | if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.TEXT)) { | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/KfSessionHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/KfSessionHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; |
| 4 | 4 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; |
| ... | ... | @@ -9,14 +9,18 @@ import org.springframework.stereotype.Component; |
| 9 | 9 | |
| 10 | 10 | import java.util.Map; |
| 11 | 11 | |
| 12 | +/** | |
| 13 | + * 接收客服会话管理的事件处理器 | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 12 | 17 | @Component |
| 13 | 18 | public class KfSessionHandler implements WxMpMessageHandler { |
| 14 | 19 | |
| 15 | 20 | @Override |
| 16 | - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |
| 17 | - Map<String, Object> context, WxMpService wxMpService, | |
| 18 | - WxSessionManager sessionManager) { | |
| 19 | - //TODO 对会话做处理 | |
| 21 | + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, | |
| 22 | + WxMpService wxMpService, WxSessionManager sessionManager) { | |
| 23 | + // TODO 对会话做处理 | |
| 20 | 24 | return null; |
| 21 | 25 | } |
| 22 | 26 | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LocationHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LocationHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.mp.builder.TextBuilder; |
| 4 | 4 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -13,14 +13,18 @@ import java.util.Map; |
| 13 | 13 | |
| 14 | 14 | import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; |
| 15 | 15 | |
| 16 | +/** | |
| 17 | + * 上报地理位置的事件处理器 | |
| 18 | + * | |
| 19 | + * // TODO @芋艿:需要实现一下~ | |
| 20 | + */ | |
| 16 | 21 | @Component |
| 17 | 22 | @Slf4j |
| 18 | 23 | public class LocationHandler implements WxMpMessageHandler { |
| 19 | 24 | |
| 20 | 25 | @Override |
| 21 | - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |
| 22 | - Map<String, Object> context, WxMpService wxMpService, | |
| 23 | - WxSessionManager sessionManager) { | |
| 26 | + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, | |
| 27 | + WxMpService wxMpService, WxSessionManager sessionManager) { | |
| 24 | 28 | if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { |
| 25 | 29 | //TODO 接收处理用户发送的地理位置消息 |
| 26 | 30 | try { | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/LogHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/LogHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 4 | 4 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -11,13 +11,18 @@ import org.springframework.stereotype.Component; |
| 11 | 11 | |
| 12 | 12 | import java.util.Map; |
| 13 | 13 | |
| 14 | +/** | |
| 15 | + * 保存微信消息的事件处理器 | |
| 16 | + * | |
| 17 | + * // TODO 芋艿:实现一下 | |
| 18 | + */ | |
| 14 | 19 | @Component |
| 15 | 20 | @Slf4j |
| 16 | 21 | public class LogHandler implements WxMpMessageHandler { |
| 22 | + | |
| 17 | 23 | @Override |
| 18 | - public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |
| 19 | - Map<String, Object> context, WxMpService wxMpService, | |
| 20 | - WxSessionManager sessionManager) { | |
| 24 | + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, | |
| 25 | + WxMpService wxMpService, WxSessionManager sessionManager) { | |
| 21 | 26 | log.info("接收到请求消息,内容:{}", JsonUtils.toJsonString(wxMessage)); |
| 22 | 27 | return null; |
| 23 | 28 | } | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MenuHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/MenuHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; |
| 4 | 4 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; |
| ... | ... | @@ -11,6 +11,11 @@ import java.util.Map; |
| 11 | 11 | |
| 12 | 12 | import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; |
| 13 | 13 | |
| 14 | +/** | |
| 15 | + * 自定义菜单的事件处理器 | |
| 16 | + * | |
| 17 | + * // TODO 芋艿:待实现 | |
| 18 | + */ | |
| 14 | 19 | @Component |
| 15 | 20 | public class MenuHandler implements WxMpMessageHandler { |
| 16 | 21 | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/ScanHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/ScanHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import me.chanjar.weixin.common.error.WxErrorException; |
| 4 | 4 | import me.chanjar.weixin.common.session.WxSessionManager; |
| ... | ... | @@ -10,6 +10,9 @@ import org.springframework.stereotype.Component; |
| 10 | 10 | |
| 11 | 11 | import java.util.Map; |
| 12 | 12 | |
| 13 | +/** | |
| 14 | + * 扫码的事件处理器 | |
| 15 | + */ | |
| 13 | 16 | @Component |
| 14 | 17 | public class ScanHandler implements WxMpMessageHandler { |
| 15 | 18 | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/StoreCheckNotifyHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/StoreCheckNotifyHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; |
| 4 | 4 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; |
| ... | ... | @@ -10,8 +10,7 @@ import org.springframework.stereotype.Component; |
| 10 | 10 | import java.util.Map; |
| 11 | 11 | |
| 12 | 12 | /** |
| 13 | - * 门店审核事件处理 | |
| 14 | - * | |
| 13 | + * 门店审核事件的事件处理器 | |
| 15 | 14 | */ |
| 16 | 15 | @Component |
| 17 | 16 | public class StoreCheckNotifyHandler implements WxMpMessageHandler { | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/SubscribeHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/SubscribeHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.date.DateUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| ... | ... | @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 9 | 9 | import cn.iocoder.yudao.module.mp.dal.dataobject.accountfans.WxAccountFansDO; |
| 10 | 10 | import cn.iocoder.yudao.module.mp.dal.dataobject.subscribetext.WxSubscribeTextDO; |
| 11 | 11 | import cn.iocoder.yudao.module.mp.dal.dataobject.texttemplate.WxTextTemplateDO; |
| 12 | -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; | |
| 12 | +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | |
| 13 | 13 | import cn.iocoder.yudao.module.mp.service.accountfans.WxAccountFansService; |
| 14 | 14 | import cn.iocoder.yudao.module.mp.service.accountfanstag.WxAccountFansTagService; |
| 15 | 15 | import cn.iocoder.yudao.module.mp.service.subscribetext.WxSubscribeTextService; |
| ... | ... | @@ -23,11 +23,18 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; |
| 23 | 23 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; |
| 24 | 24 | import me.chanjar.weixin.mp.bean.result.WxMpUser; |
| 25 | 25 | import org.springframework.beans.factory.annotation.Autowired; |
| 26 | +import org.springframework.context.annotation.Lazy; | |
| 26 | 27 | import org.springframework.stereotype.Component; |
| 27 | 28 | |
| 29 | +import javax.annotation.Resource; | |
| 28 | 30 | import java.io.UnsupportedEncodingException; |
| 29 | 31 | import java.util.Map; |
| 30 | 32 | |
| 33 | +/** | |
| 34 | + * 关注的事件处理器 | |
| 35 | + * | |
| 36 | + * // TODO 芋艿:待实现 | |
| 37 | + */ | |
| 31 | 38 | @Component |
| 32 | 39 | @Slf4j |
| 33 | 40 | public class SubscribeHandler implements WxMpMessageHandler { |
| ... | ... | @@ -35,8 +42,9 @@ public class SubscribeHandler implements WxMpMessageHandler { |
| 35 | 42 | @Autowired |
| 36 | 43 | private WxTextTemplateService wxTextTemplateService; |
| 37 | 44 | |
| 38 | - @Autowired | |
| 39 | - private WxAccountService wxAccountService; | |
| 45 | + @Resource | |
| 46 | + @Lazy // 延迟加载,解决循环依赖的问题 | |
| 47 | + private MpAccountService mpAccountService; | |
| 40 | 48 | |
| 41 | 49 | @Autowired |
| 42 | 50 | private WxSubscribeTextService wxSubscribeTextService; |
| ... | ... | @@ -60,7 +68,7 @@ public class SubscribeHandler implements WxMpMessageHandler { |
| 60 | 68 | .userInfo(wxMessage.getFromUser(), null); |
| 61 | 69 | if (wxmpUser != null) { |
| 62 | 70 | // 可以添加关注用户到本地数据库 |
| 63 | - MpAccountDO wxAccount = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 71 | + MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 64 | 72 | if (wxAccount != null) { |
| 65 | 73 | WxAccountFansDO wxAccountFans = wxAccountFansService.findBy(WxAccountFansDO::getOpenid, wxmpUser.getOpenId()); |
| 66 | 74 | if (wxAccountFans == null) {//insert |
| ... | ... | @@ -128,7 +136,7 @@ public class SubscribeHandler implements WxMpMessageHandler { |
| 128 | 136 | |
| 129 | 137 | try { |
| 130 | 138 | String content = "感谢关注!";//默认 |
| 131 | - MpAccountDO wxAccount = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 139 | + MpAccountDO wxAccount = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 132 | 140 | if (wxAccount != null) { |
| 133 | 141 | WxSubscribeTextDO wxSubscribeText = wxSubscribeTextService.findBy(WxSubscribeTextDO::getWxAccountId, String.valueOf(wxAccount.getId())); |
| 134 | 142 | if (wxSubscribeText != null) { | ... | ... |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/UnsubscribeHandler.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/UnsubscribeHandler.java
| 1 | -package cn.iocoder.yudao.module.mp.handler; | |
| 1 | +package cn.iocoder.yudao.module.mp.service.handler; | |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.mp.controller.admin.accountfans.vo.WxAccountFansUpdateReqVO; |
| 4 | 4 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 5 | 5 | import cn.iocoder.yudao.module.mp.dal.dataobject.accountfans.WxAccountFansDO; |
| 6 | -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; | |
| 6 | +import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | |
| 7 | 7 | import cn.iocoder.yudao.module.mp.service.accountfans.WxAccountFansService; |
| 8 | 8 | import lombok.extern.slf4j.Slf4j; |
| 9 | 9 | import me.chanjar.weixin.common.session.WxSessionManager; |
| ... | ... | @@ -12,16 +12,24 @@ import me.chanjar.weixin.mp.api.WxMpService; |
| 12 | 12 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; |
| 13 | 13 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; |
| 14 | 14 | import org.springframework.beans.factory.annotation.Autowired; |
| 15 | +import org.springframework.context.annotation.Lazy; | |
| 15 | 16 | import org.springframework.stereotype.Component; |
| 16 | 17 | |
| 18 | +import javax.annotation.Resource; | |
| 17 | 19 | import java.util.Map; |
| 18 | 20 | |
| 21 | +/** | |
| 22 | + * 取消关注的事件处理器 | |
| 23 | + * | |
| 24 | + * // TODO 芋艿:待实现 | |
| 25 | + */ | |
| 19 | 26 | @Component |
| 20 | 27 | @Slf4j |
| 21 | 28 | public class UnsubscribeHandler implements WxMpMessageHandler { |
| 22 | 29 | |
| 23 | - @Autowired | |
| 24 | - private WxAccountService wxAccountService; | |
| 30 | + @Resource | |
| 31 | + @Lazy // 延迟加载,解决循环依赖的问题 | |
| 32 | + private MpAccountService mpAccountService; | |
| 25 | 33 | |
| 26 | 34 | @Autowired |
| 27 | 35 | private WxAccountFansService wxAccountFansService; |
| ... | ... | @@ -34,7 +42,7 @@ public class UnsubscribeHandler implements WxMpMessageHandler { |
| 34 | 42 | log.info("取消关注用户 OPENID: " + openId); |
| 35 | 43 | // TODO 可以更新本地数据库为取消关注状态 |
| 36 | 44 | |
| 37 | - MpAccountDO wxAccountDO = wxAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 45 | + MpAccountDO wxAccountDO = mpAccountService.findBy(MpAccountDO::getAccount, wxMessage.getToUser()); | |
| 38 | 46 | if (wxAccountDO != null) { |
| 39 | 47 | WxAccountFansDO wxAccountFansDO = wxAccountFansService.findBy(WxAccountFansDO::getOpenid, openId); |
| 40 | 48 | if (wxAccountFansDO != null) { | ... | ... |