Commit 222daa5366eb8169097a9546000cd1acbcf05cee

Authored by YunaiV
1 parent a51579a7

pay 缓存,使用 guava 替代 job 扫描,目的:提升启动速度,加快缓存失效

Showing 14 changed files with 146 additions and 162 deletions
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
@@ -48,7 +48,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen @@ -48,7 +48,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
48 */ 48 */
49 public final void init() { 49 public final void init() {
50 doInit(); 50 doInit();
51 - log.info("[init][客户端({}) 初始化完成]", getId()); 51 + log.debug("[init][客户端({}) 初始化完成]", getId());
52 } 52 }
53 53
54 /** 54 /**
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
@@ -233,14 +233,38 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -233,14 +233,38 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
233 233
234 @Test 234 @Test
235 public void testGetFileClient() { 235 public void testGetFileClient() {
  236 + // mock 数据
  237 + FileConfigDO fileConfig = randomFileConfigDO().setMaster(false);
  238 + fileConfigMapper.insert(fileConfig);
236 // 准备参数 239 // 准备参数
237 - Long id = randomLongId(); 240 + Long id = fileConfig.getId();
238 // mock 获得 Client 241 // mock 获得 Client
239 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig()); 242 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
240 when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient); 243 when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient);
241 244
242 // 调用,并断言 245 // 调用,并断言
243 assertSame(fileClient, fileConfigService.getFileClient(id)); 246 assertSame(fileClient, fileConfigService.getFileClient(id));
  247 + // 断言缓存
  248 + verify(fileClientFactory).createOrUpdateFileClient(eq(id), eq(fileConfig.getStorage()),
  249 + eq(fileConfig.getConfig()));
  250 + }
  251 +
  252 + @Test
  253 + public void testGetMasterFileClient() {
  254 + // mock 数据
  255 + FileConfigDO fileConfig = randomFileConfigDO().setMaster(true);
  256 + fileConfigMapper.insert(fileConfig);
  257 + // 准备参数
  258 + Long id = fileConfig.getId();
  259 + // mock 获得 Client
  260 + FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
  261 + when(fileClientFactory.getFileClient(eq(0L))).thenReturn(fileClient);
  262 +
  263 + // 调用,并断言
  264 + assertSame(fileClient, fileConfigService.getMasterFileClient());
  265 + // 断言缓存
  266 + verify(fileClientFactory).createOrUpdateFileClient(eq(0L), eq(fileConfig.getStorage()),
  267 + eq(fileConfig.getConfig()));
244 } 268 }
245 269
246 private FileConfigDO randomFileConfigDO() { 270 private FileConfigDO randomFileConfigDO() {
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 7 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
8 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
9 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
10 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; 9 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
11 import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; 10 import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
@@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; @@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
16 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; 15 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; 16 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
18 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 17 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
  18 +import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
19 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; 19 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
20 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 20 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
21 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 21 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
@@ -53,9 +53,8 @@ public class PayNotifyController { @@ -53,9 +53,8 @@ public class PayNotifyController {
53 private PayNotifyService notifyService; 53 private PayNotifyService notifyService;
54 @Resource 54 @Resource
55 private PayAppService appService; 55 private PayAppService appService;
56 -  
57 @Resource 56 @Resource
58 - private PayClientFactory payClientFactory; 57 + private PayChannelService channelService;
59 58
60 @PostMapping(value = "/order/{channelId}") 59 @PostMapping(value = "/order/{channelId}")
61 @Operation(summary = "支付渠道的统一【支付】回调") 60 @Operation(summary = "支付渠道的统一【支付】回调")
@@ -66,7 +65,7 @@ public class PayNotifyController { @@ -66,7 +65,7 @@ public class PayNotifyController {
66 @RequestBody(required = false) String body) { 65 @RequestBody(required = false) String body) {
67 log.info("[notifyOrder][channelId({}) 回调数据({}/{})]", channelId, params, body); 66 log.info("[notifyOrder][channelId({}) 回调数据({}/{})]", channelId, params, body);
68 // 1. 校验支付渠道是否存在 67 // 1. 校验支付渠道是否存在
69 - PayClient payClient = payClientFactory.getPayClient(channelId); 68 + PayClient payClient = channelService.getPayClient(channelId);
70 if (payClient == null) { 69 if (payClient == null) {
71 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 70 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
72 throw exception(CHANNEL_NOT_FOUND); 71 throw exception(CHANNEL_NOT_FOUND);
@@ -87,7 +86,7 @@ public class PayNotifyController { @@ -87,7 +86,7 @@ public class PayNotifyController {
87 @RequestBody(required = false) String body) { 86 @RequestBody(required = false) String body) {
88 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body); 87 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
89 // 1. 校验支付渠道是否存在 88 // 1. 校验支付渠道是否存在
90 - PayClient payClient = payClientFactory.getPayClient(channelId); 89 + PayClient payClient = channelService.getPayClient(channelId);
91 if (payClient == null) { 90 if (payClient == null) {
92 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 91 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
93 throw exception(CHANNEL_NOT_FOUND); 92 throw exception(CHANNEL_NOT_FOUND);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/channel/PayChannelMapper.java
@@ -28,7 +28,4 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> { @@ -28,7 +28,4 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
28 .eq(PayChannelDO::getStatus, status)); 28 .eq(PayChannelDO::getStatus, status));
29 } 29 }
30 30
31 - @Select("SELECT COUNT(*) FROM pay_channel WHERE update_time > #{maxUpdateTime}")  
32 - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);  
33 -  
34 } 31 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java
@@ -15,7 +15,6 @@ import javax.annotation.Resource; @@ -15,7 +15,6 @@ import javax.annotation.Resource;
15 * @author 芋道源码 15 * @author 芋道源码
16 */ 16 */
17 @Component 17 @Component
18 -@TenantJob // 多租户  
19 @Slf4j 18 @Slf4j
20 public class PayNotifyJob implements JobHandler { 19 public class PayNotifyJob implements JobHandler {
21 20
@@ -23,6 +22,7 @@ public class PayNotifyJob implements JobHandler { @@ -23,6 +22,7 @@ public class PayNotifyJob implements JobHandler {
23 private PayNotifyService payNotifyService; 22 private PayNotifyService payNotifyService;
24 23
25 @Override 24 @Override
  25 + @TenantJob
26 public String execute(String param) throws Exception { 26 public String execute(String param) throws Exception {
27 int notifyCount = payNotifyService.executeNotify(); 27 int notifyCount = payNotifyService.executeNotify();
28 return String.format("执行支付通知 %s 个", notifyCount); 28 return String.format("执行支付通知 %s 个", notifyCount);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderExpireJob.java
@@ -16,13 +16,13 @@ import javax.annotation.Resource; @@ -16,13 +16,13 @@ import javax.annotation.Resource;
16 * @author 芋道源码 16 * @author 芋道源码
17 */ 17 */
18 @Component 18 @Component
19 -@TenantJob  
20 public class PayOrderExpireJob implements JobHandler { 19 public class PayOrderExpireJob implements JobHandler {
21 20
22 @Resource 21 @Resource
23 private PayOrderService orderService; 22 private PayOrderService orderService;
24 23
25 @Override 24 @Override
  25 + @TenantJob
26 public String execute(String param) { 26 public String execute(String param) {
27 int count = orderService.expireOrder(); 27 int count = orderService.expireOrder();
28 return StrUtil.format("支付过期 {} 个", count); 28 return StrUtil.format("支付过期 {} 个", count);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderSyncJob.java
@@ -18,7 +18,6 @@ import java.time.LocalDateTime; @@ -18,7 +18,6 @@ import java.time.LocalDateTime;
18 * @author 芋道源码 18 * @author 芋道源码
19 */ 19 */
20 @Component 20 @Component
21 -@TenantJob  
22 public class PayOrderSyncJob implements JobHandler { 21 public class PayOrderSyncJob implements JobHandler {
23 22
24 /** 23 /**
@@ -34,6 +33,7 @@ public class PayOrderSyncJob implements JobHandler { @@ -34,6 +33,7 @@ public class PayOrderSyncJob implements JobHandler {
34 private PayOrderService orderService; 33 private PayOrderService orderService;
35 34
36 @Override 35 @Override
  36 + @TenantJob
37 public String execute(String param) { 37 public String execute(String param) {
38 LocalDateTime minCreateTime = LocalDateTime.now().minus(CREATE_TIME_DURATION_BEFORE); 38 LocalDateTime minCreateTime = LocalDateTime.now().minus(CREATE_TIME_DURATION_BEFORE);
39 int count = orderService.syncOrder(minCreateTime); 39 int count = orderService.syncOrder(minCreateTime);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/refund/PayRefundSyncJob.java
@@ -16,13 +16,13 @@ import javax.annotation.Resource; @@ -16,13 +16,13 @@ import javax.annotation.Resource;
16 * @author 芋道源码 16 * @author 芋道源码
17 */ 17 */
18 @Component 18 @Component
19 -@TenantJob  
20 public class PayRefundSyncJob implements JobHandler { 19 public class PayRefundSyncJob implements JobHandler {
21 20
22 @Resource 21 @Resource
23 private PayRefundService refundService; 22 private PayRefundService refundService;
24 23
25 @Override 24 @Override
  25 + @TenantJob
26 public String execute(String param) { 26 public String execute(String param) {
27 int count = refundService.syncRefund(); 27 int count = refundService.syncRefund();
28 return StrUtil.format("同步退款订单 {} 个", count); 28 return StrUtil.format("同步退款订单 {} 个", count);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelService.java
1 package cn.iocoder.yudao.module.pay.service.channel; 1 package cn.iocoder.yudao.module.pay.service.channel;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
  4 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
4 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO; 5 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO;
5 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
@@ -92,4 +93,12 @@ public interface PayChannelService { @@ -92,4 +93,12 @@ public interface PayChannelService {
92 */ 93 */
93 List<PayChannelDO> getEnableChannelList(Long appId); 94 List<PayChannelDO> getEnableChannelList(Long appId);
94 95
  96 + /**
  97 + * 获得指定编号的支付客户端
  98 + *
  99 + * @param id 编号
  100 + * @return 支付客户端
  101 + */
  102 + PayClient getPayClient(Long id);
  103 +
95 } 104 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java
1 package cn.iocoder.yudao.module.pay.service.channel; 1 package cn.iocoder.yudao.module.pay.service.channel;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  7 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
9 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 8 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
10 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; 9 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
11 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 10 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
12 -import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;  
13 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO; 11 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO;
14 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO; 12 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO;
15 import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; 13 import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert;
16 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 14 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
17 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; 15 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
18 -import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient; 16 +import com.google.common.cache.CacheLoader;
  17 +import com.google.common.cache.LoadingCache;
19 import lombok.Getter; 18 import lombok.Getter;
20 -import lombok.Setter;  
21 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
22 -import org.springframework.scheduling.annotation.Scheduled;  
23 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
24 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
25 22
26 -import javax.annotation.PostConstruct;  
27 import javax.annotation.Resource; 23 import javax.annotation.Resource;
28 import javax.validation.Validator; 24 import javax.validation.Validator;
29 -import java.time.LocalDateTime; 25 +import java.time.Duration;
30 import java.util.Collection; 26 import java.util.Collection;
31 -import java.util.Collections;  
32 import java.util.List; 27 import java.util.List;
33 -import java.util.concurrent.TimeUnit;  
34 28
35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  30 +import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
36 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 31 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
37 32
38 /** 33 /**
@@ -45,71 +40,34 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; @@ -45,71 +40,34 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
45 @Validated 40 @Validated
46 public class PayChannelServiceImpl implements PayChannelService { 41 public class PayChannelServiceImpl implements PayChannelService {
47 42
48 - @Getter // 为了方便测试,这里提供 getter 方法  
49 - @Setter  
50 - private volatile List<PayChannelDO> channelCache; 43 + /**
  44 + * {@link PayClient} 缓存,通过它异步清空 smsClientFactory
  45 + */
  46 + @Getter
  47 + private final LoadingCache<Long, PayClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
  48 + new CacheLoader<Long, PayClient>() {
  49 +
  50 + @Override
  51 + public PayClient load(Long id) {
  52 + // 查询,然后尝试清空
  53 + PayChannelDO channel = payChannelMapper.selectById(id);
  54 + if (channel != null) {
  55 + payClientFactory.createOrUpdatePayClient(channel.getId(), channel.getCode(), channel.getConfig());
  56 + }
  57 + return payClientFactory.getPayClient(id);
  58 + }
  59 +
  60 + });
51 61
52 @Resource 62 @Resource
53 private PayClientFactory payClientFactory; 63 private PayClientFactory payClientFactory;
54 64
55 @Resource 65 @Resource
56 - private PayChannelMapper channelMapper; 66 + private PayChannelMapper payChannelMapper;
57 67
58 @Resource 68 @Resource
59 private Validator validator; 69 private Validator validator;
60 70
61 - /**  
62 - * 初始化 {@link #payClientFactory} 缓存  
63 - */  
64 - @PostConstruct  
65 - public void initLocalCache() {  
66 - // 注册钱包支付 Class  
67 - payClientFactory.registerPayClientClass(PayChannelEnum.WALLET, WalletPayClient.class);  
68 -  
69 - // 注意:忽略自动多租户,因为要全局初始化缓存  
70 - TenantUtils.executeIgnore(() -> {  
71 - // 第一步:查询数据  
72 - List<PayChannelDO> channels = Collections.emptyList();  
73 - try {  
74 - channels = channelMapper.selectList();  
75 - } catch (Throwable ex) {  
76 - if (!ex.getMessage().contains("doesn't exist")) {  
77 - throw ex;  
78 - }  
79 - log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");  
80 - }  
81 - log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size());  
82 -  
83 - // 第二步:构建缓存:创建或更新支付 Client  
84 - channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),  
85 - payChannel.getCode(), payChannel.getConfig()));  
86 - this.channelCache = channels;  
87 - });  
88 - }  
89 -  
90 - /**  
91 - * 通过定时任务轮询,刷新缓存  
92 - *  
93 - * 目的:多节点部署时,通过轮询”通知“所有节点,进行刷新  
94 - */  
95 - @Scheduled(initialDelay = 60, fixedRate = 60, timeUnit = TimeUnit.SECONDS)  
96 - public void refreshLocalCache() {  
97 - // 注意:忽略自动多租户,因为要全局初始化缓存  
98 - TenantUtils.executeIgnore(() -> {  
99 - // 情况一:如果缓存里没有数据,则直接刷新缓存  
100 - if (CollUtil.isEmpty(channelCache)) {  
101 - initLocalCache();  
102 - return;  
103 - }  
104 -  
105 - // 情况二,如果缓存里数据,则通过 updateTime 判断是否有数据变更,有变更则刷新缓存  
106 - LocalDateTime maxTime = CollectionUtils.getMaxValue(channelCache, PayChannelDO::getUpdateTime);  
107 - if (channelMapper.selectCountByUpdateTimeGt(maxTime) > 0) {  
108 - initLocalCache();  
109 - }  
110 - });  
111 - }  
112 -  
113 @Override 71 @Override
114 public Long createChannel(PayChannelCreateReqVO reqVO) { 72 public Long createChannel(PayChannelCreateReqVO reqVO) {
115 // 断言是否有重复的 73 // 断言是否有重复的
@@ -121,10 +79,7 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -121,10 +79,7 @@ public class PayChannelServiceImpl implements PayChannelService {
121 // 新增渠道 79 // 新增渠道
122 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO) 80 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO)
123 .setConfig(parseConfig(reqVO.getCode(), reqVO.getConfig())); 81 .setConfig(parseConfig(reqVO.getCode(), reqVO.getConfig()));
124 - channelMapper.insert(channel);  
125 -  
126 - // 刷新缓存  
127 - initLocalCache(); 82 + payChannelMapper.insert(channel);
128 return channel.getId(); 83 return channel.getId();
129 } 84 }
130 85
@@ -136,10 +91,10 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -136,10 +91,10 @@ public class PayChannelServiceImpl implements PayChannelService {
136 // 更新 91 // 更新
137 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO) 92 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO)
138 .setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig())); 93 .setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig()));
139 - channelMapper.updateById(channel); 94 + payChannelMapper.updateById(channel);
140 95
141 - // 刷新缓存  
142 - initLocalCache(); 96 + // 清空缓存
  97 + clearCache(channel.getId());
143 } 98 }
144 99
145 /** 100 /**
@@ -169,14 +124,23 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -169,14 +124,23 @@ public class PayChannelServiceImpl implements PayChannelService {
169 validateChannelExists(id); 124 validateChannelExists(id);
170 125
171 // 删除 126 // 删除
172 - channelMapper.deleteById(id); 127 + payChannelMapper.deleteById(id);
173 128
174 - // 刷新缓存  
175 - initLocalCache(); 129 + // 清空缓存
  130 + clearCache(id);
  131 + }
  132 +
  133 + /**
  134 + * 删除缓存
  135 + *
  136 + * @param id 渠道编号
  137 + */
  138 + private void clearCache(Long id) {
  139 + clientCache.invalidate(id);
176 } 140 }
177 141
178 private PayChannelDO validateChannelExists(Long id) { 142 private PayChannelDO validateChannelExists(Long id) {
179 - PayChannelDO channel = channelMapper.selectById(id); 143 + PayChannelDO channel = payChannelMapper.selectById(id);
180 if (channel == null) { 144 if (channel == null) {
181 throw exception(CHANNEL_NOT_FOUND); 145 throw exception(CHANNEL_NOT_FOUND);
182 } 146 }
@@ -185,29 +149,29 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -185,29 +149,29 @@ public class PayChannelServiceImpl implements PayChannelService {
185 149
186 @Override 150 @Override
187 public PayChannelDO getChannel(Long id) { 151 public PayChannelDO getChannel(Long id) {
188 - return channelMapper.selectById(id); 152 + return payChannelMapper.selectById(id);
189 } 153 }
190 154
191 @Override 155 @Override
192 public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) { 156 public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) {
193 - return channelMapper.selectListByAppIds(appIds); 157 + return payChannelMapper.selectListByAppIds(appIds);
194 } 158 }
195 159
196 @Override 160 @Override
197 public PayChannelDO getChannelByAppIdAndCode(Long appId, String code) { 161 public PayChannelDO getChannelByAppIdAndCode(Long appId, String code) {
198 - return channelMapper.selectByAppIdAndCode(appId, code); 162 + return payChannelMapper.selectByAppIdAndCode(appId, code);
199 } 163 }
200 164
201 @Override 165 @Override
202 public PayChannelDO validPayChannel(Long id) { 166 public PayChannelDO validPayChannel(Long id) {
203 - PayChannelDO channel = channelMapper.selectById(id); 167 + PayChannelDO channel = payChannelMapper.selectById(id);
204 validPayChannel(channel); 168 validPayChannel(channel);
205 return channel; 169 return channel;
206 } 170 }
207 171
208 @Override 172 @Override
209 public PayChannelDO validPayChannel(Long appId, String code) { 173 public PayChannelDO validPayChannel(Long appId, String code) {
210 - PayChannelDO channel = channelMapper.selectByAppIdAndCode(appId, code); 174 + PayChannelDO channel = payChannelMapper.selectByAppIdAndCode(appId, code);
211 validPayChannel(channel); 175 validPayChannel(channel);
212 return channel; 176 return channel;
213 } 177 }
@@ -223,7 +187,12 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -223,7 +187,12 @@ public class PayChannelServiceImpl implements PayChannelService {
223 187
224 @Override 188 @Override
225 public List<PayChannelDO> getEnableChannelList(Long appId) { 189 public List<PayChannelDO> getEnableChannelList(Long appId) {
226 - return channelMapper.selectListByAppId(appId, CommonStatusEnum.ENABLE.getStatus()); 190 + return payChannelMapper.selectListByAppId(appId, CommonStatusEnum.ENABLE.getStatus());
  191 + }
  192 +
  193 + @Override
  194 + public PayClient getPayClient(Long id) {
  195 + return clientCache.getUnchecked(id);
227 } 196 }
228 197
229 } 198 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 8 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
9 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 9 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
10 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 10 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
11 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; 11 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
13 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; 12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
14 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; 13 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
@@ -61,9 +60,6 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -61,9 +60,6 @@ public class PayOrderServiceImpl implements PayOrderService {
61 private PayProperties payProperties; 60 private PayProperties payProperties;
62 61
63 @Resource 62 @Resource
64 - private PayClientFactory payClientFactory;  
65 -  
66 - @Resource  
67 private PayOrderMapper orderMapper; 63 private PayOrderMapper orderMapper;
68 @Resource 64 @Resource
69 private PayOrderExtensionMapper orderExtensionMapper; 65 private PayOrderExtensionMapper orderExtensionMapper;
@@ -134,7 +130,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -134,7 +130,7 @@ public class PayOrderServiceImpl implements PayOrderService {
134 PayOrderDO order = validateOrderCanSubmit(reqVO.getId()); 130 PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
135 // 1.32 校验支付渠道是否有效 131 // 1.32 校验支付渠道是否有效
136 PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode()); 132 PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
137 - PayClient client = payClientFactory.getPayClient(channel.getId()); 133 + PayClient client = channelService.getPayClient(channel.getId());
138 134
139 // 2. 插入 PayOrderExtensionDO 135 // 2. 插入 PayOrderExtensionDO
140 String no = noRedisDAO.generate(payProperties.getOrderNoPrefix()); 136 String no = noRedisDAO.generate(payProperties.getOrderNoPrefix());
@@ -205,7 +201,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -205,7 +201,7 @@ public class PayOrderServiceImpl implements PayOrderService {
205 throw exception(ORDER_EXTENSION_IS_PAID); 201 throw exception(ORDER_EXTENSION_IS_PAID);
206 } 202 }
207 // 情况二:调用三方接口,查询支付单状态,是不是已支付 203 // 情况二:调用三方接口,查询支付单状态,是不是已支付
208 - PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); 204 + PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
209 if (payClient == null) { 205 if (payClient == null) {
210 log.error("[validateOrderCanSubmit][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId()); 206 log.error("[validateOrderCanSubmit][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
211 return; 207 return;
@@ -224,7 +220,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -224,7 +220,7 @@ public class PayOrderServiceImpl implements PayOrderService {
224 appService.validPayApp(appId); 220 appService.validPayApp(appId);
225 // 校验支付渠道是否有效 221 // 校验支付渠道是否有效
226 PayChannelDO channel = channelService.validPayChannel(appId, channelCode); 222 PayChannelDO channel = channelService.validPayChannel(appId, channelCode);
227 - PayClient client = payClientFactory.getPayClient(channel.getId()); 223 + PayClient client = channelService.getPayClient(channel.getId());
228 if (client == null) { 224 if (client == null) {
229 log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 225 log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
230 throw exception(CHANNEL_NOT_FOUND); 226 throw exception(CHANNEL_NOT_FOUND);
@@ -458,7 +454,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -458,7 +454,7 @@ public class PayOrderServiceImpl implements PayOrderService {
458 private boolean syncOrder(PayOrderExtensionDO orderExtension) { 454 private boolean syncOrder(PayOrderExtensionDO orderExtension) {
459 try { 455 try {
460 // 1.1 查询支付订单信息 456 // 1.1 查询支付订单信息
461 - PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); 457 + PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
462 if (payClient == null) { 458 if (payClient == null) {
463 log.error("[syncOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId()); 459 log.error("[syncOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
464 return false; 460 return false;
@@ -513,7 +509,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -513,7 +509,7 @@ public class PayOrderServiceImpl implements PayOrderService {
513 return false; 509 return false;
514 } 510 }
515 // 情况二:调用三方接口,查询支付单状态,是不是已支付/已退款 511 // 情况二:调用三方接口,查询支付单状态,是不是已支付/已退款
516 - PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); 512 + PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
517 if (payClient == null) { 513 if (payClient == null) {
518 log.error("[expireOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId()); 514 log.error("[expireOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
519 return false; 515 return false;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.extra.spring.SpringUtil; 4 import cn.hutool.extra.spring.SpringUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
7 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
8 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
9 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
10 import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; 9 import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
@@ -53,9 +52,6 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -53,9 +52,6 @@ public class PayRefundServiceImpl implements PayRefundService {
53 private PayProperties payProperties; 52 private PayProperties payProperties;
54 53
55 @Resource 54 @Resource
56 - private PayClientFactory payClientFactory;  
57 -  
58 - @Resource  
59 private PayRefundMapper refundMapper; 55 private PayRefundMapper refundMapper;
60 @Resource 56 @Resource
61 private PayNoRedisDAO noRedisDAO; 57 private PayNoRedisDAO noRedisDAO;
@@ -102,7 +98,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -102,7 +98,7 @@ public class PayRefundServiceImpl implements PayRefundService {
102 PayOrderDO order = validatePayOrderCanRefund(reqDTO); 98 PayOrderDO order = validatePayOrderCanRefund(reqDTO);
103 // 1.3 校验支付渠道是否有效 99 // 1.3 校验支付渠道是否有效
104 PayChannelDO channel = channelService.validPayChannel(order.getChannelId()); 100 PayChannelDO channel = channelService.validPayChannel(order.getChannelId());
105 - PayClient client = payClientFactory.getPayClient(channel.getId()); 101 + PayClient client = channelService.getPayClient(channel.getId());
106 if (client == null) { 102 if (client == null) {
107 log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 103 log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
108 throw exception(CHANNEL_NOT_FOUND); 104 throw exception(CHANNEL_NOT_FOUND);
@@ -305,7 +301,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -305,7 +301,7 @@ public class PayRefundServiceImpl implements PayRefundService {
305 private boolean syncRefund(PayRefundDO refund) { 301 private boolean syncRefund(PayRefundDO refund) {
306 try { 302 try {
307 // 1.1 查询退款订单信息 303 // 1.1 查询退款订单信息
308 - PayClient payClient = payClientFactory.getPayClient(refund.getChannelId()); 304 + PayClient payClient = channelService.getPayClient(refund.getChannelId());
309 if (payClient == null) { 305 if (payClient == null) {
310 log.error("[syncRefund][渠道编号({}) 找不到对应的支付客户端]", refund.getChannelId()); 306 log.error("[syncRefund][渠道编号({}) 找不到对应的支付客户端]", refund.getChannelId());
311 return false; 307 return false;
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.channel; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.channel;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  5 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
5 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
6 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; 7 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
7 import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig; 8 import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
@@ -12,30 +13,26 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR @@ -12,30 +13,26 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR
12 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
13 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; 14 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
14 import com.alibaba.fastjson.JSON; 15 import com.alibaba.fastjson.JSON;
15 -import org.junit.jupiter.api.BeforeEach;  
16 import org.junit.jupiter.api.Test; 16 import org.junit.jupiter.api.Test;
17 import org.springframework.boot.test.mock.mockito.MockBean; 17 import org.springframework.boot.test.mock.mockito.MockBean;
18 import org.springframework.context.annotation.Import; 18 import org.springframework.context.annotation.Import;
19 19
20 import javax.annotation.Resource; 20 import javax.annotation.Resource;
21 import javax.validation.Validator; 21 import javax.validation.Validator;
22 -  
23 -import java.time.Duration;  
24 import java.util.Collections; 22 import java.util.Collections;
25 import java.util.List; 23 import java.util.List;
26 24
27 -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;  
28 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 25 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
29 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 26 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
30 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; 27 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
31 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 28 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
32 import static org.junit.jupiter.api.Assertions.*; 29 import static org.junit.jupiter.api.Assertions.*;
  30 +import static org.mockito.ArgumentMatchers.eq;
  31 +import static org.mockito.Mockito.*;
33 32
34 @Import({PayChannelServiceImpl.class}) 33 @Import({PayChannelServiceImpl.class})
35 public class PayChannelServiceTest extends BaseDbUnitTest { 34 public class PayChannelServiceTest extends BaseDbUnitTest {
36 35
37 - private static final String ALIPAY_SERVER_URL = "https://openapi.alipay.com/gateway.do";  
38 -  
39 @Resource 36 @Resource
40 private PayChannelServiceImpl channelService; 37 private PayChannelServiceImpl channelService;
41 38
@@ -47,45 +44,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -47,45 +44,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
47 @MockBean 44 @MockBean
48 private Validator validator; 45 private Validator validator;
49 46
50 - @BeforeEach  
51 - public void setUp() {  
52 - channelService.setChannelCache(null);  
53 - }  
54 -  
55 - @Test  
56 - public void testInitLocalCache() {  
57 - // mock 数据  
58 - PayChannelDO dbChannel = randomPojo(PayChannelDO.class,  
59 - o -> o.setConfig(randomWxPayClientConfig()));  
60 - channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据  
61 -  
62 - // 调用  
63 - channelService.initLocalCache();  
64 - // 校验缓存  
65 - assertEquals(1, channelService.getChannelCache().size());  
66 - assertEquals(dbChannel, channelService.getChannelCache().get(0));  
67 - }  
68 -  
69 - @Test  
70 - public void testRefreshLocalCache() {  
71 - // mock 数据 01  
72 - PayChannelDO dbChannel = randomPojo(PayChannelDO.class,  
73 - o -> o.setConfig(randomWxPayClientConfig()).setUpdateTime(addTime(Duration.ofMinutes(-2))));  
74 - channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据  
75 - channelService.initLocalCache();  
76 - // mock 数据 02  
77 - PayChannelDO dbChannel02 = randomPojo(PayChannelDO.class,  
78 - o -> o.setConfig(randomWxPayClientConfig()));  
79 - channelMapper.insert(dbChannel02);// @Sql: 先插入出一条存在的数据  
80 -  
81 - // 调用  
82 - channelService.refreshLocalCache();  
83 - // 校验缓存  
84 - assertEquals(2, channelService.getChannelCache().size());  
85 - assertEquals(dbChannel, channelService.getChannelCache().get(0));  
86 - assertEquals(dbChannel02, channelService.getChannelCache().get(1));  
87 - }  
88 -  
89 @Test 47 @Test
90 public void testCreateChannel_success() { 48 public void testCreateChannel_success() {
91 // 准备参数 49 // 准备参数
@@ -103,8 +61,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -103,8 +61,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
103 assertPojoEquals(reqVO, channel, "config"); 61 assertPojoEquals(reqVO, channel, "config");
104 assertPojoEquals(config, channel.getConfig()); 62 assertPojoEquals(config, channel.getConfig());
105 // 校验缓存 63 // 校验缓存
106 - assertEquals(1, channelService.getChannelCache().size());  
107 - assertEquals(channel, channelService.getChannelCache().get(0)); 64 + assertNull(channelService.getClientCache().getIfPresent(channelId));
108 } 65 }
109 66
110 @Test 67 @Test
@@ -146,8 +103,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -146,8 +103,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
146 assertPojoEquals(reqVO, channel, "config"); 103 assertPojoEquals(reqVO, channel, "config");
147 assertPojoEquals(config, channel.getConfig()); 104 assertPojoEquals(config, channel.getConfig());
148 // 校验缓存 105 // 校验缓存
149 - assertEquals(1, channelService.getChannelCache().size());  
150 - assertEquals(channel, channelService.getChannelCache().get(0)); 106 + assertNull(channelService.getClientCache().getIfPresent(channel.getId()));
151 } 107 }
152 108
153 @Test 109 @Test
@@ -179,7 +135,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -179,7 +135,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
179 // 校验数据不存在了 135 // 校验数据不存在了
180 assertNull(channelMapper.selectById(id)); 136 assertNull(channelMapper.selectById(id));
181 // 校验缓存 137 // 校验缓存
182 - assertEquals(0, channelService.getChannelCache().size()); 138 + assertNull(channelService.getClientCache().getIfPresent(id));
183 } 139 }
184 140
185 @Test 141 @Test
@@ -344,6 +300,28 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -344,6 +300,28 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
344 assertPojoEquals(channel, dbChannel03); 300 assertPojoEquals(channel, dbChannel03);
345 } 301 }
346 302
  303 + @Test
  304 + public void testGetPayClient() {
  305 + // mock 数据
  306 + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> {
  307 + o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
  308 + o.setConfig(randomAlipayPayClientConfig());
  309 + });
  310 + channelMapper.insert(channel);
  311 + // mock 参数
  312 + Long id = channel.getId();
  313 + // mock 方法
  314 + PayClient mockClient = mock(PayClient.class);
  315 + when(payClientFactory.getPayClient(eq(id))).thenReturn(mockClient);
  316 +
  317 + // 调用
  318 + PayClient client = channelService.getPayClient(id);
  319 + // 断言
  320 + assertSame(client, mockClient);
  321 + verify(payClientFactory).createOrUpdatePayClient(eq(id), eq(channel.getCode()),
  322 + eq(channel.getConfig()));
  323 + }
  324 +
347 public WxPayClientConfig randomWxPayClientConfig() { 325 public WxPayClientConfig randomWxPayClientConfig() {
348 return new WxPayClientConfig() 326 return new WxPayClientConfig()
349 .setAppId(randomString()) 327 .setAppId(randomString())
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java
@@ -18,6 +18,7 @@ import lombok.Getter; @@ -18,6 +18,7 @@ import lombok.Getter;
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.scheduling.annotation.Scheduled; 19 import org.springframework.scheduling.annotation.Scheduled;
20 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.util.Assert;
21 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
22 23
23 import javax.annotation.PostConstruct; 24 import javax.annotation.PostConstruct;
@@ -43,6 +44,11 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_ @@ -43,6 +44,11 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_
43 public class SensitiveWordServiceImpl implements SensitiveWordService { 44 public class SensitiveWordServiceImpl implements SensitiveWordService {
44 45
45 /** 46 /**
  47 + * 是否开启敏感词功能
  48 + */
  49 + private static final Boolean ENABLED = false;
  50 +
  51 + /**
46 * 敏感词列表缓存 52 * 敏感词列表缓存
47 */ 53 */
48 @Getter 54 @Getter
@@ -75,6 +81,10 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { @@ -75,6 +81,10 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
75 */ 81 */
76 @PostConstruct 82 @PostConstruct
77 public void initLocalCache() { 83 public void initLocalCache() {
  84 + if (!ENABLED) {
  85 + return;
  86 + }
  87 +
78 // 第一步:查询数据 88 // 第一步:查询数据
79 List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList(); 89 List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList();
80 log.info("[initLocalCache][缓存敏感词,数量为:{}]", sensitiveWords.size()); 90 log.info("[initLocalCache][缓存敏感词,数量为:{}]", sensitiveWords.size());
@@ -216,6 +226,9 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { @@ -216,6 +226,9 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
216 226
217 @Override 227 @Override
218 public List<String> validateText(String text, List<String> tags) { 228 public List<String> validateText(String text, List<String> tags) {
  229 + Assert.isTrue(ENABLED, "敏感词功能未开启,请将 ENABLED 设置为 true");
  230 +
  231 + // 无标签时,默认所有
219 if (CollUtil.isEmpty(tags)) { 232 if (CollUtil.isEmpty(tags)) {
220 return defaultSensitiveWordTrie.validate(text); 233 return defaultSensitiveWordTrie.validate(text);
221 } 234 }
@@ -233,6 +246,9 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { @@ -233,6 +246,9 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
233 246
234 @Override 247 @Override
235 public boolean isTextValid(String text, List<String> tags) { 248 public boolean isTextValid(String text, List<String> tags) {
  249 + Assert.isTrue(ENABLED, "敏感词功能未开启,请将 ENABLED 设置为 true");
  250 +
  251 + // 无标签时,默认所有
236 if (CollUtil.isEmpty(tags)) { 252 if (CollUtil.isEmpty(tags)) {
237 return defaultSensitiveWordTrie.isValid(text); 253 return defaultSensitiveWordTrie.isValid(text);
238 } 254 }