Commit 977cc19fe31c9874aeec3e7f7dbfbff99f3ebd64

Authored by fengdan
1 parent 93dfee8e

fix(公众号账号管理): 多公众号账号初始化配置加载

yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpConfig.java deleted
1   -package cn.iocoder.yudao.module.mp.config;
2   -
3   -
4   -import cn.hutool.extra.spring.SpringUtil;
5   -import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountExportReqVO;
6   -import cn.iocoder.yudao.module.mp.dal.dataobject.account.WxAccountDO;
7   -import cn.iocoder.yudao.module.mp.handler.*;
8   -import cn.iocoder.yudao.module.mp.service.account.WxAccountService;
9   -import com.google.common.collect.Maps;
10   -import lombok.extern.slf4j.Slf4j;
11   -import me.chanjar.weixin.common.api.WxConsts;
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.WxMpDefaultConfigImpl;
16   -import me.chanjar.weixin.mp.constant.WxMpEventConstants;
17   -import org.springframework.context.annotation.Configuration;
18   -import org.springframework.scheduling.annotation.Scheduled;
19   -import org.springframework.util.CollectionUtils;
20   -
21   -import javax.annotation.PostConstruct;
22   -import javax.annotation.Resource;
23   -import java.util.List;
24   -import java.util.Map;
25   -import java.util.stream.Collectors;
26   -
27   -// TODO @芋艿:思考有没更好的处理方式
28   -@Slf4j
29   -@Configuration
30   -public class WxMpConfig {
31   -
32   - private static Map<String, WxMpMessageRouter> routers = Maps.newHashMap();
33   - private static Map<String, WxMpService> mpServices = Maps.newHashMap();
34   -
35   - @Resource
36   - private WxAccountService wxAccountService;
37   -
38   - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
39   -
40   - /**
41   - * 初始化公众号配置
42   - */
43   - @PostConstruct
44   - public synchronized void initWxConfig() {
45   - WxAccountExportReqVO req = new WxAccountExportReqVO();
46   - List<WxAccountDO> wxAccountList = wxAccountService.getWxAccountList(req);
47   - if (CollectionUtils.isEmpty(wxAccountList)) {
48   - return;
49   - }
50   - WxMpConfig.init(wxAccountList);
51   - log.info("加载公众号配置成功");
52   - }
53   -
54   -
55   - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
56   - public void schedulePeriodicRefresh() {
57   - initWxConfig();
58   - }
59   -
60   - public static void init(List<WxAccountDO> wxAccountDOS) {
61   - mpServices = wxAccountDOS.stream().map(wxAccountDO -> {
62   - // TODO 亚洲:使用 WxMpInMemoryConfigStorage 的话,多节点会不会存在 accessToken 冲突
63   -
64   - WxMpDefaultConfigImpl configStorage;
65   - configStorage = new WxMpDefaultConfigImpl();
66   -
67   - configStorage.setAppId(wxAccountDO.getAppId());
68   - configStorage.setSecret(wxAccountDO.getAppSecret());
69   - configStorage.setToken(wxAccountDO.getToken());
70   - configStorage.setAesKey(wxAccountDO.getAesKey());
71   -
72   - WxMpService service = new WxMpServiceImpl();
73   - service.setWxMpConfigStorage(configStorage);
74   - routers.put(wxAccountDO.getAppId(), newRouter(service));
75   - return service;
76   - }).collect(Collectors.toMap(s -> s.getWxMpConfigStorage().getAppId(), a -> a, (o, n) -> o));
77   - }
78   -
79   - public static Map<String, WxMpMessageRouter> getRouters() {
80   - return routers;
81   - }
82   -
83   - public static Map<String, WxMpService> getMpServices() {
84   - return mpServices;
85   - }
86   -
87   - private static WxMpMessageRouter newRouter(WxMpService wxMpService) {
88   - final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
89   - // 记录所有事件的日志 (异步执行)
90   - newRouter.rule().handler(SpringUtil.getBean(LogHandler.class)).next();
91   -
92   - // 接收客服会话管理事件
93   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
94   - .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
95   - .handler(SpringUtil.getBean(KfSessionHandler.class)).end();
96   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
97   - .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
98   - .handler(SpringUtil.getBean(KfSessionHandler.class))
99   - .end();
100   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
101   - .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
102   - .handler(SpringUtil.getBean(KfSessionHandler.class)).end();
103   -
104   - // 门店审核事件
105   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
106   - .event(WxMpEventConstants.POI_CHECK_NOTIFY)
107   - .handler(SpringUtil.getBean(StoreCheckNotifyHandler.class)).end();
108   -
109   - // 自定义菜单事件
110   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
111   - .event(WxConsts.MenuButtonType.CLICK).handler(SpringUtil.getBean(MenuHandler.class)).end();
112   -
113   - // 点击菜单连接事件
114   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
115   - .event(WxConsts.MenuButtonType.VIEW).handler(SpringUtil.getBean(NullHandler.class)).end();
116   -
117   - // 关注事件
118   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
119   - .event(WxConsts.EventType.SUBSCRIBE).handler(SpringUtil.getBean(SubscribeHandler.class))
120   - .end();
121   -
122   - // 取消关注事件
123   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
124   - .event(WxConsts.EventType.UNSUBSCRIBE)
125   - .handler(SpringUtil.getBean(UnsubscribeHandler.class)).end();
126   -
127   - // 上报地理位置事件
128   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
129   - .event(WxConsts.EventType.LOCATION).handler(SpringUtil.getBean(LocationHandler.class))
130   - .end();
131   -
132   - // 接收地理位置消息
133   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
134   - .handler(SpringUtil.getBean(LocationHandler.class)).end();
135   -
136   - // 扫码事件
137   - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
138   - .event(WxConsts.EventType.SCAN).handler(SpringUtil.getBean(ScanHandler.class)).end();
139   -
140   - // 默认
141   - newRouter.rule().async(false).handler(SpringUtil.getBean(MsgHandler.class)).end();
142   -
143   - return newRouter;
144   - }
145   -}
yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/config/WxMpProperties.java deleted
1   -package cn.iocoder.yudao.module.mp.config;
2   -
3   -import lombok.Data;
4   -import org.springframework.boot.context.properties.ConfigurationProperties;
5   -
6   -/**
7   - * wechat mp properties
8   - */
9   -@Data
10   -//@ConfigurationProperties(prefix = "wx.mp")
11   -public class WxMpProperties {
12   - /**
13   - * 是否使用redis存储access token
14   - */
15   - private boolean useRedis;
16   -
17   - private String defaultContent;
18   -
19   - /**
20   - * redis 配置
21   - */
22   - private RedisConfig redisConfig;
23   -
24   - @Data
25   - public static class RedisConfig {
26   - /**
27   - * redis服务器 主机地址
28   - */
29   - private String host;
30   -
31   - /**
32   - * redis服务器 端口号
33   - */
34   - private Integer port;
35   -
36   - /**
37   - * redis服务器 密码
38   - */
39   - private String password;
40   -
41   - /**
42   - * redis 服务连接超时时间
43   - */
44   - private Integer timeout;
45   - }
46   -
47   -}
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;
4 4 import com.baomidou.mybatisplus.annotation.KeySequence;
5 5 import com.baomidou.mybatisplus.annotation.TableId;
6 6 import com.baomidou.mybatisplus.annotation.TableName;
  7 +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
7 8 import lombok.*;
  9 +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
  10 +import me.chanjar.weixin.mp.config.WxMpConfigStorage;
  11 +import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
8 12  
9 13 // TODO 亚洲:这个模块的相关类,使用 Mp 作为前缀哈
10 14 /**
... ... @@ -64,4 +68,12 @@ public class WxAccountDO extends BaseDO {
64 68 */
65 69 private String remark;
66 70  
  71 + public WxMpConfigStorage toWxMpConfigStorage(RedisTemplateWxRedisOps redisTemplateWxRedisOps, WxMpProperties wxMpProperties) {
  72 + WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(redisTemplateWxRedisOps, wxMpProperties.getConfigStorage().getKeyPrefix());
  73 + wxMpRedisConfig.setAppId(appId);
  74 + wxMpRedisConfig.setSecret(appSecret);
  75 + wxMpRedisConfig.setToken(token);
  76 + wxMpRedisConfig.setAesKey(aesKey);
  77 + return wxMpRedisConfig;
  78 + }
67 79 }
... ...
yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/framework/weixin/WxMpMessageRouterConfiguration.java 0 → 100644
  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-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;
6 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 7 import cn.iocoder.yudao.module.infra.api.file.FileApi;
8 8 import cn.iocoder.yudao.module.mp.builder.TextBuilder;
9   -import cn.iocoder.yudao.module.mp.config.WxMpProperties;
10 9 import cn.iocoder.yudao.module.mp.controller.admin.fansmsg.vo.WxFansMsgCreateReqVO;
11 10 import cn.iocoder.yudao.module.mp.dal.dataobject.account.WxAccountDO;
12 11 import cn.iocoder.yudao.module.mp.service.account.WxAccountService;
13 12 import cn.iocoder.yudao.module.mp.service.fansmsg.WxFansMsgService;
14   -import cn.iocoder.yudao.module.mp.service.receivetext.WxReceiveTextService;
15   -import cn.iocoder.yudao.module.mp.service.texttemplate.WxTextTemplateService;
16 13 import lombok.extern.slf4j.Slf4j;
17 14 import me.chanjar.weixin.common.api.WxConsts;
18 15 import me.chanjar.weixin.common.error.WxErrorException;
... ... @@ -102,7 +99,7 @@ public class MsgHandler implements WxMpMessageHandler {
102 99 if (!downloadDir.exists()) {
103 100 downloadDir.mkdirs();
104 101 }
105   - String filepath = downloadDirStr + String.valueOf(System.currentTimeMillis()) + ".png";
  102 + String filepath = downloadDirStr + System.currentTimeMillis() + ".png";
106 103 //微信pic url下载到本地,防止失效
107 104 long size = HttpUtil.downloadFile(wxMessage.getPicUrl(), FileUtil.file(filepath));
108 105 log.info("download pic size : {}", size);
... ...
yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/costomer/WxConfigDataRefreshConsumer.java
1   -package cn.iocoder.yudao.module.mp.mq.costomer.dict;
  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.config.WxMpConfig;
5   -import cn.iocoder.yudao.module.mp.mq.message.dict.WxConfigDataRefreshMessage;
  4 +import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage;
  5 +import cn.iocoder.yudao.module.mp.service.account.WxAccountService;
6 6 import lombok.extern.slf4j.Slf4j;
7 7 import org.springframework.stereotype.Component;
8 8  
... ... @@ -18,12 +18,12 @@ import javax.annotation.Resource;
18 18 public class WxConfigDataRefreshConsumer extends AbstractChannelMessageListener<WxConfigDataRefreshMessage> {
19 19  
20 20 @Resource
21   - private WxMpConfig wxMpConfig;
  21 + private WxAccountService wxAccountService;
22 22  
23 23 @Override
24 24 public void onMessage(WxConfigDataRefreshMessage message) {
25 25 log.info("[onMessage][收到 WxConfigData 刷新消息]");
26   - wxMpConfig.initWxConfig();
  26 + wxAccountService.initLoadWxMpConfigStorages();
27 27 }
28 28  
29 29 }
... ...
yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/WxConfigDataRefreshMessage.java
1   -package cn.iocoder.yudao.module.mp.mq.message.dict;
  1 +package cn.iocoder.yudao.module.mp.mq.message;
2 2  
3 3 import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
... ...
yudao-module-wechat/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/WxMpConfigDataProducer.java
1   -package cn.iocoder.yudao.module.mp.mq.producer.dict;
  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.dict.WxConfigDataRefreshMessage;
  4 +import cn.iocoder.yudao.module.mp.mq.message.WxConfigDataRefreshMessage;
5 5 import org.springframework.stereotype.Component;
6 6  
7 7 import javax.annotation.Resource;
... ...
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 {
81 81 * @return
82 82 */
83 83 WxAccountDO findBy(SFunction<WxAccountDO, ?> field, Object val);
  84 +
  85 + /**
  86 + * 初始化
  87 + */
  88 + void initLoadWxMpConfigStorages();
84 89 }
... ...
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;
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 6 import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountCreateReqVO;
6 7 import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountExportReqVO;
7 8 import cn.iocoder.yudao.module.mp.controller.admin.account.vo.WxAccountPageReqVO;
... ... @@ -10,30 +11,52 @@ import cn.iocoder.yudao.module.mp.convert.account.WxAccountConvert;
10 11 import cn.iocoder.yudao.module.mp.dal.dataobject.account.WxAccountDO;
11 12 import cn.iocoder.yudao.module.mp.dal.mysql.account.WxAccountMapper;
12 13 import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants;
13   -import cn.iocoder.yudao.module.mp.mq.producer.dict.WxMpConfigDataProducer;
  14 +import cn.iocoder.yudao.module.mp.mq.producer.WxMpConfigDataProducer;
14 15 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
  16 +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
  17 +import lombok.extern.slf4j.Slf4j;
  18 +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
  19 +import me.chanjar.weixin.mp.api.WxMpService;
  20 +import me.chanjar.weixin.mp.config.WxMpConfigStorage;
  21 +import org.springframework.context.annotation.Lazy;
  22 +import org.springframework.data.redis.core.StringRedisTemplate;
  23 +import org.springframework.scheduling.annotation.Scheduled;
15 24 import org.springframework.stereotype.Service;
  25 +import org.springframework.util.CollectionUtils;
16 26 import org.springframework.validation.annotation.Validated;
17 27  
  28 +import javax.annotation.PostConstruct;
18 29 import javax.annotation.Resource;
19 30 import java.util.Collection;
  31 +import java.util.HashMap;
20 32 import java.util.List;
  33 +import java.util.Map;
21 34  
22 35  
23 36 /**
24 37 * 公众号账户 Service 实现类
25 38 *
26   - * @author 芋道源码
  39 + * @author fengdan
27 40 */
  41 +@Slf4j
28 42 @Service
29 43 @Validated
30 44 public class WxAccountServiceImpl implements WxAccountService {
31 45  
  46 + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
32 47 @Resource
33 48 private WxAccountMapper wxAccountMapper;
34   -
35 49 @Resource
36 50 private WxMpConfigDataProducer wxMpConfigDataProducer;
  51 + @Resource
  52 + private StringRedisTemplate stringRedisTemplate;
  53 + @Resource
  54 + private WxMpService wxMpService;
  55 + @Resource
  56 + private WxMpProperties wxMpProperties;
  57 + @Resource
  58 + @Lazy // 注入自己,所以延迟加载
  59 + private WxAccountService self;
37 60  
38 61 @Override
39 62 public Long createWxAccount(WxAccountCreateReqVO createReqVO) {
... ... @@ -94,4 +117,43 @@ public class WxAccountServiceImpl implements WxAccountService {
94 117 public WxAccountDO findBy(SFunction<WxAccountDO, ?> field, Object val) {
95 118 return wxAccountMapper.selectOne(field, val);
96 119 }
  120 +
  121 + @PostConstruct
  122 + @TenantIgnore
  123 + @Override
  124 + public void initLoadWxMpConfigStorages() {
  125 + List<WxAccountDO> wxAccountList = this.wxAccountMapper.selectList();
  126 + if (CollectionUtils.isEmpty(wxAccountList)) {
  127 + log.info("未读取到公众号配置,请在管理后台添加");
  128 + return;
  129 + }
  130 + log.info("加载到{}条公众号配置", wxAccountList.size());
  131 + wxAccountList.forEach(account -> addAccountToRuntime(account, new RedisTemplateWxRedisOps(stringRedisTemplate)));
  132 + log.info("公众号配置加载完成");
  133 + }
  134 +
  135 + /**
  136 + * 添加账号到当前程序,如首次添加需初始化configStorageMap
  137 + *
  138 + * @param account 公众号
  139 + */
  140 + private synchronized void addAccountToRuntime(WxAccountDO account, RedisTemplateWxRedisOps redisOps) {
  141 + String appId = account.getAppId();
  142 + WxMpConfigStorage wxMpRedisConfig = account.toWxMpConfigStorage(redisOps, wxMpProperties);
  143 + try {
  144 + wxMpService.addConfigStorage(appId, wxMpRedisConfig);
  145 + } catch (NullPointerException e) {
  146 + log.info("需初始化configStorageMap...");
  147 + Map<String, WxMpConfigStorage> configStorages = new HashMap<>(4);
  148 + configStorages.put(appId, wxMpRedisConfig);
  149 + wxMpService.setMultiConfigStorages(configStorages, appId);
  150 + }
  151 + }
  152 +
  153 + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
  154 + public void schedulePeriodicRefresh() {
  155 + self.initLoadWxMpConfigStorages();
  156 + }
  157 +
  158 +
97 159 }
... ...