mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	fix(公众号账号管理): 多公众号账号初始化配置加载
This commit is contained in:
		| @@ -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<String, WxMpMessageRouter> routers = Maps.newHashMap(); | ||||
|     private static Map<String, WxMpService> 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<WxAccountDO> 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<WxAccountDO> 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<String, WxMpMessageRouter> getRouters() { | ||||
|         return routers; | ||||
|     } | ||||
|  | ||||
|     public static Map<String, WxMpService> 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; | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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<WxConfigDataRefreshMessage> { | ||||
|  | ||||
|     @Resource | ||||
|     private WxMpConfig wxMpConfig; | ||||
|     private WxAccountService wxAccountService; | ||||
|  | ||||
|     @Override | ||||
|     public void onMessage(WxConfigDataRefreshMessage message) { | ||||
|         log.info("[onMessage][收到 WxConfigData 刷新消息]"); | ||||
|         wxMpConfig.initWxConfig(); | ||||
|         wxAccountService.initLoadWxMpConfigStorages(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -81,4 +81,9 @@ public interface WxAccountService { | ||||
|      * @return | ||||
|      */ | ||||
|     WxAccountDO findBy(SFunction<WxAccountDO, ?> field, Object val); | ||||
|  | ||||
|     /** | ||||
|      * 初始化 | ||||
|      */ | ||||
|     void initLoadWxMpConfigStorages(); | ||||
| } | ||||
|   | ||||
| @@ -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<WxAccountDO, ?> field, Object val) { | ||||
|         return wxAccountMapper.selectOne(field, val); | ||||
|     } | ||||
|  | ||||
|     @PostConstruct | ||||
|     @TenantIgnore | ||||
|     @Override | ||||
|     public void initLoadWxMpConfigStorages() { | ||||
|         List<WxAccountDO> 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<String, WxMpConfigStorage> configStorages = new HashMap<>(4); | ||||
|             configStorages.put(appId, wxMpRedisConfig); | ||||
|             wxMpService.setMultiConfigStorages(configStorages, appId); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||||
|     public void schedulePeriodicRefresh() { | ||||
|         self.initLoadWxMpConfigStorages(); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 fengdan
					fengdan