From 1c282bd3cb7ada650947b6978d6943df392c1e13 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 18 Jul 2023 13:00:22 +0800 Subject: [PATCH 01/11] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20PayClient=20=E9=80=80=E6=AC=BE=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E8=BF=94=E5=9B=9E=E4=B8=9A=E5=8A=A1=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=20errorCode=20+=20errorMsg=20=E9=94=99=E8=AF=AF=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/dto/refund/PayRefundRespDTO.java | 68 +++++++++++++ .../core/client/impl/AbstractPayClient.java | 17 +++- .../impl/alipay/AbstractAlipayPayClient.java | 36 +++---- .../impl/weixin/AbstractWxPayClient.java | 99 +++++++------------ 4 files changed, 130 insertions(+), 90 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundRespDTO.java index 6d10dc9a0..3184f278d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundRespDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundRespDTO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.pay.core.client.dto.refund; +import cn.iocoder.yudao.framework.pay.core.client.exception.PayException; import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; import lombok.Data; @@ -44,4 +45,71 @@ public class PayRefundRespDTO { */ private Object rawData; + /** + * 调用渠道的错误码 + * + * 注意:这里返回的是业务异常,而是不系统异常。 + * 如果是系统异常,则会抛出 {@link PayException} + */ + private String channelErrorCode; + /** + * 调用渠道报错时,错误信息 + */ + private String channelErrorMsg; + + private PayRefundRespDTO() { + } + + /** + * 创建【WAITING】状态的退款返回 + */ + public static PayRefundRespDTO waitingOf(String channelRefundNo, + String outRefundNo, Object rawData) { + PayRefundRespDTO respDTO = new PayRefundRespDTO(); + respDTO.status = PayRefundStatusRespEnum.WAITING.getStatus(); + respDTO.channelRefundNo = channelRefundNo; + // 相对通用的字段 + respDTO.outRefundNo = outRefundNo; + respDTO.rawData = rawData; + return respDTO; + } + + /** + * 创建【SUCCESS】状态的退款返回 + */ + public static PayRefundRespDTO successOf(String channelRefundNo, LocalDateTime successTime, + String outRefundNo, Object rawData) { + PayRefundRespDTO respDTO = new PayRefundRespDTO(); + respDTO.status = PayRefundStatusRespEnum.SUCCESS.getStatus(); + respDTO.channelRefundNo = channelRefundNo; + respDTO.successTime = successTime; + // 相对通用的字段 + respDTO.outRefundNo = outRefundNo; + respDTO.rawData = rawData; + return respDTO; + } + + /** + * 创建【FAILURE】状态的退款返回 + */ + public static PayRefundRespDTO failureOf(String outRefundNo, Object rawData) { + return failureOf(null, null, + outRefundNo, rawData); + } + + /** + * 创建【FAILURE】状态的退款返回 + */ + public static PayRefundRespDTO failureOf(String channelErrorCode, String channelErrorMsg, + String outRefundNo, Object rawData) { + PayRefundRespDTO respDTO = new PayRefundRespDTO(); + respDTO.status = PayRefundStatusRespEnum.FAILURE.getStatus(); + respDTO.channelErrorCode = channelErrorCode; + respDTO.channelErrorMsg = channelErrorMsg; + // 相对通用的字段 + respDTO.outRefundNo = outRefundNo; + respDTO.rawData = rawData; + return respDTO; + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java index 8be5aa498..194432738 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -98,7 +98,8 @@ public abstract class AbstractPayClient implemen try { return doParseOrderNotify(params, body); } catch (Throwable ex) { - log.error("[parseOrderNotify][params({}) body({}) 解析失败]", params, body, ex); + log.error("[parseOrderNotify][客户端({}) params({}) body({}) 解析失败]", + getId(), params, body, ex); throw buildPayException(ex); } } @@ -129,6 +130,20 @@ public abstract class AbstractPayClient implemen protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable; + @Override + public PayRefundRespDTO parseRefundNotify(Map params, String body) { + try { + return doParseRefundNotify(params, body); + } catch (Throwable ex) { + log.error("[parseRefundNotify][客户端({}) params({}) body({}) 解析失败]", + getId(), params, body, ex); + throw buildPayException(ex); + } + } + + protected abstract PayRefundRespDTO doParseRefundNotify(Map params, String body) + throws Throwable; + // ========== 各种工具方法 ========== private PayException buildPayException(Throwable ex) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java index f11c88ec0..ebca93952 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java @@ -29,7 +29,6 @@ import java.util.Objects; import java.util.function.Supplier; import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款) @@ -94,7 +93,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient params, String body) { + public PayRefundRespDTO doParseRefundNotify(Map params, String body) { // 补充说明:支付宝退款时,没有回调,这点和微信支付是不同的。并且,退款分成部分退款、和全部退款。 // ① 部分退款:是会有回调,但是它回调的是订单状态的同步回调,不是退款订单的回调 // ② 全部退款:Wap 支付有订单状态的同步回调,但是 PC/扫码又没有 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index 05534d0b6..e6a8663c5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; -import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; @@ -163,9 +162,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient params, String body) { - try { - // 微信支付 v2 回调结果处理 - switch (config.getApiVersion()) { - case API_VERSION_V2: - return parseRefundNotifyV2(body); - case WxPayClientConfig.API_VERSION_V3: - return parseRefundNotifyV3(body); - default: - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); - } - } catch (WxPayException e) { - log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); - throw new RuntimeException(e); - // TODO 芋艿:缺一个异常翻译 + public PayRefundRespDTO doParseRefundNotify(Map params, String body) throws WxPayException { + switch (config.getApiVersion()) { + case API_VERSION_V2: + return doParseRefundNotifyV2(body); + case WxPayClientConfig.API_VERSION_V3: + return parseRefundNotifyV3(body); + default: + throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); } } - @SuppressWarnings("DuplicatedCode") - private PayRefundRespDTO parseRefundNotifyV2(String body) throws WxPayException { + private PayRefundRespDTO doParseRefundNotifyV2(String body) throws WxPayException { // 1. 解析回调 WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body); - WxPayRefundNotifyResult.ReqInfo responseResult = response.getReqInfo(); + WxPayRefundNotifyResult.ReqInfo result = response.getReqInfo(); // 2. 构建结果 - PayRefundRespDTO notify = new PayRefundRespDTO() - .setChannelRefundNo(responseResult.getRefundId()) - .setOutRefundNo(responseResult.getOutRefundNo()) - .setRawData(response); - if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) { - notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) - .setSuccessTime(parseDateV2B(responseResult.getSuccessTime())); - } else { - notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); + if (Objects.equals("SUCCESS", result.getRefundStatus())) { + return PayRefundRespDTO.successOf(result.getRefundId(), parseDateV2B(result.getSuccessTime()), + result.getOutRefundNo(), response); } - return notify; + return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response); } - @SuppressWarnings("DuplicatedCode") private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException { // 1. 解析回调 WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null); - WxPayRefundNotifyV3Result.DecryptNotifyResult responseResult = response.getResult(); + WxPayRefundNotifyV3Result.DecryptNotifyResult result = response.getResult(); // 2. 构建结果 - PayRefundRespDTO notify = new PayRefundRespDTO() - .setChannelRefundNo(responseResult.getRefundId()) - .setOutRefundNo(responseResult.getOutRefundNo()) - .setRawData(response); - if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) { - notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) - .setSuccessTime(parseDateV3(responseResult.getSuccessTime())); - } else { - notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); + if (Objects.equals("SUCCESS", result.getRefundStatus())) { + return PayRefundRespDTO.successOf(result.getRefundId(), parseDateV3(result.getSuccessTime()), + result.getOutRefundNo(), response); } - return notify; + return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response); } // ========== 各种工具方法 ========== From 3f410c273577498634b0588f8907eb5d34225b3d Mon Sep 17 00:00:00 2001 From: "zhijiantianya@gmail.com" Date: Tue, 18 Jul 2023 20:21:25 +0800 Subject: [PATCH 02/11] =?UTF-8?q?by=20gateway:=201.=20=E8=A1=A5=E5=85=A8?= =?UTF-8?q?=20channel=20=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=202.=20?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=83=A8=E5=88=86=20order=20=E5=8D=95?= =?UTF-8?q?=E5=85=83=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, From 888c48820662de70e8df18623f6660f179abd01c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 18 Jul 2023 22:36:03 +0800 Subject: [PATCH 03/11] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20PayClient=20=E9=80=80=E6=AC=BE=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E8=BF=94=E5=9B=9E=E4=B8=9A=E5=8A=A1=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=20errorCode=20+=20errorMsg=20=E9=94=99=E8=AF=AF=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/refund/PayRefundStatusRespEnum.java | 4 ++ .../pay/enums/refund/PayRefundStatusEnum.java | 4 ++ .../service/order/PayOrderServiceImpl.java | 8 +++- .../service/refund/PayRefundServiceImpl.java | 47 ++++++++++++++++--- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/refund/PayRefundStatusRespEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/refund/PayRefundStatusRespEnum.java index 74b2f8d7d..9a44e3194 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/refund/PayRefundStatusRespEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/refund/PayRefundStatusRespEnum.java @@ -25,4 +25,8 @@ public enum PayRefundStatusRespEnum { return Objects.equals(status, SUCCESS.getStatus()); } + public static boolean isFailure(Integer status) { + return Objects.equals(status, FAILURE.getStatus()); + } + } diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java index 29fdc923b..4ae14cc67 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java @@ -25,4 +25,8 @@ public enum PayRefundStatusEnum { return Objects.equals(status, SUCCESS.getStatus()); } + public static boolean isFailure(Integer status) { + return Objects.equals(status, FAILURE.getStatus()); + } + } 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 49f38ee3b..997a3f08a 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 @@ -237,6 +237,7 @@ public class PayOrderServiceImpl implements PayOrderService { TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify)); } + // TODO 芋艿:事务问题 private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { // 情况一:支付成功的回调 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { @@ -372,7 +373,7 @@ public class PayOrderServiceImpl implements PayOrderService { throw exception(ORDER_NOT_FOUND); } if (!PayOrderStatusEnum.isSuccess(order.getStatus())) { - throw exception(REFUND_PRICE_EXCEED); + throw exception(ORDER_STATUS_IS_NOT_SUCCESS); } if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { throw exception(REFUND_PRICE_EXCEED); @@ -389,7 +390,10 @@ public class PayOrderServiceImpl implements PayOrderService { updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus()); } - orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj); + int updateCount = orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj); + if (updateCount == 0) { + throw exception(ORDER_STATUS_IS_NOT_SUCCESS); + } } } 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 5ffe87cb0..bf45349a7 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 @@ -206,7 +206,6 @@ public class PayRefundServiceImpl implements PayRefundService { } @Override - @Transactional(rollbackFor = Exception.class) public void notifyRefund(Long channelId, PayRefundRespDTO notify) { // 校验支付渠道是否有效 channelService.validPayChannel(channelId); @@ -218,15 +217,20 @@ public class PayRefundServiceImpl implements PayRefundService { TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify)); } + // TODO 芋艿:事务问题 private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) { + // 情况一:退款成功 if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) { notifyRefundSuccess(channel, notify); - } else { + return; + } + // 情况二:退款失败 + if (PayRefundStatusRespEnum.isFailure(notify.getStatus())) { notifyRefundFailure(channel, notify); } } - private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { + public void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { // 1.1 查询 PayRefundDO PayRefundDO refund = refundMapper.selectByAppIdAndNo( channel.getAppId(), notify.getOutRefundNo()); @@ -234,12 +238,12 @@ public class PayRefundServiceImpl implements PayRefundService { throw exception(ErrorCodeConstants.REFUND_NOT_FOUND); } if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 + log.info("[notifyRefundSuccess][退款订单({}) 已经是退款成功,无需更新]", refund.getId()); return; } if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); } - // 1.2 更新 PayRefundDO PayRefundDO updateRefundObj = new PayRefundDO() .setSuccessTime(notify.getSuccessTime()) @@ -250,17 +254,46 @@ public class PayRefundServiceImpl implements PayRefundService { if (updateCounts == 0) { // 校验状态,必须是等待状态 throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); } + log.info("[notifyRefundSuccess][退款订单({}) 更新为退款成功]", refund.getId()); // 2. 更新订单 orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice()); - // 3. 插入退款通知记录 + // 3. 插入退款通知记录 TODO 芋艿:退款成功 notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); } - private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { - // TODO 芋艿:未实现 + @Transactional(rollbackFor = Exception.class) + public void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { + // 1.1 查询 PayRefundDO + PayRefundDO refund = refundMapper.selectByAppIdAndNo( + channel.getAppId(), notify.getOutRefundNo()); + if (refund == null) { + throw exception(ErrorCodeConstants.REFUND_NOT_FOUND); + } + if (PayRefundStatusEnum.isFailure(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 + log.info("[notifyRefundSuccess][退款订单({}) 已经是退款关闭,无需更新]", refund.getId()); + return; + } + if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); + } + // 1.2 更新 PayRefundDO + PayRefundDO updateRefundObj = new PayRefundDO() + .setChannelRefundNo(notify.getChannelRefundNo()) + .setStatus(PayRefundStatusEnum.FAILURE.getStatus()) + .setChannelNotifyData(toJsonString(notify)) + .setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg()); + int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj); + if (updateCounts == 0) { // 校验状态,必须是等待状态 + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); + } + log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId()); + + // 2. 插入退款通知记录 TODO 芋艿:退款失败 + notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() + .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); } } From 5dcb3db5d7ae8c205a7f2f61354211c7604b8f54 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 19 Jul 2023 09:50:24 +0800 Subject: [PATCH 04/11] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=AE=A2=E5=8D=95=E7=AE=A1=E7=90=86=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/order/PayOrderController.java | 25 ++--- .../admin/order/vo/PayOrderDetailsRespVO.java | 14 +-- .../pay/convert/order/PayOrderConvert.java | 14 ++- .../service/order/PayOrderServiceImpl.java | 24 +++- .../service/refund/PayRefundServiceImpl.java | 2 +- yudao-ui-admin/src/views/pay/order/index.vue | 103 +++++------------- 6 files changed, 73 insertions(+), 109 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java index 6acc41ceb..5bbf5c96b 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java @@ -56,31 +56,20 @@ public class PayOrderController { return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id))); } - // TODO 芋艿:看看怎么优化下; @GetMapping("/get-detail") @Operation(summary = "获得支付订单详情") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('pay:order:query')") public CommonResult getOrderDetail(@RequestParam("id") Long id) { PayOrderDO order = payOrderService.getOrder(id); - if (ObjectUtil.isNull(order)) { - return success(new PayOrderDetailsRespVO()); + if (order == null) { + return success(null); } - PayAppDO appDO = appService.getApp(order.getAppId()); - PayChannelEnum channelEnum = PayChannelEnum.getByCode(order.getChannelCode()); - - // TODO @aquan:文案,都是前端 format; - PayOrderDetailsRespVO respVO = PayOrderConvert.INSTANCE.orderDetailConvert(order); - respVO.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); - respVO.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); - - PayOrderExtensionDO extensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); - if (ObjectUtil.isNotNull(extensionDO)) { - respVO.setPayOrderExtension(PayOrderConvert.INSTANCE.orderDetailExtensionConvert(extensionDO)); - } - - return success(respVO); + // 拼接返回 + PayAppDO app = appService.getApp(order.getAppId()); + PayOrderExtensionDO orderExtension = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); + return success(PayOrderConvert.INSTANCE.convert(order, orderExtension, app)); } @PostMapping("/submit") @@ -90,6 +79,7 @@ public class PayOrderController { return success(respVO); } + // TODO 芋艿:优化 @GetMapping("/page") @Operation(summary = "获得支付订单分页") @PreAuthorize("@ss.hasPermission('pay:order:query')") @@ -116,6 +106,7 @@ public class PayOrderController { return success(new PageResult<>(pageList, pageResult.getTotal())); } + // TODO 芋艿:优化 @GetMapping("/export-excel") @Operation(summary = "导出支付订单Excel") @PreAuthorize("@ss.hasPermission('pay:order:export')") diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java index 759450c93..a6a5f684a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java @@ -13,32 +13,30 @@ import java.time.LocalDateTime; @ToString(callSuper = true) public class PayOrderDetailsRespVO extends PayOrderBaseVO { - @Schema(description = "支付订单编号") + @Schema(description = "支付订单编号", required = true, example = "1024") private Long id; - @Schema(description = "应用名称") + @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") private String appName; - @Schema(description = "渠道编号名称") - private String channelCodeName; - - @Schema(description = "创建时间") + @Schema(description = "创建时间", required = true) private LocalDateTime createTime; /** * 支付订单扩展 */ - private PayOrderExtension payOrderExtension; + private PayOrderExtension extension; @Data @Schema(description = "支付订单扩展") public static class PayOrderExtension { - @Schema(description = "支付订单号") + @Schema(description = "支付订单号", required = true, example = "1024") private String no; @Schema(description = "支付异步通知的内容") private String channelNotifyData; + } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java index 647fe3dbb..e9f0ebf43 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; import org.mapstruct.Mapper; @@ -30,9 +31,16 @@ public interface PayOrderConvert { PayOrderRespDTO convert2(PayOrderDO order); - PayOrderDetailsRespVO orderDetailConvert(PayOrderDO bean); - - PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean); + default PayOrderDetailsRespVO convert(PayOrderDO order, PayOrderExtensionDO orderExtension, PayAppDO app) { + PayOrderDetailsRespVO respVO = convertDetail(order); + respVO.setExtension(convert(orderExtension)); + if (app != null) { + respVO.setAppName(app.getName()); + } + return respVO; + } + PayOrderDetailsRespVO convertDetail(PayOrderDO bean); + PayOrderDetailsRespVO.PayOrderExtension convert(PayOrderExtensionDO bean); List convertList(List list); 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 997a3f08a..e7551ba57 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 @@ -5,6 +5,7 @@ import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; 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; @@ -161,7 +162,7 @@ public class PayOrderServiceImpl implements PayOrderService { // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功 if (unifiedOrderResp != null) { - notifyPayOrder(channel, unifiedOrderResp); + getSelf().notifyPayOrder(channel, unifiedOrderResp); // 如有渠道错误码,则抛出业务异常,提示用户 if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) { throw exception(ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), @@ -234,11 +235,17 @@ public class PayOrderServiceImpl implements PayOrderService { // 校验支付渠道是否有效 PayChannelDO channel = channelService.validPayChannel(channelId); // 更新支付订单为已支付 - TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify)); + TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyPayOrder(channel, notify)); } - // TODO 芋艿:事务问题 - private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { + /** + * 通知并更新订单的支付结果 + * + * @param channel 支付渠道 + * @param notify 通知 + */ + @Transactional(rollbackFor = Exception.class) // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyPayOrder(channel, notify) 调用,否则事务不生效 + public void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { // 情况一:支付成功的回调 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { notifyOrderSuccess(channel, notify); @@ -396,4 +403,13 @@ public class PayOrderServiceImpl implements PayOrderService { } } + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private PayOrderServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } 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 bf45349a7..516c137e8 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 @@ -137,7 +137,7 @@ public class PayRefundServiceImpl implements PayRefundService { .setOutRefundNo(refund.getNo()) .setNotifyUrl(genChannelRefundNotifyUrl(channel)) .setReason(reqDTO.getReason()); - PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO); // TODO 增加一个 channelErrorCode、channelErrorMsg 字段 + PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO); // 2.3 处理退款返回 notifyRefund(channel, refundRespDTO); diff --git a/yudao-ui-admin/src/views/pay/order/index.vue b/yudao-ui-admin/src/views/pay/order/index.vue index 6f3fe5006..661b30c4e 100755 --- a/yudao-ui-admin/src/views/pay/order/index.vue +++ b/yudao-ui-admin/src/views/pay/order/index.vue @@ -11,7 +11,7 @@ - + @@ -24,13 +24,13 @@ - - @@ -102,6 +102,7 @@ + @@ -124,7 +125,7 @@ @@ -134,7 +135,7 @@ - + {{ orderDetail.appName }} @@ -149,8 +150,8 @@ {{ orderDetail.channelOrderNo }} - - {{ orderDetail.payOrderExtension.no }} + + {{ orderDetail.extension.no }} @@ -176,7 +177,9 @@ - {{ orderDetail.channelCodeName }} + + + {{ orderDetail.userIp }} @@ -194,7 +197,7 @@ {{ orderDetail.body }} - {{ orderDetail.payOrderExtension.channelNotifyData }} + {{ orderDetail.extension.channelNotifyData }} @@ -204,34 +207,6 @@ diff --git a/yudao-ui-admin/src/views/pay/order/index.vue b/yudao-ui-admin/src/views/pay/order/index.vue index 1ceb52918..6d7be5014 100755 --- a/yudao-ui-admin/src/views/pay/order/index.vue +++ b/yudao-ui-admin/src/views/pay/order/index.vue @@ -121,7 +121,7 @@ @pagination="getList"/> - + {{ orderDetail.merchantOrderId }} diff --git a/yudao-ui-admin/src/views/pay/refund/index.vue b/yudao-ui-admin/src/views/pay/refund/index.vue index 3ea674531..2149f16ed 100755 --- a/yudao-ui-admin/src/views/pay/refund/index.vue +++ b/yudao-ui-admin/src/views/pay/refund/index.vue @@ -128,7 +128,7 @@ @pagination="getList"/> - + {{ refundDetail.merchantRefundId }} @@ -180,7 +180,7 @@ {{ refundDetail.notifyUrl }} - + {{refundDetail.channelErrorCode}} {{refundDetail.channelErrorMsg}} From da529851bd142ccd9dff47abcbf8b8acc1e0cb64 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 21 Jul 2023 09:19:59 +0800 Subject: [PATCH 10/11] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E7=AE=80?= =?UTF-8?q?=E5=8C=96=E6=94=AF=E4=BB=98=E5=AE=9D=E6=94=AF=E4=BB=98=E7=9A=84?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-ui-admin/src/utils/dict.js | 3 - .../pay/app/components/aliPayChannelForm.vue | 96 ++++--------------- yudao-ui-admin/src/views/pay/app/index.vue | 4 +- 3 files changed, 21 insertions(+), 82 deletions(-) diff --git a/yudao-ui-admin/src/utils/dict.js b/yudao-ui-admin/src/utils/dict.js index 8abbe2093..6019cdc83 100644 --- a/yudao-ui-admin/src/utils/dict.js +++ b/yudao-ui-admin/src/utils/dict.js @@ -51,9 +51,6 @@ export const DICT_TYPE = { // ========== PAY 模块 ========== PAY_CHANNEL_WECHAT_VERSION: 'pay_channel_wechat_version', // 微信渠道版本 - PAY_CHANNEL_ALIPAY_SIGN_TYPE: 'pay_channel_alipay_sign_type', // 支付渠道支付宝算法类型 - PAY_CHANNEL_ALIPAY_MODE: 'pay_channel_alipay_mode', // 支付宝公钥类型 - PAY_CHANNEL_ALIPAY_SERVER_TYPE: 'pay_channel_alipay_server_type', // 支付宝网关地址 PAY_CHANNEL_CODE: 'pay_channel_code', // 支付渠道编码类型 PAY_ORDER_STATUS: 'pay_order_status', // 商户支付订单状态 diff --git a/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue index d3a8943b6..76b047490 100644 --- a/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue +++ b/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue @@ -8,36 +8,32 @@ - + - + {{ dict.label }} - - {{ dict.label }} - + 线上环境 + 沙箱环境 - - {{ dict.label }} - + RSA2 - - {{ dict.label }} - + 公钥模式 + 证书模式
@@ -122,7 +118,6 @@
- diff --git a/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue new file mode 100644 index 000000000..1043c414a --- /dev/null +++ b/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue @@ -0,0 +1,268 @@ + + + diff --git a/yudao-ui-admin/src/views/pay/app/index.vue b/yudao-ui-admin/src/views/pay/app/index.vue index d280321a3..3a038f8be 100644 --- a/yudao-ui-admin/src/views/pay/app/index.vue +++ b/yudao-ui-admin/src/views/pay/app/index.vue @@ -216,7 +216,7 @@ - + @@ -225,13 +225,13 @@ import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage } import { DICT_TYPE, getDictDatas } from "@/utils/dict"; import { PayType, PayChannelEnum, CommonStatusEnum } from "@/utils/constants"; import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm"; -import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm"; +import alipayChannelForm from "@/views/pay/app/components/alipayChannelForm"; export default { name: "PayApp", components: { "wechatChannelForm": wechatChannelForm, - "aliPayChannelForm": aliPayChannelForm + "alipayChannelForm": alipayChannelForm }, data() { return { @@ -285,13 +285,6 @@ export default { "appId": null, // 渠道编码 "payCode": null, - // 商户对象 - "payMerchant": { - // 编号 - "id": null, - // 名称 - "name": null - }, } }; }, @@ -426,14 +419,12 @@ export default { this.channelParam.aliPayOpen = false; } if (type === PayType.ALIPAY) { - this.channelParam.aliPayOpen = true; - this.channelParam.wechatOpen = false; + console.log(this.$refs['alipayChannelFormRef']) + this.$refs['alipayChannelFormRef'].open(row.id, payCode); + return; + // this.channelParam.aliPayOpen = true; + // this.channelParam.wechatOpen = false; } - this.channelParam.edit = false; - this.channelParam.loading = false; - this.channelParam.appId = row.id; - this.channelParam.payCode = payCode; - this.channelParam.payMerchant = row.payMerchant; }, /** * 根据渠道编码判断渠道列表中是否存在