From 3f410c273577498634b0588f8907eb5d34225b3d Mon Sep 17 00:00:00 2001 From: "zhijiantianya@gmail.com" Date: Tue, 18 Jul 2023 20:21:25 +0800 Subject: [PATCH] =?UTF-8?q?by=20gateway:=201.=20=E8=A1=A5=E5=85=A8=20chann?= =?UTF-8?q?el=20=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=202.=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E9=83=A8=E5=88=86=20order=20=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/test/core/util/RandomUtils.java | 6 +- .../service/order/TradeOrderServiceImpl.java | 4 +- .../module/pay/enums/ErrorCodeConstants.java | 64 +++-- .../admin/notify/PayNotifyController.java | 7 +- .../dataobject/order/PayOrderExtensionDO.java | 1 + .../pay/dal/mysql/order/PayOrderMapper.java | 6 - .../pay/service/app/PayAppServiceImpl.java | 14 +- .../channel/PayChannelServiceImpl.java | 11 +- .../service/demo/PayDemoOrderServiceImpl.java | 34 +-- .../pay/service/order/PayOrderService.java | 36 ++- .../service/order/PayOrderServiceImpl.java | 87 +++--- .../service/refund/PayRefundServiceImpl.java | 21 +- .../pay/service/app/PayAppServiceTest.java | 12 +- .../channel/PayChannelServiceTest.java | 136 +++++++++- .../service/order/PayOrderServiceTest.java | 256 +++++++++++++----- .../src/test/resources/sql/create_tables.sql | 28 +- 16 files changed, 493 insertions(+), 230 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java index 779803059..fbe6acfb6 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java @@ -55,6 +55,9 @@ public class RandomUtils { } return RandomUtil.randomInt(); }); + // LocalDateTime + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class, + (dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime()); // Boolean PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { // 如果是 deleted 的字段,返回非删除 @@ -82,7 +85,8 @@ public class RandomUtils { } public static LocalDateTime randomLocalDateTime() { - return LocalDateTimeUtil.of(randomDate()); + // 设置 Nano 为零的原因,避免 MySQL、H2 存储不到时间戳 + return LocalDateTimeUtil.of(randomDate()).withNano(0); } public static Short randomShort() { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java index 77b9376f3..48c709962 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -57,7 +57,7 @@ import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** @@ -308,7 +308,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); if (payOrder == null) { log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); - throw exception(PAY_ORDER_NOT_FOUND); + throw exception(cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND); } // 校验支付单已支付 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index 16174285f..3e1ea9da7 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -10,48 +10,46 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; public interface ErrorCodeConstants { // ========== APP 模块 1007000000 ========== - ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在"); - ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用"); - ErrorCode PAY_APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在支付订单,无法删除"); - ErrorCode PAY_APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1007000004, "支付应用存在退款订单,无法删除"); + ErrorCode APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在"); + ErrorCode APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用"); + ErrorCode APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在支付订单,无法删除"); + ErrorCode APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1007000004, "支付应用存在退款订单,无法删除"); // ========== CHANNEL 模块 1007001000 ========== - ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在"); - ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); - ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); - ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在"); - ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道"); + ErrorCode CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在"); + ErrorCode CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); + ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001004, "已存在相同的渠道"); // ========== ORDER 模块 1007002000 ========== - ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); - ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); - ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); - ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); - ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); + ErrorCode ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); + ErrorCode ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); + ErrorCode ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); + ErrorCode ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); + ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); // ========== ORDER 模块(拓展单) 1007003000 ========== - ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); - ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); + ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); + ErrorCode ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); // ========== 支付模块(退款) 1007006000 ========== - ErrorCode PAY_REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); - ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款"); - ErrorCode PAY_REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中"); - ErrorCode PAY_REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单"); - ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); - ErrorCode PAY_REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款"); + ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); + ErrorCode REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款"); + ErrorCode REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中"); + ErrorCode REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单"); + ErrorCode REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); + ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款"); // ========== 示例订单 1007900000 ========== - ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态"); - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配"); - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007900003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态"); - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1007900004, "示例订单更新支付状态失败,支付单金额不匹配"); - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(1007900005, "发起退款失败,示例订单未支付"); - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(1007900006, "发起退款失败,示例订单已退款"); - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007900007, "发起退款失败,退款订单不存在"); - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(1007900008, "发起退款失败,退款订单未退款成功"); - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007900009, "发起退款失败,退款单编号不匹配"); - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007900010, "发起退款失败,退款单金额不匹配"); + ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); + ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态"); + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配"); + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007900003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态"); + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1007900004, "示例订单更新支付状态失败,支付单金额不匹配"); + ErrorCode DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(1007900005, "发起退款失败,示例订单未支付"); + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(1007900006, "发起退款失败,示例订单已退款"); + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007900007, "发起退款失败,退款订单不存在"); + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(1007900008, "发起退款失败,退款订单未退款成功"); + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007900009, "发起退款失败,退款单编号不匹配"); + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007900010, "发起退款失败,退款单金额不匹配"); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java index e37ddfc11..04c080843 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java @@ -17,8 +17,7 @@ import javax.annotation.Resource; import javax.annotation.security.PermitAll; import java.util.Map; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND; @Tag(name = "管理后台 - 支付通知") @RestController @@ -47,7 +46,7 @@ public class PayNotifyController { PayClient payClient = payClientFactory.getPayClient(channelId); if (payClient == null) { log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw exception(CHANNEL_NOT_FOUND); } // 2. 解析通知数据 @@ -68,7 +67,7 @@ public class PayNotifyController { PayClient payClient = payClientFactory.getPayClient(channelId); if (payClient == null) { log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw exception(CHANNEL_NOT_FOUND); } // 2. 解析通知数据 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java index 15d3a96ea..9466243e1 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java @@ -15,6 +15,7 @@ import java.util.Map; /** * 支付订单拓展 DO * + * 每次调用支付渠道,都会生成一条对应记录 * * @author 芋道源码 */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java index 49c7d2fbf..3811cef96 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java @@ -44,12 +44,6 @@ public interface PayOrderMapper extends BaseMapperX { .orderByDesc("id")); } - default List findByIdListQueryOrderSubject(Collection idList) { - return selectList(new LambdaQueryWrapper() - .select(PayOrderDO::getId, PayOrderDO::getSubject) - .in(PayOrderDO::getId, idList)); - } - default Long selectCountByAppId(Long appId) { return selectCount(PayOrderDO::getAppId, appId); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java index 48e9c3c97..d7cc0010f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.pay.service.app; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO; @@ -9,10 +8,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO; import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper; -import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import org.springframework.context.annotation.Lazy; @@ -77,10 +73,10 @@ public class PayAppServiceImpl implements PayAppService { validateAppExists(id); // 校验关联数据是否存在 if (orderService.getOrderCountByAppId(id) > 0) { - throw exception(PAY_APP_EXIST_ORDER_CANT_DELETE); + throw exception(APP_EXIST_ORDER_CANT_DELETE); } if (refundService.getRefundCountByAppId(id) > 0) { - throw exception(PAY_APP_EXIST_REFUND_CANT_DELETE); + throw exception(APP_EXIST_REFUND_CANT_DELETE); } // 删除 @@ -89,7 +85,7 @@ public class PayAppServiceImpl implements PayAppService { private void validateAppExists(Long id) { if (appMapper.selectById(id) == null) { - throw exception(PAY_APP_NOT_FOUND); + throw exception(APP_NOT_FOUND); } } @@ -113,11 +109,11 @@ public class PayAppServiceImpl implements PayAppService { PayAppDO app = appMapper.selectById(id); // 校验是否存在 if (app == null) { - throw exception(ErrorCodeConstants.PAY_APP_NOT_FOUND); + throw exception(ErrorCodeConstants.APP_NOT_FOUND); } // 校验是否禁用 if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) { - throw exception(ErrorCodeConstants.PAY_APP_IS_DISABLE); + throw exception(ErrorCodeConstants.APP_IS_DISABLE); } return app; } 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 45604c04c..e76e4b35d 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 @@ -32,8 +32,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_EXISTS; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; /** * 支付渠道 Service 实现类 @@ -142,7 +141,7 @@ public class PayChannelServiceImpl implements PayChannelService { // 解析配置 Class payClass = PayChannelEnum.getByCode(code).getConfigClass(); if (ObjectUtil.isNull(payClass)) { - throw exception(CHANNEL_NOT_EXISTS); + throw exception(CHANNEL_NOT_FOUND); } PayClientConfig config = JsonUtils.parseObject2(configStr, payClass); Assert.notNull(config); @@ -167,7 +166,7 @@ public class PayChannelServiceImpl implements PayChannelService { private PayChannelDO validateChannelExists(Long id) { PayChannelDO channel = channelMapper.selectById(id); if (channel == null) { - throw exception(CHANNEL_NOT_EXISTS); + throw exception(CHANNEL_NOT_FOUND); } return channel; } @@ -203,10 +202,10 @@ public class PayChannelServiceImpl implements PayChannelService { private void validPayChannel(PayChannelDO channel) { if (channel == null) { - throw exception(ErrorCodeConstants.PAY_CHANNEL_NOT_FOUND); + throw exception(CHANNEL_NOT_FOUND); } if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) { - throw exception(ErrorCodeConstants.PAY_CHANNEL_IS_DISABLE); + throw exception(CHANNEL_IS_DISABLE); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java index 24e7b7572..f5ebf7961 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java @@ -119,7 +119,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { new PayDemoOrderDO().setPayStatus(true).setPayTime(LocalDateTime.now()) .setPayChannelCode(payOrder.getChannelCode())); if (updateCount == 0) { - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); + throw exception(DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); } } @@ -137,44 +137,44 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { // 1.1 校验订单是否存在 PayDemoOrderDO order = payDemoOrderMapper.selectById(id); if (order == null) { - throw exception(PAY_DEMO_ORDER_NOT_FOUND); + throw exception(DEMO_ORDER_NOT_FOUND); } // 1.2 校验订单未支付 if (order.getPayStatus()) { log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", id, toJsonString(order)); - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); + throw exception(DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); } // 1.3 校验支付订单匹配 if (notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", id, payOrderId, toJsonString(order)); - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); } // 2.1 校验支付单是否存在 PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); if (payOrder == null) { log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); - throw exception(PAY_ORDER_NOT_FOUND); + throw exception(ORDER_NOT_FOUND); } // 2.2 校验支付单已支付 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", id, payOrderId, toJsonString(payOrder)); - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); } // 2.3 校验支付金额一致 if (notEqual(payOrder.getPrice(), order.getPrice())) { log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", id, payOrderId, toJsonString(order), toJsonString(payOrder)); - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); } // 2.4 校验支付订单匹配(二次) if (notEqual(payOrder.getMerchantOrderId(), id.toString())) { log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", id, payOrderId, toJsonString(payOrder)); - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); } return payOrder; } @@ -203,15 +203,15 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { // 校验订单是否存在 PayDemoOrderDO order = payDemoOrderMapper.selectById(id); if (order == null) { - throw exception(PAY_DEMO_ORDER_NOT_FOUND); + throw exception(DEMO_ORDER_NOT_FOUND); } // 校验订单是否支付 if (!order.getPayStatus()) { - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID); + throw exception(DEMO_ORDER_REFUND_FAIL_NOT_PAID); } // 校验订单是否已退款 if (order.getPayRefundId() != null) { - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED); + throw exception(DEMO_ORDER_REFUND_FAIL_REFUNDED); } return order; } @@ -229,35 +229,35 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { // 1.1 校验示例订单 PayDemoOrderDO order = payDemoOrderMapper.selectById(id); if (order == null) { - throw exception(PAY_DEMO_ORDER_NOT_FOUND); + throw exception(DEMO_ORDER_NOT_FOUND); } // 1.2 校验退款订单匹配 if (Objects.equals(order.getPayOrderId(), payRefundId)) { log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]", id, payRefundId, toJsonString(order)); - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); } // 2.1 校验退款订单 PayRefundRespDTO payRefund = payRefundApi.getRefund(payRefundId); if (payRefund == null) { - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND); + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND); } // 2.2 if (!PayRefundStatusEnum.isSuccess(payRefund.getStatus())) { - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS); + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS); } // 2.3 校验退款金额一致 if (notEqual(payRefund.getRefundPrice(), order.getPrice())) { log.error("[validateDemoOrderCanRefunded][order({}) payRefund({}) 退款金额不匹配,请进行处理!order 数据是:{},payRefund 数据是:{}]", id, payRefundId, toJsonString(order), toJsonString(payRefund)); - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH); + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH); } // 2.4 校验退款订单匹配(二次) if (notEqual(payRefund.getMerchantOrderId(), id.toString())) { log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!payRefund 数据是:{}]", id, payRefundId, toJsonString(payRefund)); - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); } return payRefund; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index 8aadac856..7d429a219 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -49,41 +49,37 @@ public interface PayOrderService { Long getOrderCountByAppId(Long appId); /** - * 获得支付订单 - * 分页 + * 获得支付订单分页 * * @param pageReqVO 分页查询 - * @return 支付订单 - * 分页 + * @return 支付订单分页 */ PageResult getOrderPage(PayOrderPageReqVO pageReqVO); /** - * 获得支付订单 - * 列表, 用于 Excel 导出 + * 获得支付订单列表, 用于 Excel 导出 * * @param exportReqVO 查询条件 - * @return 支付订单 - * 列表 + * @return 支付订单列表 */ List getOrderList(PayOrderExportReqVO exportReqVO); /** - * 根据 ID 集合获取只包含商品名称的订单集合 - * - * @param idList 订单 ID 集合 - * @return 只包含商品名称的订单集合 - */ - List getOrderSubjectList(Collection idList); - - /** - * 根据订单 ID 集合获取订单商品名称Map集合 + * 获得支付订单列表 * * @param ids 订单 ID 集合 - * @return 订单商品 map 集合 + * @return 支付订单列表 + */ + List getOrderList(Collection ids); + + /** + * 获得支付订单 Map + * + * @param ids 订单 ID 集合 + * @return 支付订单 Map 集合 */ default Map getOrderSubjectMap(Collection ids) { - List list = getOrderSubjectList(ids); + List list = getOrderList(ids); return CollectionUtils.convertMap(list, PayOrderDO::getId); } @@ -122,4 +118,4 @@ public interface PayOrderService { */ void updateOrderRefundPrice(Long id, Integer incrRefundPrice); -} +} \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 0e5fee42e..49f38ee3b 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -102,10 +102,9 @@ public class PayOrderServiceImpl implements PayOrderService { return orderMapper.selectList(exportReqVO); } - // TODO @艿艿:需要优化。不确定这个方法的作用 @Override - public List getOrderSubjectList(Collection idList) { - return orderMapper.findByIdListQueryOrderSubject(idList); + public List getOrderList(Collection ids) { + return orderMapper.selectBatchIds(ids); } @Override @@ -165,7 +164,7 @@ public class PayOrderServiceImpl implements PayOrderService { notifyPayOrder(channel, unifiedOrderResp); // 如有渠道错误码,则抛出业务异常,提示用户 if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) { - throw exception(PAY_ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), + throw exception(ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), unifiedOrderResp.getChannelErrorMsg()); } // 此处需要读取最新的状态 @@ -177,13 +176,13 @@ public class PayOrderServiceImpl implements PayOrderService { private PayOrderDO validateOrderCanSubmit(Long id) { PayOrderDO order = orderMapper.selectById(id); if (order == null) { // 是否存在 - throw exception(PAY_ORDER_NOT_FOUND); + throw exception(ORDER_NOT_FOUND); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + throw exception(ORDER_STATUS_IS_NOT_WAITING); } if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期 - throw exception(PAY_ORDER_IS_EXPIRED); + throw exception(ORDER_IS_EXPIRED); } return order; } @@ -196,7 +195,7 @@ public class PayOrderServiceImpl implements PayOrderService { PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw exception(CHANNEL_NOT_FOUND); } return channel; } @@ -238,33 +237,6 @@ public class PayOrderServiceImpl implements PayOrderService { TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify)); } - @Override - public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) { - PayOrderDO order = orderMapper.selectById(id); - if (order == null) { - throw exception(PAY_ORDER_NOT_FOUND); - } - if (!PayOrderStatusEnum.isSuccess(order.getStatus())) { - throw exception(PAY_REFUND_PRICE_EXCEED); - } - if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { - throw exception(PAY_REFUND_PRICE_EXCEED); - } - - // 更新订单 - PayOrderDO updateObj = new PayOrderDO() - .setRefundPrice(order.getRefundPrice() + incrRefundPrice) - .setRefundTimes(order.getRefundTimes() + 1); - if (Objects.equals(updateObj.getRefundPrice(), order.getPrice())) { - updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) - .setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()); - } else { - updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) - .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus()); - } - orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj); - } - private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { // 情况一:支付成功的回调 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { @@ -301,21 +273,21 @@ public class PayOrderServiceImpl implements PayOrderService { // 1. 查询 PayOrderExtensionDO PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); if (orderExtension == null) { - throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); + throw exception(ORDER_EXTENSION_NOT_FOUND); } if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新]", orderExtension.getId()); return orderExtension; } if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } // 2. 更新 PayOrderExtensionDO int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(), PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } log.info("[updateOrderExtensionSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId()); return orderExtension; @@ -335,7 +307,7 @@ public class PayOrderServiceImpl implements PayOrderService { // 1. 判断 PayOrderDO 是否处于待支付 PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); if (order == null) { - throw exception(PAY_ORDER_NOT_FOUND); + throw exception(ORDER_NOT_FOUND); } if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 && Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) { @@ -343,7 +315,7 @@ public class PayOrderServiceImpl implements PayOrderService { return Pair.of(true, order); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + throw exception(ORDER_STATUS_IS_NOT_WAITING); } // 2. 更新 PayOrderDO @@ -354,7 +326,7 @@ public class PayOrderServiceImpl implements PayOrderService { .channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId()) .notifyTime(LocalDateTime.now()).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + throw exception(ORDER_STATUS_IS_NOT_WAITING); } log.info("[updateOrderExtensionSuccess][支付订单({}) 更新为已支付]", order.getId()); return Pair.of(false, order); @@ -368,7 +340,7 @@ public class PayOrderServiceImpl implements PayOrderService { // 1. 查询 PayOrderExtensionDO PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); if (orderExtension == null) { - throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); + throw exception(ORDER_EXTENSION_NOT_FOUND); } if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { // 如果已经是关闭,直接返回,不用重复更新 log.info("[updateOrderExtensionClosed][支付拓展单({}) 已经是支付关闭,无需更新]", orderExtension.getId()); @@ -380,7 +352,7 @@ public class PayOrderServiceImpl implements PayOrderService { return; } if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } // 2. 更新 PayOrderExtensionDO @@ -388,9 +360,36 @@ public class PayOrderServiceImpl implements PayOrderService { PayOrderExtensionDO.builder().status(PayOrderStatusEnum.CLOSED.getStatus()).channelNotifyData(toJsonString(notify)) .channelErrorCode(notify.getChannelErrorCode()).channelErrorMsg(notify.getChannelErrorMsg()).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } log.info("[updateOrderExtensionClosed][支付拓展单({}) 更新为支付关闭]", orderExtension.getId()); } + @Override + public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) { + PayOrderDO order = orderMapper.selectById(id); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + if (!PayOrderStatusEnum.isSuccess(order.getStatus())) { + throw exception(REFUND_PRICE_EXCEED); + } + if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { + throw exception(REFUND_PRICE_EXCEED); + } + + // 更新订单 + PayOrderDO updateObj = new PayOrderDO() + .setRefundPrice(order.getRefundPrice() + incrRefundPrice) + .setRefundTimes(order.getRefundTimes() + 1); + if (Objects.equals(updateObj.getRefundPrice(), order.getPrice())) { + updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) + .setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()); + } else { + updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) + .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus()); + } + orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java index 7914b70f6..5ffe87cb0 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java @@ -43,6 +43,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND; /** * 退款订单 Service 实现类 @@ -106,13 +107,13 @@ public class PayRefundServiceImpl implements PayRefundService { PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); + throw exception(CHANNEL_NOT_FOUND); } // 1.4 校验退款订单是否已经存在 PayRefundDO refund = refundMapper.selectByAppIdAndMerchantRefundId( app.getId(), reqDTO.getMerchantRefundId()); if (refund != null) { - throw exception(ErrorCodeConstants.PAY_REFUND_EXISTS); + throw exception(ErrorCodeConstants.REFUND_EXISTS); } // 2.1 插入退款单 @@ -153,25 +154,25 @@ public class PayRefundServiceImpl implements PayRefundService { private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) { PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId()); if (order == null) { - throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); + throw exception(ErrorCodeConstants.ORDER_NOT_FOUND); } // 校验状态,必须是支付状态 if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { - throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS); + throw exception(ErrorCodeConstants.ORDER_STATUS_IS_NOT_SUCCESS); } // 是否已经全额退款 if (PayOrderRefundStatusEnum.ALL.getStatus().equals(order.getRefundStatus())) { - throw exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED); + throw exception(ErrorCodeConstants.REFUND_ALL_REFUNDED); } // 校验金额 退款金额不能大于原定的金额 if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){ - throw exception(ErrorCodeConstants.PAY_REFUND_PRICE_EXCEED); + throw exception(ErrorCodeConstants.REFUND_PRICE_EXCEED); } // 是否有退款中的订单 if (refundMapper.selectCountByAppIdAndOrderId(reqDTO.getAppId(), order.getId(), PayRefundStatusEnum.WAITING.getStatus()) > 0) { - throw exception(ErrorCodeConstants.PAY_REFUND_HAS_REFUNDING); + throw exception(ErrorCodeConstants.REFUND_HAS_REFUNDING); } return order; } @@ -230,13 +231,13 @@ public class PayRefundServiceImpl implements PayRefundService { PayRefundDO refund = refundMapper.selectByAppIdAndNo( channel.getAppId(), notify.getOutRefundNo()); if (refund == null) { - throw exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND); + throw exception(ErrorCodeConstants.REFUND_NOT_FOUND); } if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 return; } if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { - throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING); + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); } // 1.2 更新 PayRefundDO @@ -247,7 +248,7 @@ public class PayRefundServiceImpl implements PayRefundService { .setChannelNotifyData(toJsonString(notify)); int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj); if (updateCounts == 0) { // 校验状态,必须是等待状态 - throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING); + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); } // 2. 更新订单 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java index f25bf8942..1934cfe97 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java @@ -90,7 +90,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); // 调用, 并断言异常 - assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND); + assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_FOUND); } @Test @@ -130,7 +130,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { Long id = randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> appService.deleteApp(id), PAY_APP_NOT_FOUND); + assertServiceException(() -> appService.deleteApp(id), APP_NOT_FOUND); } @Test @@ -144,7 +144,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { when(orderService.getOrderCountByAppId(eq(id))).thenReturn(10L); // 调用, 并断言异常 - assertServiceException(() -> appService.deleteApp(id), PAY_APP_EXIST_ORDER_CANT_DELETE); + assertServiceException(() -> appService.deleteApp(id), APP_EXIST_ORDER_CANT_DELETE); } @Test @@ -158,7 +158,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { when(refundService.getRefundCountByAppId(eq(id))).thenReturn(10L); // 调用, 并断言异常 - assertServiceException(() -> appService.deleteApp(id), PAY_APP_EXIST_REFUND_CANT_DELETE); + assertServiceException(() -> appService.deleteApp(id), APP_EXIST_REFUND_CANT_DELETE); } @Test @@ -239,7 +239,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { @Test public void testValidPayApp_notFound() { - assertServiceException(() -> appService.validPayApp(randomLongId()), PAY_APP_NOT_FOUND); + assertServiceException(() -> appService.validPayApp(randomLongId()), APP_NOT_FOUND); } @Test @@ -252,7 +252,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { Long id = dbApp.getId(); // 调用,并断言异常 - assertServiceException(() -> appService.validPayApp(id), PAY_APP_IS_DISABLE); + assertServiceException(() -> appService.validPayApp(id), APP_IS_DISABLE); } } 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 0a5d33495..2304257ed 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 @@ -26,8 +26,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_EXISTS; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; @Import({PayChannelServiceImpl.class}) @@ -51,6 +50,40 @@ public class PayChannelServiceTest extends BaseDbUnitTest { channelService.setChannelCache(null); } + @Test + public void testInitLocalCache() { + // mock 数据 + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, + o -> o.setConfig(randomWxPayClientConfig())); + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 + + // 调用 + channelService.initLocalCache(); + // 校验缓存 + assertEquals(1, channelService.getChannelCache().size()); + assertEquals(dbChannel, channelService.getChannelCache().get(0)); + } + + @Test + public void testRefreshLocalCache() { + // mock 数据 01 + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, + o -> o.setConfig(randomWxPayClientConfig())); + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 + channelService.initLocalCache(); + // mock 数据 02 + PayChannelDO dbChannel02 = randomPojo(PayChannelDO.class, + o -> o.setConfig(randomWxPayClientConfig())); + channelMapper.insert(dbChannel02);// @Sql: 先插入出一条存在的数据 + + // 调用 + channelService.refreshLocalCache(); + // 校验缓存 + assertEquals(2, channelService.getChannelCache().size()); + assertEquals(dbChannel, channelService.getChannelCache().get(0)); + assertEquals(dbChannel02, channelService.getChannelCache().get(1)); + } + @Test public void testCreateChannel_success() { // 准备参数 @@ -125,7 +158,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { }); // 调用, 并断言异常 - assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS); + assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_FOUND); } @Test @@ -153,7 +186,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { Long id = randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS); + assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_FOUND); } @Test @@ -214,6 +247,101 @@ public class PayChannelServiceTest extends BaseDbUnitTest { assertPojoEquals(channel, dbChannel); } + @Test + public void testValidPayChannel_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> channelService.validPayChannel(id), CHANNEL_NOT_FOUND); + } + + @Test + public void testValidPayChannel_isDisable() { + // mock 数据 + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); + o.setConfig(randomAlipayPayClientConfig()); + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); + }); + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbChannel.getId(); + + // 调用, 并断言异常 + assertServiceException(() -> channelService.validPayChannel(id), CHANNEL_IS_DISABLE); + } + + @Test + public void testValidPayChannel_success() { + // mock 数据 + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); + o.setConfig(randomAlipayPayClientConfig()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbChannel.getId(); + + // 调用 + PayChannelDO channel = channelService.validPayChannel(id); + // 断言异常 + assertPojoEquals(channel, dbChannel); + } + + @Test + public void testValidPayChannel_appIdAndCode() { + // mock 数据 + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); + o.setConfig(randomAlipayPayClientConfig()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long appId = dbChannel.getAppId(); + String code = dbChannel.getCode(); + + // 调用 + PayChannelDO channel = channelService.validPayChannel(appId, code); + // 断言异常 + assertPojoEquals(channel, dbChannel); + } + + @Test + public void testGetEnableChannelList() { + // 准备参数 + Long appId = randomLongId(); + // mock 数据 01(enable 不匹配) + PayChannelDO dbChannel01 = randomPojo(PayChannelDO.class, o -> { + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); + o.setConfig(randomAlipayPayClientConfig()); + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); + }); + channelMapper.insert(dbChannel01);// @Sql: 先插入出一条存在的数据 + // mock 数据 02(appId 不匹配) + PayChannelDO dbChannel02 = randomPojo(PayChannelDO.class, o -> { + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); + o.setConfig(randomAlipayPayClientConfig()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + channelMapper.insert(dbChannel02);// @Sql: 先插入出一条存在的数据 + // mock 数据 03 + PayChannelDO dbChannel03 = randomPojo(PayChannelDO.class, o -> { + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); + o.setConfig(randomAlipayPayClientConfig()); + o.setAppId(appId); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + channelMapper.insert(dbChannel03);// @Sql: 先插入出一条存在的数据 + + // 调用 + List channel = channelService.getEnableChannelList(appId); + // 断言异常 + assertPojoEquals(channel, dbChannel03); + } + public WxPayClientConfig randomWxPayClientConfig() { return new WxPayClientConfig() .setAppId(randomString()) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java index c225fa5b9..43c5d675e 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java @@ -3,32 +3,53 @@ package cn.iocoder.yudao.module.pay.service.order; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.pay.config.PayProperties; +import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.framework.test.core.util.AssertUtils; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; -import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; +import java.time.Duration; import java.time.LocalDateTime; import java.util.List; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.equalsAny; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * {@link PayOrderServiceImpl} 的单元测试类 @@ -43,6 +64,8 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @Resource private PayOrderMapper orderMapper; + @Resource + private PayOrderExtensionMapper orderExtensionMapper; @MockBean private PayClientFactory payClientFactory; @@ -55,42 +78,18 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @MockBean private PayNotifyService notifyService; - public String generateNo() { - return DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); - } - @Test public void testGetOrderPage() { - - String merchantOrderId = generateNo(); - String channelOrderId = generateNo(); - // mock 数据 PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 o.setAppId(1L); - o.setChannelId(1L); + o.setChannelId(10L); o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); - o.setMerchantOrderId(merchantOrderId); - o.setSubject("灿灿子的炸弹猫"); - o.setBody("斌斌子送给灿灿子的炸弹猫"); - o.setNotifyUrl("https://hc.com/lbh"); + o.setMerchantOrderId("110"); o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); - o.setPrice(10000); - o.setChannelFeeRate(0.01); - o.setChannelFeePrice(1L); o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); - o.setUserIp("127.0.0.1"); - o.setCreateTime(LocalDateTime.of(2018, 1, 1, 10, 1, 0)); - o.setExpireTime(LocalDateTime.of(2018, 1, 1, 10, 30, 0)); - o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2)); - o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); - o.setSuccessExtensionId(1L); + o.setCreateTime(buildTime(2018, 1, 15)); o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); - o.setRefundTimes(0); - o.setRefundPrice(0); - o.setChannelUserId("1008611"); - o.setChannelOrderNo(channelOrderId); - o.setUpdateTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); }); orderMapper.insert(dbOrder); // 测试 appId 不匹配 @@ -100,7 +99,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { // 测试 channelCode 不匹配 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); // 测试 merchantOrderId 不匹配 - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo()))); + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(randomString()))); // 测试 notifyStatus 不匹配 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); // 测试 status 不匹配 @@ -108,58 +107,38 @@ public class PayOrderServiceTest extends BaseDbUnitTest { // 测试 refundStatus 不匹配 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()))); // 测试 createTime 不匹配 - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10, - 1)))); + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(buildTime(2019, 1, 1)))); // 准备参数 PayOrderPageReqVO reqVO = new PayOrderPageReqVO(); reqVO.setAppId(1L); - reqVO.setChannelId(1L); + reqVO.setChannelId(10L); reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); - reqVO.setMerchantOrderId(merchantOrderId); + reqVO.setMerchantOrderId("110"); reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)})); + reqVO.setCreateTime(buildBetweenTime(2018, 1, 10, 2018, 1, 30)); + // 调用 PageResult pageResult = orderService.getOrderPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); assertPojoEquals(dbOrder, pageResult.getList().get(0)); - // assertEquals(0, dbOrder.getUpdateTime().compareTo(pageResult.getList().get(0).getUpdateTime())); } @Test public void testGetOrderList() { // mock 数据 - String merchantOrderId = generateNo(); - String channelOrderId = generateNo(); PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 o.setAppId(1L); - o.setChannelId(1L); + o.setChannelId(10L); o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); - o.setMerchantOrderId(merchantOrderId); - o.setSubject("灿灿子的炸弹猫"); - o.setBody("斌斌子送给灿灿子的炸弹猫"); - o.setNotifyUrl("https://hc.com/lbh"); + o.setMerchantOrderId("110"); o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); - o.setPrice(10000); - o.setChannelFeeRate(0.01); - o.setChannelFeePrice(1L); o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); - o.setUserIp("127.0.0.1"); - o.setCreateTime(LocalDateTime.of(2018, 1, 1, 10, 1, 0)); - o.setExpireTime(LocalDateTime.of(2018, 1, 1, 10, 30, 0)); - o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2)); - o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); - o.setSuccessExtensionId(1L); + o.setCreateTime(buildTime(2018, 1, 15)); o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); - o.setRefundTimes(0); - o.setRefundPrice(0); - o.setChannelUserId("1008611"); - o.setChannelOrderNo(channelOrderId); - o.setUpdateTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); - }); orderMapper.insert(dbOrder); // 测试 appId 不匹配 @@ -169,7 +148,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { // 测试 channelCode 不匹配 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); // 测试 merchantOrderId 不匹配 - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo()))); + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(randomString()))); // 测试 notifyStatus 不匹配 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); // 测试 status 不匹配 @@ -177,18 +156,17 @@ public class PayOrderServiceTest extends BaseDbUnitTest { // 测试 refundStatus 不匹配 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()))); // 测试 createTime 不匹配 - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10, - 1)))); + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(buildTime(2019, 1, 1)))); // 准备参数 PayOrderExportReqVO reqVO = new PayOrderExportReqVO(); reqVO.setAppId(1L); - reqVO.setChannelId(1L); + reqVO.setChannelId(10L); reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); - reqVO.setMerchantOrderId(merchantOrderId); + reqVO.setMerchantOrderId("110"); reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)})); + reqVO.setCreateTime(buildBetweenTime(2018, 1, 10, 2018, 1, 30)); // 调用 List list = orderService.getOrderList(reqVO); @@ -197,4 +175,154 @@ public class PayOrderServiceTest extends BaseDbUnitTest { assertPojoEquals(dbOrder, list.get(0)); } + @Test + public void testCreateOrder_success() { + // mock 参数 + PayOrderCreateReqDTO reqDTO = randomPojo(PayOrderCreateReqDTO.class, + o -> o.setAppId(1L).setMerchantOrderId("10") + .setSubject(randomString()).setBody(randomString())); + // mock 方法 + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L).setOrderNotifyUrl("http://127.0.0.1")); + when(appService.validPayApp(eq(reqDTO.getAppId()))).thenReturn(app); + + // 调用 + Long orderId = orderService.createOrder(reqDTO); + // 断言 + PayOrderDO order = orderMapper.selectById(orderId); + assertPojoEquals(order, reqDTO); + assertEquals(order.getAppId(), 1L); + assertEquals(order.getNotifyUrl(), "http://127.0.0.1"); + assertEquals(order.getStatus(), PayOrderStatusEnum.WAITING.getStatus()); + assertEquals(order.getRefundStatus(), PayOrderRefundStatusEnum.NO.getStatus()); + assertEquals(order.getRefundTimes(), 0); + assertEquals(order.getRefundPrice(), 0); + } + + @Test + public void testCreateOrder_exists() { + // mock 参数 + PayOrderCreateReqDTO reqDTO = randomPojo(PayOrderCreateReqDTO.class, + o -> o.setAppId(1L).setMerchantOrderId("10")); + // mock 数据 + PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> o.setAppId(1L).setMerchantOrderId("10")); + orderMapper.insert(dbOrder); + + // 调用 + Long orderId = orderService.createOrder(reqDTO); + // 断言 + PayOrderDO order = orderMapper.selectById(orderId); + assertPojoEquals(dbOrder, order); + } + + @Test + public void testSubmitOrder_notFound() { + // 准备参数 + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class); + String userIp = randomString(); + + // 调用, 并断言异常 + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_NOT_FOUND); + } + + @Test + public void testSubmitOrder_notWaiting() { + // mock 数据(order) + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())); + orderMapper.insert(order); + // 准备参数 + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId())); + String userIp = randomString(); + + // 调用, 并断言异常 + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_STATUS_IS_NOT_WAITING); + } + + @Test + public void testSubmitOrder_expired() { + // mock 数据(order) + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) + .setExpireTime(addTime(Duration.ofDays(-1)))); + orderMapper.insert(order); + // 准备参数 + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId())); + String userIp = randomString(); + + // 调用, 并断言异常 + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_IS_EXPIRED); + } + + @Test + public void testSubmitOrder_channelNotFound() { + // mock 数据(order) + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) + .setAppId(1L)); + orderMapper.insert(order); + // 准备参数 + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()) + .setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())); + String userIp = randomString(); + // mock 方法(app) + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L)); + when(appService.validPayApp(eq(1L))).thenReturn(app); + // mock 方法(channel) + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setCode(PayChannelEnum.ALIPAY_APP.getCode())); + when(channelService.validPayChannel(eq(1L), eq(PayChannelEnum.ALIPAY_APP.getCode()))) + .thenReturn(channel); + + // 调用, 并断言异常 + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), CHANNEL_NOT_FOUND); + } + + @Test // 调用 unifiedOrder 接口,返回存在渠道错误 + public void testSubmitOrder_channelError() { + // mock 数据(order) + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) + .setAppId(1L)); + orderMapper.insert(order); + // 准备参数 + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()) + .setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())); + String userIp = randomString(); + // mock 方法(app) + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L)); + when(appService.validPayApp(eq(1L))).thenReturn(app); + // mock 方法(channel) + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L) + .setCode(PayChannelEnum.ALIPAY_APP.getCode())); + when(channelService.validPayChannel(eq(1L), eq(PayChannelEnum.ALIPAY_APP.getCode()))) + .thenReturn(channel); + // mock 方法(client) + PayClient client = mock(PayClient.class); + when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); + when(client.unifiedOrder(any(PayOrderUnifiedReqDTO.class))).thenThrow(new NullPointerException()); + + // 调用,并断言异常 + assertThrows(NullPointerException.class, () -> orderService.submitOrder(reqVO, userIp)); + // 断言,数据记录(PayOrderExtensionDO) + PayOrderExtensionDO orderExtension = orderExtensionMapper.selectOne(null); + assertNotNull(orderExtension); + assertThat(orderExtension).extracting("no", "orderId").isNotNull(); + assertThat(orderExtension) + .extracting("channelId", "channelCode","userIp" ,"status", "channelExtras", + "channelErrorCode", "channelErrorMsg", "channelNotifyData") + .containsExactly(10L, PayChannelEnum.ALIPAY_APP.getCode(), userIp, + PayOrderStatusEnum.WAITING.getStatus(), reqVO.getChannelExtras(), + null, null, null); + } + + @Test // 【成功】支付结果为等待中 + public void testSubmitOrder_waitingResult() { + + } + + @Test // 【成功】支付结果为已完成 + public void testSubmitOrder_successResult() { + + } + + @Test // 【成功】支付结果为已关闭 + public void testSubmitOrder_closedResult() { + + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql b/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql index fea1365a5..82c8d1016 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql @@ -40,9 +40,9 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( `body` varchar(128) NOT NULL, `notify_url` varchar(1024) NOT NULL, `notify_status` tinyint(4) NOT NULL, - `amount` bigint(20) NOT NULL, + `price` bigint(20) NOT NULL, `channel_fee_rate` double DEFAULT 0, - `channel_fee_amount` bigint(20) DEFAULT 0, + `channel_fee_price` bigint(20) DEFAULT 0, `status` tinyint(4) NOT NULL, `user_ip` varchar(50) NOT NULL, `expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -50,8 +50,8 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, `success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号', `refund_status` tinyint(4) NOT NULL, - `refund_times` tinyint(4) NOT NULL, - `refund_amount` bigint(20) NOT NULL, + `refund_times` int NOT NULL, + `refund_price` bigint(20) NOT NULL, `channel_user_id` varchar(255) DEFAULT NULL, `channel_order_no` varchar(64) DEFAULT NULL, `creator` varchar(64) DEFAULT '', @@ -62,6 +62,26 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( PRIMARY KEY ("id") ) COMMENT = '支付订单'; +CREATE TABLE IF NOT EXISTS `pay_order_extension` ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `no` varchar(64) NOT NULL, + `order_id` bigint(20) NOT NULL, + `channel_id` bigint(20) NOT NULL, + `channel_code` varchar(32) NOT NULL, + `user_ip` varchar(50) NULL DEFAULT NULL, + `status` tinyint(4) NOT NULL, + `channel_extras` varchar(1024) NULL DEFAULT NULL, + `channel_error_code` varchar(64) NULL, + `channel_error_msg` varchar(64) NULL, + `channel_notify_data` varchar(64) NULL, + `creator` varchar(64) NULL DEFAULT '', + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updater` varchar(64) NULL DEFAULT '', + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT = '支付订单拓展'; + CREATE TABLE IF NOT EXISTS `pay_refund` ( "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, `app_id` bigint(20) NOT NULL,