diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/CacheConstants.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/CacheConstants.java
index 191ef6386..a2384aff4 100644
--- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/CacheConstants.java
+++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/CacheConstants.java
@@ -63,6 +63,11 @@ public interface CacheConstants {
*/
String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
+ /**
+ * 公众号 reload
+ */
+ String MP_REDIS_RELOAD_TOPIC = "mp_redis_reload_topic";
+
/**
* 参数缓存
*/
diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java
similarity index 58%
rename from pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java
index 409d936a6..297a72534 100755
--- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
+++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java
@@ -1,17 +1,29 @@
package com.pig4cloud.pigx.mp.config;
import com.google.common.collect.Maps;
+import com.pig4cloud.pigx.admin.api.feign.RemoteTenantService;
+import com.pig4cloud.pigx.common.core.constant.CacheConstants;
+import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
+import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
+import com.pig4cloud.pigx.mp.entity.WxAccount;
import com.pig4cloud.pigx.mp.handler.*;
import com.pig4cloud.pigx.mp.service.WxAccountService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
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.constant.WxMpEventConstants;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.listener.ChannelTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -23,56 +35,50 @@ import static me.chanjar.weixin.common.api.WxConsts.*;
*
* 微信公众号基础配置,初始化配置
*/
+@Slf4j
@Configuration
-public class WxMpConfiguration {
- public static Map getRouters() {
- return routers;
- }
-
- public static Map getMpServices() {
- return mpServices;
- }
-
- private WxAccountService accountService;
- private LogHandler logHandler;
- private NullHandler nullHandler;
- private KfSessionHandler kfSessionHandler;
- private StoreCheckNotifyHandler storeCheckNotifyHandler;
- private LocationHandler locationHandler;
- private MenuHandler menuHandler;
- private MsgHandler msgHandler;
- private UnsubscribeHandler unsubscribeHandler;
- private SubscribeHandler subscribeHandler;
- private ScanHandler scanHandler;
- private RedisTemplate redisTemplate;
-
+@RequiredArgsConstructor
+public class WxMpInitConfigRunner {
+ /**
+ * 保存 appid-router 的对应关系
+ */
private static Map routers = Maps.newHashMap();
+
+ /**
+ * 保存 appid-mpservice 的对应关系
+ */
private static Map mpServices = Maps.newHashMap();
- @Autowired
- public WxMpConfiguration(WxAccountService accountService, LogHandler logHandler, NullHandler nullHandler
- , KfSessionHandler kfSessionHandler, StoreCheckNotifyHandler storeCheckNotifyHandler
- , LocationHandler locationHandler, MenuHandler menuHandler
- , MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler
- , SubscribeHandler subscribeHandler, ScanHandler scanHandler
- , RedisTemplate redisTemplate) {
- this.accountService = accountService;
- this.logHandler = logHandler;
- this.nullHandler = nullHandler;
- this.kfSessionHandler = kfSessionHandler;
- this.storeCheckNotifyHandler = storeCheckNotifyHandler;
- this.locationHandler = locationHandler;
- this.menuHandler = menuHandler;
- this.msgHandler = msgHandler;
- this.unsubscribeHandler = unsubscribeHandler;
- this.subscribeHandler = subscribeHandler;
- this.scanHandler = scanHandler;
- this.redisTemplate = redisTemplate;
- }
+ /**
+ * 保存 appid-tenantId 的对应关系
+ */
+ private static Map tenants = Maps.newHashMap();
+
+ private final RemoteTenantService tenantService;
+ private final WxAccountService accountService;
+ private final LogHandler logHandler;
+ private final NullHandler nullHandler;
+ private final KfSessionHandler kfSessionHandler;
+ private final StoreCheckNotifyHandler storeCheckNotifyHandler;
+ private final LocationHandler locationHandler;
+ private final MenuHandler menuHandler;
+ private final MsgHandler msgHandler;
+ private final UnsubscribeHandler unsubscribeHandler;
+ private final SubscribeHandler subscribeHandler;
+ private final ScanHandler scanHandler;
+ private final RedisTemplate redisTemplate;
@PostConstruct
public void initServices() {
- mpServices = accountService.list().stream().map(a -> {
+ // 获取全部租户 遍历所有租户对应的公众号列表
+ List accountList = new ArrayList<>();
+ tenantService.list(SecurityConstants.FROM_IN).getData()
+ .forEach(tenant -> {
+ TenantContextHolder.setTenantId(tenant.getId());
+ accountList.addAll(accountService.list());
+ });
+
+ mpServices = accountList.stream().map(a -> {
WxMpInRedisConfigStorage configStorage = new WxMpInRedisConfigStorage(redisTemplate);
configStorage.setAppId(a.getAppid());
configStorage.setSecret(a.getAppsecret());
@@ -82,6 +88,7 @@ public class WxMpConfiguration {
WxMpService service = new WxMpServiceImpl();
service.setWxMpConfigStorage(configStorage);
routers.put(a.getAppid(), this.newRouter(service));
+ tenants.put(a.getAppid(), a.getTenantId());
return service;
}).collect(Collectors.toMap(s -> s.getWxMpConfigStorage().getAppId(), a -> a));
}
@@ -146,4 +153,34 @@ public class WxMpConfiguration {
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;
+ }
+
+ public static Map getTenants() {
+ return tenants;
+ }
+
+ public static Map getRouters() {
+ return routers;
+ }
+
+ public static Map getMpServices() {
+ return mpServices;
+ }
}
diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
index 0c1ededd8..27a1853db 100755
--- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
+++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
@@ -18,12 +18,13 @@ package com.pig4cloud.pigx.mp.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
-import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
import com.pig4cloud.pigx.mp.entity.WxAccount;
import com.pig4cloud.pigx.mp.service.WxAccountService;
import lombok.AllArgsConstructor;
+import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -38,8 +39,8 @@ import org.springframework.web.bind.annotation.*;
@AllArgsConstructor
@RequestMapping("/wxaccount")
public class WxAccountController {
- private final WxMpConfiguration wxMpConfiguration;
private final WxAccountService wxAccountService;
+ private final RedisTemplate redisTemplate;
/**
* 分页查询
@@ -76,7 +77,7 @@ public class WxAccountController {
@PreAuthorize("@pms.hasPermission('mp_wxaccount_add')")
public R save(@RequestBody WxAccount wxAccount) {
wxAccountService.save(wxAccount);
- wxMpConfiguration.initServices();
+ redisTemplate.convertAndSend(CacheConstants.MP_REDIS_RELOAD_TOPIC,"重新加载公众号配置");
return R.ok();
}
@@ -91,7 +92,7 @@ public class WxAccountController {
@PreAuthorize("@pms.hasPermission('mp_wxaccount_edit')")
public R updateById(@RequestBody WxAccount wxAccount) {
wxAccountService.updateById(wxAccount);
- wxMpConfiguration.initServices();
+ redisTemplate.convertAndSend(CacheConstants.MP_REDIS_RELOAD_TOPIC,"重新加载公众号配置");
return R.ok();
}
@@ -106,7 +107,7 @@ public class WxAccountController {
@PreAuthorize("@pms.hasPermission('mp_wxaccount_del')")
public R removeById(@PathVariable Integer id) {
wxAccountService.removeById(id);
- wxMpConfiguration.initServices();
+ redisTemplate.convertAndSend(CacheConstants.MP_REDIS_RELOAD_TOPIC,"重新加载公众号配置");
return R.ok();
}
diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java
index 0735cfadd..8adc489df 100755
--- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java
+++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java
@@ -16,32 +16,15 @@
*/
package com.pig4cloud.pigx.mp.controller;
-import cn.hutool.json.JSONArray;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
-import com.pig4cloud.pigx.mp.constant.MsgTypeEnum;
-import com.pig4cloud.pigx.mp.entity.WxAccountFans;
import com.pig4cloud.pigx.mp.entity.WxMsg;
-import com.pig4cloud.pigx.mp.service.WxAccountFansService;
import com.pig4cloud.pigx.mp.service.WxMsgService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import me.chanjar.weixin.common.api.WxConsts;
-import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.mp.api.WxMpKefuService;
-import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
-import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* 微信粉丝消息管理
@@ -55,7 +38,6 @@ import java.util.List;
@RequestMapping("/wxfansmsg")
public class WxFansMsgController {
- private final WxAccountFansService wxAccountFansService;
private final WxMsgService wxMsgService;
/**
@@ -88,91 +70,7 @@ public class WxFansMsgController {
*/
@PostMapping
public R save(@RequestBody WxMsg wxMsg) {
- try {
- WxAccountFans wxUser = wxAccountFansService.getById(wxMsg.getWxUserId());
- //入库
- wxMsg.setNickName(wxUser.getNickname());
- wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
- wxMsg.setCreateTime(LocalDateTime.now());
- wxMsg.setType(MsgTypeEnum.MP2USER.getType());
- WxMpKefuMessage wxMpKefuMessage = null;
- if (WxConsts.KefuMsgType.TEXT.equals(wxMsg.getRepType())) {
- wxMsg.setRepContent(wxMsg.getRepContent());
- wxMpKefuMessage = WxMpKefuMessage.TEXT().build();
- wxMpKefuMessage.setContent(wxMsg.getRepContent());
- }
- if (WxConsts.KefuMsgType.IMAGE.equals(wxMsg.getRepType())) {//图片
- wxMsg.setRepName(wxMsg.getRepName());
- wxMsg.setRepUrl(wxMsg.getRepUrl());
- wxMsg.setRepMediaId(wxMsg.getRepMediaId());
- wxMpKefuMessage = WxMpKefuMessage.IMAGE().build();
- wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId());
- }
- if (WxConsts.KefuMsgType.VOICE.equals(wxMsg.getRepType())) {
- wxMsg.setRepName(wxMsg.getRepName());
- wxMsg.setRepUrl(wxMsg.getRepUrl());
- wxMsg.setRepMediaId(wxMsg.getRepMediaId());
- wxMpKefuMessage = WxMpKefuMessage.VOICE().build();
- wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId());
- }
- if (WxConsts.KefuMsgType.VIDEO.equals(wxMsg.getRepType())) {
- wxMsg.setRepName(wxMsg.getRepName());
- wxMsg.setRepDesc(wxMsg.getRepDesc());
- wxMsg.setRepUrl(wxMsg.getRepUrl());
- wxMsg.setRepMediaId(wxMsg.getRepMediaId());
- wxMpKefuMessage = WxMpKefuMessage.VIDEO().build();
- wxMpKefuMessage.setMediaId(wxMsg.getRepMediaId());
- wxMpKefuMessage.setTitle(wxMsg.getRepName());
- wxMpKefuMessage.setDescription(wxMsg.getRepDesc());
- }
- if (WxConsts.KefuMsgType.MUSIC.equals(wxMsg.getRepType())) {
- wxMsg.setRepName(wxMsg.getRepName());
- wxMsg.setRepDesc(wxMsg.getRepDesc());
- wxMsg.setRepUrl(wxMsg.getRepUrl());
- wxMsg.setRepHqUrl(wxMsg.getRepHqUrl());
- wxMpKefuMessage = WxMpKefuMessage.MUSIC().build();
- wxMpKefuMessage.setTitle(wxMsg.getRepName());
- wxMpKefuMessage.setDescription(wxMsg.getRepDesc());
- wxMpKefuMessage.setMusicUrl(wxMsg.getRepUrl());
- wxMpKefuMessage.setHqMusicUrl(wxMsg.getRepHqUrl());
- wxMpKefuMessage.setThumbMediaId(wxMsg.getRepThumbMediaId());
- }
- if (WxConsts.KefuMsgType.NEWS.equals(wxMsg.getRepType())) {
- List list = new ArrayList<>();
- JSONArray articles = JSONUtil.parseObj(wxMsg.getContent()).getJSONArray("articles");
- WxMpKefuMessage.WxArticle t;
- for (Object object : articles) {
- JSONObject obj = JSONUtil.parseObj(JSONUtil.toJsonStr(object));
- t = new WxMpKefuMessage.WxArticle();
- t.setTitle(obj.getStr("title"));
- t.setDescription(obj.getStr("digest"));
- t.setPicUrl(obj.getStr("thumbUrl"));
- t.setUrl(obj.getStr("url"));
- list.add(t);
- }
- wxMsg.setRepName(wxMsg.getRepName());
- wxMsg.setRepDesc(wxMsg.getRepDesc());
- wxMsg.setRepUrl(wxMsg.getRepUrl());
- wxMsg.setRepMediaId(wxMsg.getRepMediaId());
- wxMsg.setContent(wxMsg.getContent());
- wxMpKefuMessage = WxMpKefuMessage.NEWS().build();
- wxMpKefuMessage.setArticles(list);
- }
- if (wxMpKefuMessage != null) {
- WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxMsg.getAppId());
- WxMpKefuService wxMpKefuService = wxMpService.getKefuService();
- wxMpKefuMessage.setToUser(wxUser.getOpenid());
- wxMpKefuService.sendKefuMessage(wxMpKefuMessage);
- wxMsgService.save(wxMsg);
- return R.ok(wxMsg);
- } else {
- return R.failed("非法消息类型");
- }
- } catch (WxErrorException e) {
- e.printStackTrace();
- log.error("新增微信消息失败" + e.getMessage());
- return R.failed(e.getMessage());
- }
+ return wxMsgService.saveAndPushMsg(wxMsg);
}
/**
@@ -182,7 +80,6 @@ public class WxFansMsgController {
* @return R
*/
@PutMapping
- @PreAuthorize("@ss.hasPermi('wxmp:wxmsg:edit')")
public R updateById(@RequestBody WxMsg wxMsg) {
return R.ok(wxMsgService.updateById(wxMsg));
}
@@ -194,7 +91,6 @@ public class WxFansMsgController {
* @return R
*/
@DeleteMapping("/{id}")
- @PreAuthorize("@ss.hasPermi('wxmp:wxmsg:del')")
public R removeById(@PathVariable String id) {
return R.ok(wxMsgService.removeById(id));
}
diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxMaterialController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxMaterialController.java
index fc779271f..d8a1805ea 100644
--- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxMaterialController.java
+++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxMaterialController.java
@@ -6,7 +6,7 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
+import com.pig4cloud.pigx.mp.config.WxMpInitConfigRunner;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
@@ -65,7 +65,7 @@ public class WxMaterialController {
mulFile.transferTo(file);
material.setFile(file);
- WxMpService wxMpService = WxMpConfiguration.getMpServices().get(appId);
+ WxMpService wxMpService = WxMpInitConfigRunner.getMpServices().get(appId);
WxMpMaterialService wxMpMaterialService = wxMpService.getMaterialService();
WxMpMaterialUploadResult wxMpMaterialUploadResult = wxMpMaterialService.materialFileUpload(mediaType, material);
WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem wxMpMaterialFileBatchGetResult = new WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem();
@@ -98,7 +98,7 @@ public class WxMaterialController {
news.setArticles(articles);
String appId = data.getStr("appId");
- WxMpService wxMpService = WxMpConfiguration.getMpServices().get(appId);
+ WxMpService wxMpService = WxMpInitConfigRunner.getMpServices().get(appId);
WxMpMaterialService wxMpMaterialService = wxMpService.getMaterialService();
WxMpMaterialUploadResult wxMpMaterialUploadResult = wxMpMaterialService.materialNewsUpload(news);
return R.ok(wxMpMaterialUploadResult);
@@ -124,7 +124,7 @@ public class WxMaterialController {
JSONArray jSONArray = data.getJSONArray("articles");
List articles = jSONArray.toList(WxMpMaterialNews.WxMpMaterialNewsArticle.class);
String appId = data.getStr("appId");
- WxMpService wxMpService = WxMpConfiguration.getMpServices().get(appId);
+ WxMpService wxMpService = WxMpInitConfigRunner.getMpServices().get(appId);
WxMpMaterialService wxMpMaterialService = wxMpService.getMaterialService();
WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate = new WxMpMaterialArticleUpdate();
wxMpMaterialArticleUpdate.setMediaId(mediaId);
@@ -155,10 +155,10 @@ public class WxMaterialController {
public String newsImgUpload(@RequestParam("file") MultipartFile mulFile, @RequestParam String appId) throws Exception {
File file = FileUtil.createTempFile(FileUtil.getTmpDir());
mulFile.transferTo(file);
- WxMpService wxMpService = WxMpConfiguration.getMpServices().get(appId);
+ WxMpService wxMpService = WxMpInitConfigRunner.getMpServices().get(appId);
WxMpMaterialService wxMpMaterialService = wxMpService.getMaterialService();
WxMediaImgUploadResult wxMediaImgUploadResult = wxMpMaterialService.mediaImgUpload(file);
- Map