diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpConfig.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpConfig.java deleted file mode 100644 index b5dfd8ad6..000000000 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpConfig.java +++ /dev/null @@ -1,145 +0,0 @@ -package cn.iocoder.yudao.module.mp.config; - - -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountExportReqVO; -import cn.iocoder.yudao.module.mp.dal.dataobject.account.WxAccountDO; -import cn.iocoder.yudao.module.mp.handler.*; -import cn.iocoder.yudao.module.mp.service.account.WxAccountService; -import com.google.common.collect.Maps; -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.api.impl.WxMpServiceImpl; -import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; -import me.chanjar.weixin.mp.constant.WxMpEventConstants; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.util.CollectionUtils; - -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -// TODO @芋艿:思考有没更好的处理方式 -@Slf4j -@Configuration -public class WxMpConfig { - - private static Map routers = Maps.newHashMap(); - private static Map mpServices = Maps.newHashMap(); - - @Resource - private WxAccountService wxAccountService; - - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; - - /** - * 初始化公众号配置 - */ - @PostConstruct - public synchronized void initWxConfig() { - WxAccountExportReqVO req = new WxAccountExportReqVO(); - List wxAccountList = wxAccountService.getWxAccountList(req); - if (CollectionUtils.isEmpty(wxAccountList)) { - return; - } - WxMpConfig.init(wxAccountList); - log.info("加载公众号配置成功"); - } - - - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - initWxConfig(); - } - - public static void init(List wxAccountDOS) { - mpServices = wxAccountDOS.stream().map(wxAccountDO -> { - // TODO 亚洲:使用 WxMpInMemoryConfigStorage 的话,多节点会不会存在 accessToken 冲突 - - WxMpDefaultConfigImpl configStorage; - configStorage = new WxMpDefaultConfigImpl(); - - configStorage.setAppId(wxAccountDO.getAppId()); - configStorage.setSecret(wxAccountDO.getAppSecret()); - configStorage.setToken(wxAccountDO.getToken()); - configStorage.setAesKey(wxAccountDO.getAesKey()); - - WxMpService service = new WxMpServiceImpl(); - service.setWxMpConfigStorage(configStorage); - routers.put(wxAccountDO.getAppId(), newRouter(service)); - return service; - }).collect(Collectors.toMap(s -> s.getWxMpConfigStorage().getAppId(), a -> a, (o, n) -> o)); - } - - public static Map getRouters() { - return routers; - } - - public static Map getMpServices() { - return mpServices; - } - - private static WxMpMessageRouter newRouter(WxMpService wxMpService) { - final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); - // 记录所有事件的日志 (异步执行) - newRouter.rule().handler(SpringUtil.getBean(LogHandler.class)).next(); - - // 接收客服会话管理事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) - .handler(SpringUtil.getBean(KfSessionHandler.class)).end(); - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) - .handler(SpringUtil.getBean(KfSessionHandler.class)) - .end(); - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) - .handler(SpringUtil.getBean(KfSessionHandler.class)).end(); - - // 门店审核事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxMpEventConstants.POI_CHECK_NOTIFY) - .handler(SpringUtil.getBean(StoreCheckNotifyHandler.class)).end(); - - // 自定义菜单事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.MenuButtonType.CLICK).handler(SpringUtil.getBean(MenuHandler.class)).end(); - - // 点击菜单连接事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.MenuButtonType.VIEW).handler(SpringUtil.getBean(NullHandler.class)).end(); - - // 关注事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.SUBSCRIBE).handler(SpringUtil.getBean(SubscribeHandler.class)) - .end(); - - // 取消关注事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.UNSUBSCRIBE) - .handler(SpringUtil.getBean(UnsubscribeHandler.class)).end(); - - // 上报地理位置事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.LOCATION).handler(SpringUtil.getBean(LocationHandler.class)) - .end(); - - // 接收地理位置消息 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION) - .handler(SpringUtil.getBean(LocationHandler.class)).end(); - - // 扫码事件 - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxConsts.EventType.SCAN).handler(SpringUtil.getBean(ScanHandler.class)).end(); - - // 默认 - newRouter.rule().async(false).handler(SpringUtil.getBean(MsgHandler.class)).end(); - - return newRouter; - } -} diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpProperties.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpProperties.java deleted file mode 100644 index 1867e3578..000000000 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpProperties.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.mp.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * wechat mp properties - */ -@Data -//@ConfigurationProperties(prefix = "wx.mp") -public class WxMpProperties { - /** - * 是否使用redis存储access token - */ - private boolean useRedis; - - private String defaultContent; - - /** - * redis 配置 - */ - private RedisConfig redisConfig; - - @Data - public static class RedisConfig { - /** - * redis服务器 主机地址 - */ - private String host; - - /** - * redis服务器 端口号 - */ - private Integer port; - - /** - * redis服务器 密码 - */ - private String password; - - /** - * redis 服务连接超时时间 - */ - private Integer timeout; - } - -} diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/WxAccountDO.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/WxAccountDO.java index 9e8764cf0..2507c4691 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/WxAccountDO.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/WxAccountDO.java @@ -4,7 +4,11 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; import lombok.*; +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; +import me.chanjar.weixin.mp.config.WxMpConfigStorage; +import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; // TODO 亚洲:这个模块的相关类,使用 Mp 作为前缀哈 /** @@ -64,4 +68,12 @@ public class WxAccountDO extends BaseDO { */ private String remark; + 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-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java new file mode 100644 index 000000000..3fc8d3705 --- /dev/null +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java @@ -0,0 +1,106 @@ +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-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java index b889cc7ec..c7a73b51f 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/handler/MsgHandler.java @@ -6,13 +6,10 @@ import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.mp.builder.TextBuilder; -import cn.iocoder.yudao.module.mp.config.WxMpProperties; import cn.iocoder.yudao.module.mp.controller.admin.fansmsg.vo.WxFansMsgCreateReqVO; import cn.iocoder.yudao.module.mp.dal.dataobject.account.WxAccountDO; import cn.iocoder.yudao.module.mp.service.account.WxAccountService; import cn.iocoder.yudao.module.mp.service.fansmsg.WxFansMsgService; -import cn.iocoder.yudao.module.mp.service.receivetext.WxReceiveTextService; -import cn.iocoder.yudao.module.mp.service.texttemplate.WxTextTemplateService; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.error.WxErrorException; @@ -102,7 +99,7 @@ public class MsgHandler implements WxMpMessageHandler { if (!downloadDir.exists()) { downloadDir.mkdirs(); } - String filepath = downloadDirStr + String.valueOf(System.currentTimeMillis()) + ".png"; + String filepath = downloadDirStr + System.currentTimeMillis() + ".png"; //微信pic url下载到本地,防止失效 long size = HttpUtil.downloadFile(wxMessage.getPicUrl(), FileUtil.file(filepath)); log.info("download pic size : {}", size); diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java index a9355fe26..2f0863b60 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.module.mp.mq.costomer.dict; +package cn.iocoder.yudao.module.mp.mq.costomer; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.module.mp.config.WxMpConfig; -import cn.iocoder.yudao.module.mp.mq.message.dict.WxConfigDataRefreshMessage; +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; @@ -18,12 +18,12 @@ import javax.annotation.Resource; public class WxConfigDataRefreshConsumer extends AbstractChannelMessageListener { @Resource - private WxMpConfig wxMpConfig; + private WxAccountService wxAccountService; @Override public void onMessage(WxConfigDataRefreshMessage message) { log.info("[onMessage][收到 WxConfigData 刷新消息]"); - wxMpConfig.initWxConfig(); + wxAccountService.initLoadWxMpConfigStorages(); } } diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java index 09eee99a6..48382605c 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mp.mq.message.dict; +package cn.iocoder.yudao.module.mp.mq.message; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java index 725cb5eeb..d765b9aa7 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.module.mp.mq.producer.dict; +package cn.iocoder.yudao.module.mp.mq.producer; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; -import cn.iocoder.yudao.module.mp.mq.message.dict.WxConfigDataRefreshMessage; +import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage; import org.springframework.stereotype.Component; import javax.annotation.Resource; diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java index 57e3b4225..79650c2d7 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountService.java @@ -81,4 +81,9 @@ public interface WxAccountService { * @return */ WxAccountDO findBy(SFunction field, Object val); + + /** + * 初始化 + */ + void initLoadWxMpConfigStorages(); } diff --git a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java index e8153233f..6b550bb20 100644 --- a/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java +++ b/yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/WxAccountServiceImpl.java @@ -2,6 +2,7 @@ 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.WxAccountCreateReqVO; import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountExportReqVO; import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountPageReqVO; @@ -10,30 +11,52 @@ import cn.iocoder.yudao.module.mp.convert.account.WxAccountConvert; import cn.iocoder.yudao.module.mp.dal.dataobject.account.WxAccountDO; import cn.iocoder.yudao.module.mp.dal.mysql.account.WxAccountMapper; import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.mp.mq.producer.dict.WxMpConfigDataProducer; +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.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 公众号账户 Service 实现类 * - * @author 芋道源码 + * @author fengdan */ +@Slf4j @Service @Validated public class WxAccountServiceImpl implements WxAccountService { + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; @Resource private WxAccountMapper 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 createWxAccount(WxAccountCreateReqVO createReqVO) { @@ -94,4 +117,43 @@ public class WxAccountServiceImpl implements WxAccountService { public WxAccountDO findBy(SFunction field, Object val) { return wxAccountMapper.selectOne(field, val); } + + @PostConstruct + @TenantIgnore + @Override + public void initLoadWxMpConfigStorages() { + 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(WxAccountDO 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(); + } + + }