From f717c0f9c632f82195a2d3eb6a678290c51c8144 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 24 Jul 2024 23:03:59 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91PAY=EF=BC=9A=E7=A7=BB=E9=99=A4=20PayClient=20?= =?UTF-8?q?=E7=BC=93=E5=AD=98=EF=BC=8C=E5=87=8F=E5=B0=91=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E6=80=A7=EF=BC=8C=E6=80=A7=E8=83=BD=E8=B6=B3=E5=A4=9F=EF=BC=88?= =?UTF-8?q?=E9=9D=9E=E9=AB=98=E9=A2=91=E8=AF=BB=E5=8F=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/handler/GlobalExceptionHandler.java | 15 ++++++- .../module/pay/job/order/PayOrderSyncJob.java | 4 +- .../channel/PayChannelServiceImpl.java | 42 +------------------ .../pay/core/client/PayClientFactory.java | 5 ++- .../client/impl/PayClientFactoryImpl.java | 5 ++- .../client/impl/weixin/WxNativePayClient.java | 3 +- 6 files changed, 25 insertions(+), 49 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index 6935f7bee..6658d0b27 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -2,10 +2,12 @@ package cn.iocoder.yudao.framework.web.core.handler; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.JakartaServletUtil; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -222,8 +224,17 @@ public class GlobalExceptionHandler { // 不包含的时候,才进行打印,避免 ex 堆栈过多 if (!IGNORE_ERROR_MESSAGES.contains(ex.getMessage())) { // 即使打印,也只打印第一层 StackTraceElement,并且使用 warn 在控制台输出,更容易看到 - StackTraceElement[] stackTrace = ex.getStackTrace(); - log.warn("[serviceExceptionHandler]\n\t{}", stackTrace[0]); + try { + StackTraceElement[] stackTraces = ex.getStackTrace(); + for (StackTraceElement stackTrace : stackTraces) { + if (ObjUtil.notEqual(stackTrace.getClassName(), ServiceExceptionUtil.class.getName())) { + log.warn("[serviceExceptionHandler]\n\t{}", stackTrace); + break; + } + } + } catch (Exception ignored) { + // 忽略日志,避免影响主流程 + } } return CommonResult.error(ex.getCode(), ex.getMessage()); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderSyncJob.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderSyncJob.java index b39032322..bd247d082 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderSyncJob.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderSyncJob.java @@ -22,9 +22,9 @@ import java.time.LocalDateTime; public class PayOrderSyncJob { /** - * 同步创建时间在 N 分钟之前的订单 + * 同步创建时间在 N 分钟之内的订单 * - * 为什么同步 10 分钟之前的订单? + * 为什么同步 10 分钟之内的订单? * 因为一个订单发起支付,到支付成功,大多数在 10 分钟内,需要保证轮询到。 * 如果设置为 30、60 或者更大时间范围,会导致轮询的订单太多,影响性能。当然,你也可以根据自己的业务情况来处理。 */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java index 6dde7d9a7..ba2bef7b8 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java @@ -14,22 +14,17 @@ import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import jakarta.validation.Validator; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.time.Duration; import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; /** @@ -42,25 +37,6 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; @Validated public class PayChannelServiceImpl implements PayChannelService { - /** - * {@link PayClient} 缓存,通过它异步清空 smsClientFactory - */ - @Getter - private final LoadingCache clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), - new CacheLoader() { - - @Override - public PayClient load(Long id) { - // 查询,然后尝试清空 - PayChannelDO channel = payChannelMapper.selectById(id); - if (channel != null) { - payClientFactory.createOrUpdatePayClient(channel.getId(), channel.getCode(), channel.getConfig()); - } - return payClientFactory.getPayClient(id); - } - - }); - @Resource private PayClientFactory payClientFactory; @@ -102,9 +78,6 @@ public class PayChannelServiceImpl implements PayChannelService { PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO) .setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig())); payChannelMapper.updateById(channel); - - // 清空缓存 - clearCache(channel.getId()); } /** @@ -135,18 +108,6 @@ public class PayChannelServiceImpl implements PayChannelService { // 删除 payChannelMapper.deleteById(id); - - // 清空缓存 - clearCache(id); - } - - /** - * 删除缓存 - * - * @param id 渠道编号 - */ - private void clearCache(Long id) { - clientCache.invalidate(id); } private PayChannelDO validateChannelExists(Long id) { @@ -202,7 +163,8 @@ public class PayChannelServiceImpl implements PayChannelService { @Override public PayClient getPayClient(Long id) { - return clientCache.getUnchecked(id); + PayChannelDO channel = validPayChannel(id); + return payClientFactory.createOrUpdatePayClient(id, channel.getCode(), channel.getConfig()); } } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java index 53f1a8c06..934b20bd8 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java @@ -23,9 +23,10 @@ public interface PayClientFactory { * @param channelId 渠道编号 * @param channelCode 渠道编码 * @param config 支付配置 + * @return 支付客户端 */ - void createOrUpdatePayClient(Long channelId, String channelCode, - Config config); + PayClient createOrUpdatePayClient(Long channelId, String channelCode, + Config config); /** * 注册支付客户端 Class,用于模块中实现的 PayClient diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index 815f8d4a6..1a50215cb 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -71,8 +71,8 @@ public class PayClientFactoryImpl implements PayClientFactory { @Override @SuppressWarnings("unchecked") - public void createOrUpdatePayClient(Long channelId, String channelCode, - Config config) { + public PayClient createOrUpdatePayClient(Long channelId, String channelCode, + Config config) { AbstractPayClient client = (AbstractPayClient) clients.get(channelId); if (client == null) { client = this.createPayClient(channelId, channelCode, config); @@ -81,6 +81,7 @@ public class PayClientFactoryImpl implements PayClientFactory { } else { client.refresh(config); } + return client; } @SuppressWarnings("unchecked") diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java index 5a073501d..7961ad510 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java @@ -34,7 +34,8 @@ public class WxNativePayClient extends AbstractWxPayClient { @Override protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO); + WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO) + .setProductId(reqDTO.getOutTradeNo()); // V2 必须传递 productId,无需在微信配置。该参数在 V3 简化,无需传递! // 执行请求 WxPayNativeOrderResult response = client.createOrder(request); From 41f56969e12b3a1b5aa80b0b509720853f18c272 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 24 Jul 2024 23:06:11 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91PAY=EF=BC=9A=E7=A7=BB=E9=99=A4=20PayClient=20?= =?UTF-8?q?=E7=BC=93=E5=AD=98=EF=BC=8C=E5=87=8F=E5=B0=91=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E6=80=A7=EF=BC=8C=E6=80=A7=E8=83=BD=E8=B6=B3=E5=A4=9F=EF=BC=88?= =?UTF-8?q?=E9=9D=9E=E9=AB=98=E9=A2=91=E8=AF=BB=E5=8F=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/channel/PayChannelServiceTest.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java index 45dcb4df2..229e71795 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java @@ -13,12 +13,12 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; import com.alibaba.fastjson.JSON; -import jakarta.annotation.Resource; -import jakarta.validation.Validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; +import jakarta.annotation.Resource; +import jakarta.validation.Validator; import java.util.Collections; import java.util.List; @@ -60,8 +60,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { PayChannelDO channel = channelMapper.selectById(channelId); assertPojoEquals(reqVO, channel, "config"); assertPojoEquals(config, channel.getConfig()); - // 校验缓存 - assertNull(channelService.getClientCache().getIfPresent(channelId)); } @Test @@ -102,8 +100,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, channel, "config"); assertPojoEquals(config, channel.getConfig()); - // 校验缓存 - assertNull(channelService.getClientCache().getIfPresent(channel.getId())); } @Test @@ -134,8 +130,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { channelService.deleteChannel(id); // 校验数据不存在了 assertNull(channelMapper.selectById(id)); - // 校验缓存 - assertNull(channelService.getClientCache().getIfPresent(id)); } @Test @@ -306,20 +300,20 @@ public class PayChannelServiceTest extends BaseDbUnitTest { PayChannelDO channel = randomPojo(PayChannelDO.class, o -> { o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); o.setConfig(randomAlipayPayClientConfig()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); channelMapper.insert(channel); // mock 参数 Long id = channel.getId(); // mock 方法 PayClient mockClient = mock(PayClient.class); - when(payClientFactory.getPayClient(eq(id))).thenReturn(mockClient); + when(payClientFactory.createOrUpdatePayClient(eq(id), eq(channel.getCode()), eq(channel.getConfig()))) + .thenReturn(mockClient); // 调用 PayClient client = channelService.getPayClient(id); // 断言 assertSame(client, mockClient); - verify(payClientFactory).createOrUpdatePayClient(eq(id), eq(channel.getCode()), - eq(channel.getConfig())); } public WxPayClientConfig randomWxPayClientConfig() { From 5fc4b5a64bf7d2919e6fde6136c7bf03eda05254 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 26 Jul 2024 09:23:32 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91PAY=EF=BC=9A=E5=BE=AE=E4=BF=A1=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E4=BD=BF=E7=94=A8=20certSerialNo=20=E6=9B=BF=E4=BB=A3?= =?UTF-8?q?=20privateCertContent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rule/dept/DeptDataPermissionRule.java | 2 +- .../impl/weixin/AbstractWxPayClient.java | 26 ++++++++----------- .../client/impl/weixin/WxPayClientConfig.java | 24 ++++++----------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java index af1a5a6fb..9774c59af 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java @@ -157,7 +157,7 @@ public class DeptDataPermissionRule implements DataPermissionRule { // 拼接条件 return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), // Parenthesis 的目的,是提供 (1,2,3) 的 () 左右括号 - new Parenthesis(new ExpressionList<>(CollectionUtils.convertList(deptIds, LongValue::new)))); + new Parenthesis(new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new)))); } private Expression buildUserExpression(String tableName, Alias tableAlias, Boolean self, Long userId) { diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index a8c50cf1c..9ad4b260f 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -36,6 +36,7 @@ import java.util.Objects; import static cn.hutool.core.date.DatePattern.*; import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V2; +import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V3; /** * 微信支付抽象类,实现微信统一的接口、以及部分实现(退款) @@ -59,19 +60,14 @@ public abstract class AbstractWxPayClient extends AbstractPayClient