diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java index 71b768c60..458e5334a 100644 --- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java +++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java @@ -33,66 +33,131 @@ import java.util.stream.Collectors; import static me.chanjar.weixin.common.api.WxConsts.*; /** + * 微信公众号初始化配置类 + *
+ * 功能说明: + * 1. 应用启动时自动加载所有租户的微信公众号配置 + * 2. 为每个公众号创建独立的 WxMpService 和消息路由器 + * 3. 监听 Redis 消息,支持运行时动态重新加载配置 + *
+ * 核心数据结构: + * - routers: appid -> WxMpMessageRouter 映射,用于消息路由分发 + * - mpServices: appid -> WxMpService 映射,用于调用微信API + * - tenants: appid -> tenantId 映射,用于多租户隔离 + * * @author Binary Wang * @author lengleng - *
- * 微信公众号基础配置,初始化配置
*/
@Slf4j
@Configuration
@RequiredArgsConstructor
public class WxMpInitConfigRunner {
- /**
- * 保存 appid-router 的对应关系
- */
- private static Map
+ * 执行流程:
+ * 1. 获取系统中所有租户
+ * 2. 遍历每个租户,查询其配置的公众号列表
+ * 3. 为每个公众号创建 WxMpService 和消息路由器
+ * 4. 缓存 appid 与租户的映射关系
+ */
+ public void initServices() {
+ // 获取全部租户 遍历所有租户对应的公众号列表
+ List
+ * 配置消息路由规则,将不同类型的消息/事件分发到对应的处理器:
+ * - 客服会话事件 -> kfSessionHandler
+ * - 门店审核事件 -> storeCheckNotifyHandler
+ * - 菜单点击事件 -> menuHandler
+ * - 关注/取消关注事件 -> subscribeHandler/unsubscribeHandler
+ * - 地理位置事件 -> locationHandler
+ * - 扫码事件 -> scanHandler
+ * - 其他消息 -> msgHandler(默认处理器)
+ *
+ * @param wxMpService 微信公众号服务实例
+ * @return 配置完成的消息路由器
+ */
+ private WxMpMessageRouter newRouter(WxMpService wxMpService) {
+ final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
- // 记录所有事件的日志 (异步执行) #5637 大数据量瓶颈
- newRouter.rule().handler(this.logHandler).next();
+ // 记录所有事件的日志 (异步执行) #5637 大数据量瓶颈
+ newRouter.rule().handler(this.logHandler).next();
- // 接收客服会话管理事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
- .handler(this.kfSessionHandler)
- .end();
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
- .handler(this.kfSessionHandler)
- .end();
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
- .handler(this.kfSessionHandler)
- .end();
+ // 接收客服会话管理事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
+ .handler(this.kfSessionHandler)
+ .end();
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
+ .handler(this.kfSessionHandler)
+ .end();
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
+ .handler(this.kfSessionHandler)
+ .end();
- // 门店审核事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(WxMpEventConstants.POI_CHECK_NOTIFY)
- .handler(this.storeCheckNotifyHandler)
- .end();
+ // 门店审核事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.POI_CHECK_NOTIFY)
+ .handler(this.storeCheckNotifyHandler)
+ .end();
- // 自定义菜单事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(MenuButtonType.CLICK)
- .handler(this.menuHandler)
- .end();
+ // 自定义菜单事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(MenuButtonType.CLICK)
+ .handler(this.menuHandler)
+ .end();
- // 点击菜单连接事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(MenuButtonType.VIEW)
- .handler(this.nullHandler)
- .end();
+ // 点击菜单连接事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(MenuButtonType.VIEW)
+ .handler(this.nullHandler)
+ .end();
- // 关注事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(EventType.SUBSCRIBE)
- .handler(this.subscribeHandler)
- .end();
+ // 关注事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(EventType.SUBSCRIBE)
+ .handler(this.subscribeHandler)
+ .end();
- // 取消关注事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(EventType.UNSUBSCRIBE)
- .handler(this.unsubscribeHandler)
- .end();
+ // 取消关注事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(EventType.UNSUBSCRIBE)
+ .handler(this.unsubscribeHandler)
+ .end();
- // 上报地理位置事件
- newRouter.rule()
- .async(false)
- .msgType(XmlMsgType.EVENT)
- .event(EventType.LOCATION)
- .handler(this.locationHandler)
- .end();
+ // 上报地理位置事件
+ newRouter.rule()
+ .async(false)
+ .msgType(XmlMsgType.EVENT)
+ .event(EventType.LOCATION)
+ .handler(this.locationHandler)
+ .end();
- // 接收地理位置消息
- newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();
+ // 接收地理位置消息
+ newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();
- // 扫码事件
- newRouter.rule().async(false).msgType(XmlMsgType.EVENT).event(EventType.SCAN).handler(this.scanHandler).end();
+ // 扫码事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT).event(EventType.SCAN).handler(this.scanHandler).end();
- // 默认
- newRouter.rule().async(false).handler(this.msgHandler).end();
+ // 默认
+ newRouter.rule().async(false).handler(this.msgHandler).end();
- return newRouter;
- }
+ return newRouter;
+ }
- /**
- * redis 监听配置,监听 mp_redis_reload_topic,重新加载配置
- * @param redisConnectionFactory redis 配置
- * @return
- */
- @Bean
- public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory) {
- RedisMessageListenerContainer container = new RedisMessageListenerContainer();
- container.setConnectionFactory(redisConnectionFactory);
- container.addMessageListener((message, bytes) -> {
- log.warn("接收到重新加载公众号配置事件");
- initServices();
- }, new ChannelTopic(CacheConstants.MP_REDIS_RELOAD_TOPIC));
- return container;
- }
+ /**
+ * 配置 Redis 消息监听容器
+ *
+ * 监听 mp_redis_reload_topic 频道,当收到消息时重新加载公众号配置
+ * 适用场景:后台修改公众号配置后,通过发布 Redis 消息触发配置热更新
+ *
+ * @param redisConnectionFactory Redis 连接工厂
+ * @return Redis 消息监听容器
+ */
+ @Bean
+ public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory) {
+ RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+ container.setConnectionFactory(redisConnectionFactory);
+ container.addMessageListener((message, bytes) -> {
+ log.warn("接收到重新加载公众号配置事件");
+ initServices();
+ }, new ChannelTopic(CacheConstants.MP_REDIS_RELOAD_TOPIC));
+ return container;
+ }
- public static Map