Commit a73e078593b05c205c3c068ab0b66e87b8d8e73c
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
# Conflicts: # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
Showing
94 changed files
with
2583 additions
and
2314 deletions
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java
| @@ -12,7 +12,6 @@ import org.springframework.context.annotation.Bean; | @@ -12,7 +12,6 @@ import org.springframework.context.annotation.Bean; | ||
| 12 | * @author 芋道源码 | 12 | * @author 芋道源码 |
| 13 | */ | 13 | */ |
| 14 | @AutoConfiguration | 14 | @AutoConfiguration |
| 15 | -@EnableConfigurationProperties(PayProperties.class) | ||
| 16 | public class YudaoPayAutoConfiguration { | 15 | public class YudaoPayAutoConfiguration { |
| 17 | 16 | ||
| 18 | @Bean | 17 | @Bean |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/order/PayOrderRespDTO.java
| @@ -79,14 +79,16 @@ public class PayOrderRespDTO { | @@ -79,14 +79,16 @@ public class PayOrderRespDTO { | ||
| 79 | /** | 79 | /** |
| 80 | * 创建【WAITING】状态的订单返回 | 80 | * 创建【WAITING】状态的订单返回 |
| 81 | */ | 81 | */ |
| 82 | - public PayOrderRespDTO(String displayMode, String displayContent, | ||
| 83 | - String outTradeNo, Object rawData) { | ||
| 84 | - this.status = PayOrderStatusRespEnum.WAITING.getStatus(); | ||
| 85 | - this.displayMode = displayMode; | ||
| 86 | - this.displayContent = displayContent; | 82 | + public static PayOrderRespDTO waitingOf(String displayMode, String displayContent, |
| 83 | + String outTradeNo, Object rawData) { | ||
| 84 | + PayOrderRespDTO respDTO = new PayOrderRespDTO(); | ||
| 85 | + respDTO.status = PayOrderStatusRespEnum.WAITING.getStatus(); | ||
| 86 | + respDTO.displayMode = displayMode; | ||
| 87 | + respDTO.displayContent = displayContent; | ||
| 87 | // 相对通用的字段 | 88 | // 相对通用的字段 |
| 88 | - this.outTradeNo = outTradeNo; | ||
| 89 | - this.rawData = rawData; | 89 | + respDTO.outTradeNo = outTradeNo; |
| 90 | + respDTO.rawData = rawData; | ||
| 91 | + return respDTO; | ||
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | /** | 94 | /** |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundRespDTO.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.dto.refund; | 1 | package cn.iocoder.yudao.framework.pay.core.client.dto.refund; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.exception.PayException; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | 4 | import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; |
| 4 | import lombok.Data; | 5 | import lombok.Data; |
| 5 | 6 | ||
| @@ -44,4 +45,71 @@ public class PayRefundRespDTO { | @@ -44,4 +45,71 @@ public class PayRefundRespDTO { | ||
| 44 | */ | 45 | */ |
| 45 | private Object rawData; | 46 | private Object rawData; |
| 46 | 47 | ||
| 48 | + /** | ||
| 49 | + * 调用渠道的错误码 | ||
| 50 | + * | ||
| 51 | + * 注意:这里返回的是业务异常,而是不系统异常。 | ||
| 52 | + * 如果是系统异常,则会抛出 {@link PayException} | ||
| 53 | + */ | ||
| 54 | + private String channelErrorCode; | ||
| 55 | + /** | ||
| 56 | + * 调用渠道报错时,错误信息 | ||
| 57 | + */ | ||
| 58 | + private String channelErrorMsg; | ||
| 59 | + | ||
| 60 | + private PayRefundRespDTO() { | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 创建【WAITING】状态的退款返回 | ||
| 65 | + */ | ||
| 66 | + public static PayRefundRespDTO waitingOf(String channelRefundNo, | ||
| 67 | + String outRefundNo, Object rawData) { | ||
| 68 | + PayRefundRespDTO respDTO = new PayRefundRespDTO(); | ||
| 69 | + respDTO.status = PayRefundStatusRespEnum.WAITING.getStatus(); | ||
| 70 | + respDTO.channelRefundNo = channelRefundNo; | ||
| 71 | + // 相对通用的字段 | ||
| 72 | + respDTO.outRefundNo = outRefundNo; | ||
| 73 | + respDTO.rawData = rawData; | ||
| 74 | + return respDTO; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 创建【SUCCESS】状态的退款返回 | ||
| 79 | + */ | ||
| 80 | + public static PayRefundRespDTO successOf(String channelRefundNo, LocalDateTime successTime, | ||
| 81 | + String outRefundNo, Object rawData) { | ||
| 82 | + PayRefundRespDTO respDTO = new PayRefundRespDTO(); | ||
| 83 | + respDTO.status = PayRefundStatusRespEnum.SUCCESS.getStatus(); | ||
| 84 | + respDTO.channelRefundNo = channelRefundNo; | ||
| 85 | + respDTO.successTime = successTime; | ||
| 86 | + // 相对通用的字段 | ||
| 87 | + respDTO.outRefundNo = outRefundNo; | ||
| 88 | + respDTO.rawData = rawData; | ||
| 89 | + return respDTO; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * 创建【FAILURE】状态的退款返回 | ||
| 94 | + */ | ||
| 95 | + public static PayRefundRespDTO failureOf(String outRefundNo, Object rawData) { | ||
| 96 | + return failureOf(null, null, | ||
| 97 | + outRefundNo, rawData); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * 创建【FAILURE】状态的退款返回 | ||
| 102 | + */ | ||
| 103 | + public static PayRefundRespDTO failureOf(String channelErrorCode, String channelErrorMsg, | ||
| 104 | + String outRefundNo, Object rawData) { | ||
| 105 | + PayRefundRespDTO respDTO = new PayRefundRespDTO(); | ||
| 106 | + respDTO.status = PayRefundStatusRespEnum.FAILURE.getStatus(); | ||
| 107 | + respDTO.channelErrorCode = channelErrorCode; | ||
| 108 | + respDTO.channelErrorMsg = channelErrorMsg; | ||
| 109 | + // 相对通用的字段 | ||
| 110 | + respDTO.outRefundNo = outRefundNo; | ||
| 111 | + respDTO.rawData = rawData; | ||
| 112 | + return respDTO; | ||
| 113 | + } | ||
| 114 | + | ||
| 47 | } | 115 | } |
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<Config extends PayClientConfig> implemen | @@ -98,7 +98,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 98 | try { | 98 | try { |
| 99 | return doParseOrderNotify(params, body); | 99 | return doParseOrderNotify(params, body); |
| 100 | } catch (Throwable ex) { | 100 | } catch (Throwable ex) { |
| 101 | - log.error("[parseOrderNotify][params({}) body({}) 解析失败]", params, body, ex); | 101 | + log.error("[parseOrderNotify][客户端({}) params({}) body({}) 解析失败]", |
| 102 | + getId(), params, body, ex); | ||
| 102 | throw buildPayException(ex); | 103 | throw buildPayException(ex); |
| 103 | } | 104 | } |
| 104 | } | 105 | } |
| @@ -129,6 +130,20 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -129,6 +130,20 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 129 | 130 | ||
| 130 | protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable; | 131 | protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable; |
| 131 | 132 | ||
| 133 | + @Override | ||
| 134 | + public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) { | ||
| 135 | + try { | ||
| 136 | + return doParseRefundNotify(params, body); | ||
| 137 | + } catch (Throwable ex) { | ||
| 138 | + log.error("[parseRefundNotify][客户端({}) params({}) body({}) 解析失败]", | ||
| 139 | + getId(), params, body, ex); | ||
| 140 | + throw buildPayException(ex); | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + protected abstract PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) | ||
| 145 | + throws Throwable; | ||
| 146 | + | ||
| 132 | // ========== 各种工具方法 ========== | 147 | // ========== 各种工具方法 ========== |
| 133 | 148 | ||
| 134 | private PayException buildPayException(Throwable ex) { | 149 | private PayException buildPayException(Throwable ex) { |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
| @@ -3,8 +3,10 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | @@ -3,8 +3,10 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | ||
| 3 | import cn.hutool.core.bean.BeanUtil; | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | import cn.hutool.core.date.LocalDateTimeUtil; | 4 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 5 | import cn.hutool.core.lang.Assert; | 5 | import cn.hutool.core.lang.Assert; |
| 6 | +import cn.hutool.core.map.MapUtil; | ||
| 6 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 7 | import cn.hutool.http.HttpUtil; | 8 | import cn.hutool.http.HttpUtil; |
| 9 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 11 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 12 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| @@ -29,7 +31,6 @@ import java.util.Objects; | @@ -29,7 +31,6 @@ import java.util.Objects; | ||
| 29 | import java.util.function.Supplier; | 31 | import java.util.function.Supplier; |
| 30 | 32 | ||
| 31 | import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; | 33 | import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; |
| 32 | -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||
| 33 | 34 | ||
| 34 | /** | 35 | /** |
| 35 | * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款) | 36 | * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款) |
| @@ -74,10 +75,15 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -74,10 +75,15 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 74 | StandardCharsets.UTF_8.name(), config.getSignType()); | 75 | StandardCharsets.UTF_8.name(), config.getSignType()); |
| 75 | 76 | ||
| 76 | // 2. 解析订单的状态 | 77 | // 2. 解析订单的状态 |
| 78 | + // 额外说明:支付宝不仅仅支付成功会回调,再各种触发支付单数据变化时,都会进行回调,所以这里 status 的解析会写的比较复杂 | ||
| 77 | String tradeStatus = bodyObj.get("trade_status"); | 79 | String tradeStatus = bodyObj.get("trade_status"); |
| 78 | Integer status = Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus() | 80 | Integer status = Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus() |
| 79 | - : Objects.equals("TRADE_SUCCESS", tradeStatus) ? PayOrderStatusRespEnum.SUCCESS.getStatus() | 81 | + : ObjectUtils.equalsAny(tradeStatus, "TRADE_FINISHED", "TRADE_SUCCESS") ? PayOrderStatusRespEnum.SUCCESS.getStatus() |
| 80 | : Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null; | 82 | : Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null; |
| 83 | + // 特殊逻辑: 支付宝没有退款成功的状态,所以,如果有退款金额,我们认为是退款成功 | ||
| 84 | + if (MapUtil.getDouble(bodyObj, "refund_fee", 0D) > 0) { | ||
| 85 | + status = PayOrderStatusRespEnum.REFUND.getStatus(); | ||
| 86 | + } | ||
| 81 | Assert.notNull(status, (Supplier<Throwable>) () -> { | 87 | Assert.notNull(status, (Supplier<Throwable>) () -> { |
| 82 | throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body)); | 88 | throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body)); |
| 83 | }); | 89 | }); |
| @@ -94,7 +100,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -94,7 +100,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 94 | * @return 退款请求 Response | 100 | * @return 退款请求 Response |
| 95 | */ | 101 | */ |
| 96 | @Override | 102 | @Override |
| 97 | - protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { | 103 | + protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 98 | // 1.1 构建 AlipayTradeRefundModel 请求 | 104 | // 1.1 构建 AlipayTradeRefundModel 请求 |
| 99 | AlipayTradeRefundModel model = new AlipayTradeRefundModel(); | 105 | AlipayTradeRefundModel model = new AlipayTradeRefundModel(); |
| 100 | model.setOutTradeNo(reqDTO.getOutTradeNo()); | 106 | model.setOutTradeNo(reqDTO.getOutTradeNo()); |
| @@ -104,31 +110,22 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -104,31 +110,22 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 104 | // 1.2 构建 AlipayTradePayRequest 请求 | 110 | // 1.2 构建 AlipayTradePayRequest 请求 |
| 105 | AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); | 111 | AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); |
| 106 | request.setBizModel(model); | 112 | request.setBizModel(model); |
| 107 | - try { | ||
| 108 | - // 2.1 执行请求 | ||
| 109 | - AlipayTradeRefundResponse response = client.execute(request); | ||
| 110 | - // 2.2 创建返回结果 | ||
| 111 | - PayRefundRespDTO refund = new PayRefundRespDTO() | ||
| 112 | - .setOutRefundNo(reqDTO.getOutRefundNo()) | ||
| 113 | - .setRawData(response); | ||
| 114 | - // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。 | ||
| 115 | - // 另外,支付宝没有退款单号,所以不用设置 | ||
| 116 | - if (response.isSuccess()) { | ||
| 117 | - refund.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 118 | - .setSuccessTime(LocalDateTimeUtil.of(response.getGmtRefundPay())); | ||
| 119 | - Assert.notNull(refund.getSuccessTime(), "退款成功时间不能为空"); | ||
| 120 | - } else { | ||
| 121 | - refund.setStatus(PayOrderStatusRespEnum.CLOSED.getStatus()); | ||
| 122 | - } | ||
| 123 | - return refund; | ||
| 124 | - } catch (AlipayApiException e) { | ||
| 125 | - log.error("[doUnifiedRefund][request({}) 发起退款异常]", toJsonString(reqDTO), e); | ||
| 126 | - return null; | 113 | + |
| 114 | + // 2.1 执行请求 | ||
| 115 | + AlipayTradeRefundResponse response = client.execute(request); | ||
| 116 | + // 2.2 创建返回结果 | ||
| 117 | + // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。 | ||
| 118 | + // 另外,支付宝没有退款单号,所以不用设置 | ||
| 119 | + if (response.isSuccess()) { | ||
| 120 | + return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()), | ||
| 121 | + reqDTO.getOutRefundNo(), response); | ||
| 122 | + } else { | ||
| 123 | + return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response); | ||
| 127 | } | 124 | } |
| 128 | } | 125 | } |
| 129 | 126 | ||
| 130 | @Override | 127 | @Override |
| 131 | - public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) { | 128 | + public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) { |
| 132 | // 补充说明:支付宝退款时,没有回调,这点和微信支付是不同的。并且,退款分成部分退款、和全部退款。 | 129 | // 补充说明:支付宝退款时,没有回调,这点和微信支付是不同的。并且,退款分成部分退款、和全部退款。 |
| 133 | // ① 部分退款:是会有回调,但是它回调的是订单状态的同步回调,不是退款订单的回调 | 130 | // ① 部分退款:是会有回调,但是它回调的是订单状态的同步回调,不是退款订单的回调 |
| 134 | // ② 全部退款:Wap 支付有订单状态的同步回调,但是 PC/扫码又没有 | 131 | // ② 全部退款:Wap 支付有订单状态的同步回调,但是 PC/扫码又没有 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java
| @@ -52,7 +52,7 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { | @@ -52,7 +52,7 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { | ||
| 52 | if (!response.isSuccess()) { | 52 | if (!response.isSuccess()) { |
| 53 | return buildClosedPayOrderRespDTO(reqDTO, response); | 53 | return buildClosedPayOrderRespDTO(reqDTO, response); |
| 54 | } | 54 | } |
| 55 | - return new PayOrderRespDTO(displayMode, "", | 55 | + return PayOrderRespDTO.waitingOf(displayMode, "", |
| 56 | reqDTO.getOutTradeNo(), response); | 56 | reqDTO.getOutTradeNo(), response); |
| 57 | } | 57 | } |
| 58 | 58 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java
| @@ -62,7 +62,7 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { | @@ -62,7 +62,7 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { | ||
| 62 | if (!response.isSuccess()) { | 62 | if (!response.isSuccess()) { |
| 63 | return buildClosedPayOrderRespDTO(reqDTO, response); | 63 | return buildClosedPayOrderRespDTO(reqDTO, response); |
| 64 | } | 64 | } |
| 65 | - return new PayOrderRespDTO(displayMode, "", | 65 | + return PayOrderRespDTO.waitingOf(displayMode, "", |
| 66 | reqDTO.getOutTradeNo(), response); | 66 | reqDTO.getOutTradeNo(), response); |
| 67 | } | 67 | } |
| 68 | 68 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
| @@ -63,7 +63,7 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { | @@ -63,7 +63,7 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { | ||
| 63 | if (!response.isSuccess()) { | 63 | if (!response.isSuccess()) { |
| 64 | return buildClosedPayOrderRespDTO(reqDTO, response); | 64 | return buildClosedPayOrderRespDTO(reqDTO, response); |
| 65 | } | 65 | } |
| 66 | - return new PayOrderRespDTO(displayMode, response.getBody(), | 66 | + return PayOrderRespDTO.waitingOf(displayMode, response.getBody(), |
| 67 | reqDTO.getOutTradeNo(), response); | 67 | reqDTO.getOutTradeNo(), response); |
| 68 | } | 68 | } |
| 69 | 69 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
| @@ -50,7 +50,7 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { | @@ -50,7 +50,7 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { | ||
| 50 | if (!response.isSuccess()) { | 50 | if (!response.isSuccess()) { |
| 51 | return buildClosedPayOrderRespDTO(reqDTO, response); | 51 | return buildClosedPayOrderRespDTO(reqDTO, response); |
| 52 | } | 52 | } |
| 53 | - return new PayOrderRespDTO(displayMode, response.getQrCode(), | 53 | + return PayOrderRespDTO.waitingOf(displayMode, response.getQrCode(), |
| 54 | reqDTO.getOutTradeNo(), response); | 54 | reqDTO.getOutTradeNo(), response); |
| 55 | } | 55 | } |
| 56 | 56 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
| @@ -52,7 +52,7 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { | @@ -52,7 +52,7 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { | ||
| 52 | if (!response.isSuccess()) { | 52 | if (!response.isSuccess()) { |
| 53 | return buildClosedPayOrderRespDTO(reqDTO, response); | 53 | return buildClosedPayOrderRespDTO(reqDTO, response); |
| 54 | } | 54 | } |
| 55 | - return new PayOrderRespDTO(displayMode, response.getBody(), | 55 | + return PayOrderRespDTO.waitingOf(displayMode, response.getBody(), |
| 56 | reqDTO.getOutTradeNo(), response); | 56 | reqDTO.getOutTradeNo(), response); |
| 57 | } | 57 | } |
| 58 | 58 |
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; | @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | ||
| 12 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | 12 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |
| 13 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; | 13 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |
| 14 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; | 14 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; |
| 15 | -import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | ||
| 16 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; | 15 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| 17 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; | 16 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; |
| 18 | import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; | 17 | import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; |
| @@ -131,6 +130,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -131,6 +130,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 131 | // 1. 解析回调 | 130 | // 1. 解析回调 |
| 132 | WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body); | 131 | WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body); |
| 133 | // 2. 构建结果 | 132 | // 2. 构建结果 |
| 133 | + // 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂 | ||
| 134 | Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ? | 134 | Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ? |
| 135 | PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus(); | 135 | PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus(); |
| 136 | return new PayOrderRespDTO(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()), | 136 | return new PayOrderRespDTO(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()), |
| @@ -142,6 +142,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -142,6 +142,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 142 | WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null); | 142 | WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null); |
| 143 | WxPayOrderNotifyV3Result.DecryptNotifyResult result = response.getResult(); | 143 | WxPayOrderNotifyV3Result.DecryptNotifyResult result = response.getResult(); |
| 144 | // 2. 构建结果 | 144 | // 2. 构建结果 |
| 145 | + // 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂 | ||
| 145 | Integer status = Objects.equals(result.getTradeState(), "SUCCESS") ? | 146 | Integer status = Objects.equals(result.getTradeState(), "SUCCESS") ? |
| 146 | PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus(); | 147 | PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus(); |
| 147 | String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null; | 148 | String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null; |
| @@ -163,9 +164,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -163,9 +164,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 163 | throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | 164 | throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); |
| 164 | } | 165 | } |
| 165 | } catch (WxPayException e) { | 166 | } catch (WxPayException e) { |
| 166 | - // todo 芋艿:异常的处理; | ||
| 167 | -// throw buildUnifiedOrderException(null, e); | ||
| 168 | - return null; | 167 | + String errorCode = getErrorCode(e); |
| 168 | + String errorMessage = getErrorMessage(e); | ||
| 169 | + return PayRefundRespDTO.failureOf(errorCode, errorMessage, | ||
| 170 | + reqDTO.getOutTradeNo(), e.getXmlString()); | ||
| 169 | } | 171 | } |
| 170 | } | 172 | } |
| 171 | 173 | ||
| @@ -181,17 +183,11 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -181,17 +183,11 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 181 | // 2.1 执行请求 | 183 | // 2.1 执行请求 |
| 182 | WxPayRefundResult response = client.refundV2(request); | 184 | WxPayRefundResult response = client.refundV2(request); |
| 183 | // 2.2 创建返回结果 | 185 | // 2.2 创建返回结果 |
| 184 | - PayRefundRespDTO refund = new PayRefundRespDTO() | ||
| 185 | - .setOutRefundNo(reqDTO.getOutRefundNo()) | ||
| 186 | - .setRawData(response); | ||
| 187 | if (Objects.equals("SUCCESS", response.getResultCode())) { | 186 | if (Objects.equals("SUCCESS", response.getResultCode())) { |
| 188 | - refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus()) | ||
| 189 | - .setChannelRefundNo(response.getRefundId()); | ||
| 190 | - } else { | ||
| 191 | - refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | 187 | + return PayRefundRespDTO.waitingOf(response.getRefundId(), |
| 188 | + reqDTO.getOutRefundNo(), response); | ||
| 192 | } | 189 | } |
| 193 | - // TODO 芋艿;异常的处理; | ||
| 194 | - return refund; | 190 | + return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response); |
| 195 | } | 191 | } |
| 196 | 192 | ||
| 197 | private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable { | 193 | private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable { |
| @@ -206,78 +202,51 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -206,78 +202,51 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 206 | // 2.1 执行请求 | 202 | // 2.1 执行请求 |
| 207 | WxPayRefundV3Result response = client.refundV3(request); | 203 | WxPayRefundV3Result response = client.refundV3(request); |
| 208 | // 2.2 创建返回结果 | 204 | // 2.2 创建返回结果 |
| 209 | - PayRefundRespDTO refund = new PayRefundRespDTO() | ||
| 210 | - .setOutRefundNo(reqDTO.getOutRefundNo()) | ||
| 211 | - .setRawData(response); | ||
| 212 | if (Objects.equals("SUCCESS", response.getStatus())) { | 205 | if (Objects.equals("SUCCESS", response.getStatus())) { |
| 213 | - refund.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) | ||
| 214 | - .setChannelRefundNo(response.getRefundId()) | ||
| 215 | - .setSuccessTime(parseDateV3(response.getSuccessTime())); | ||
| 216 | - } else if (Objects.equals("PROCESSING", response.getStatus())) { | ||
| 217 | - refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus()) | ||
| 218 | - .setChannelRefundNo(response.getRefundId()); | ||
| 219 | - } else { | ||
| 220 | - refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | 206 | + return PayRefundRespDTO.successOf(response.getRefundId(), parseDateV3(response.getSuccessTime()), |
| 207 | + reqDTO.getOutRefundNo(), response); | ||
| 221 | } | 208 | } |
| 222 | - // TODO 芋艿;异常的处理; | ||
| 223 | - return refund; | 209 | + if (Objects.equals("PROCESSING", response.getStatus())) { |
| 210 | + return PayRefundRespDTO.waitingOf(response.getRefundId(), | ||
| 211 | + reqDTO.getOutRefundNo(), response); | ||
| 212 | + } | ||
| 213 | + return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response); | ||
| 224 | } | 214 | } |
| 225 | 215 | ||
| 226 | @Override | 216 | @Override |
| 227 | - public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) { | ||
| 228 | - try { | ||
| 229 | - // 微信支付 v2 回调结果处理 | ||
| 230 | - switch (config.getApiVersion()) { | ||
| 231 | - case API_VERSION_V2: | ||
| 232 | - return parseRefundNotifyV2(body); | ||
| 233 | - case WxPayClientConfig.API_VERSION_V3: | ||
| 234 | - return parseRefundNotifyV3(body); | ||
| 235 | - default: | ||
| 236 | - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | ||
| 237 | - } | ||
| 238 | - } catch (WxPayException e) { | ||
| 239 | - log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); | ||
| 240 | - throw new RuntimeException(e); | ||
| 241 | - // TODO 芋艿:缺一个异常翻译 | 217 | + public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) throws WxPayException { |
| 218 | + switch (config.getApiVersion()) { | ||
| 219 | + case API_VERSION_V2: | ||
| 220 | + return doParseRefundNotifyV2(body); | ||
| 221 | + case WxPayClientConfig.API_VERSION_V3: | ||
| 222 | + return parseRefundNotifyV3(body); | ||
| 223 | + default: | ||
| 224 | + throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | ||
| 242 | } | 225 | } |
| 243 | } | 226 | } |
| 244 | 227 | ||
| 245 | - @SuppressWarnings("DuplicatedCode") | ||
| 246 | - private PayRefundRespDTO parseRefundNotifyV2(String body) throws WxPayException { | 228 | + private PayRefundRespDTO doParseRefundNotifyV2(String body) throws WxPayException { |
| 247 | // 1. 解析回调 | 229 | // 1. 解析回调 |
| 248 | WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body); | 230 | WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body); |
| 249 | - WxPayRefundNotifyResult.ReqInfo responseResult = response.getReqInfo(); | 231 | + WxPayRefundNotifyResult.ReqInfo result = response.getReqInfo(); |
| 250 | // 2. 构建结果 | 232 | // 2. 构建结果 |
| 251 | - PayRefundRespDTO notify = new PayRefundRespDTO() | ||
| 252 | - .setChannelRefundNo(responseResult.getRefundId()) | ||
| 253 | - .setOutRefundNo(responseResult.getOutRefundNo()) | ||
| 254 | - .setRawData(response); | ||
| 255 | - if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) { | ||
| 256 | - notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) | ||
| 257 | - .setSuccessTime(parseDateV2B(responseResult.getSuccessTime())); | ||
| 258 | - } else { | ||
| 259 | - notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | 233 | + if (Objects.equals("SUCCESS", result.getRefundStatus())) { |
| 234 | + return PayRefundRespDTO.successOf(result.getRefundId(), parseDateV2B(result.getSuccessTime()), | ||
| 235 | + result.getOutRefundNo(), response); | ||
| 260 | } | 236 | } |
| 261 | - return notify; | 237 | + return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response); |
| 262 | } | 238 | } |
| 263 | 239 | ||
| 264 | - @SuppressWarnings("DuplicatedCode") | ||
| 265 | private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException { | 240 | private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException { |
| 266 | // 1. 解析回调 | 241 | // 1. 解析回调 |
| 267 | WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null); | 242 | WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null); |
| 268 | - WxPayRefundNotifyV3Result.DecryptNotifyResult responseResult = response.getResult(); | 243 | + WxPayRefundNotifyV3Result.DecryptNotifyResult result = response.getResult(); |
| 269 | // 2. 构建结果 | 244 | // 2. 构建结果 |
| 270 | - PayRefundRespDTO notify = new PayRefundRespDTO() | ||
| 271 | - .setChannelRefundNo(responseResult.getRefundId()) | ||
| 272 | - .setOutRefundNo(responseResult.getOutRefundNo()) | ||
| 273 | - .setRawData(response); | ||
| 274 | - if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) { | ||
| 275 | - notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) | ||
| 276 | - .setSuccessTime(parseDateV3(responseResult.getSuccessTime())); | ||
| 277 | - } else { | ||
| 278 | - notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | 245 | + if (Objects.equals("SUCCESS", result.getRefundStatus())) { |
| 246 | + return PayRefundRespDTO.successOf(result.getRefundId(), parseDateV3(result.getSuccessTime()), | ||
| 247 | + result.getOutRefundNo(), response); | ||
| 279 | } | 248 | } |
| 280 | - return notify; | 249 | + return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response); |
| 281 | } | 250 | } |
| 282 | 251 | ||
| 283 | // ========== 各种工具方法 ========== | 252 | // ========== 各种工具方法 ========== |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClient.java
| @@ -67,7 +67,7 @@ public class WxBarPayClient extends AbstractWxPayClient { | @@ -67,7 +67,7 @@ public class WxBarPayClient extends AbstractWxPayClient { | ||
| 67 | for (int i = 1; i < Byte.MAX_VALUE; i++) { | 67 | for (int i = 1; i < Byte.MAX_VALUE; i++) { |
| 68 | try { | 68 | try { |
| 69 | WxPayMicropayResult response = client.micropay(request); | 69 | WxPayMicropayResult response = client.micropay(request); |
| 70 | - // 支付成功,例如说:1)用户输入了密码;2) | 70 | + // 支付成功,例如说:1)用户输入了密码;2)用户免密支付 |
| 71 | return new PayOrderRespDTO(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()), | 71 | return new PayOrderRespDTO(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()), |
| 72 | response.getOutTradeNo(), response) | 72 | response.getOutTradeNo(), response) |
| 73 | .setDisplayMode(PayOrderDisplayModeEnum.BAR_CODE.getMode()); | 73 | .setDisplayMode(PayOrderDisplayModeEnum.BAR_CODE.getMode()); |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java
| @@ -48,7 +48,7 @@ public class WxNativePayClient extends AbstractWxPayClient { | @@ -48,7 +48,7 @@ public class WxNativePayClient extends AbstractWxPayClient { | ||
| 48 | WxPayNativeOrderResult response = client.createOrder(request); | 48 | WxPayNativeOrderResult response = client.createOrder(request); |
| 49 | 49 | ||
| 50 | // 转换结果 | 50 | // 转换结果 |
| 51 | - return new PayOrderRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(), response.getCodeUrl(), | 51 | + return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.QR_CODE.getMode(), response.getCodeUrl(), |
| 52 | reqDTO.getOutTradeNo(), response); | 52 | reqDTO.getOutTradeNo(), response); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| @@ -66,7 +66,7 @@ public class WxNativePayClient extends AbstractWxPayClient { | @@ -66,7 +66,7 @@ public class WxNativePayClient extends AbstractWxPayClient { | ||
| 66 | String response = client.createOrderV3(TradeTypeEnum.NATIVE, request); | 66 | String response = client.createOrderV3(TradeTypeEnum.NATIVE, request); |
| 67 | 67 | ||
| 68 | // 转换结果 | 68 | // 转换结果 |
| 69 | - return new PayOrderRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(), response, | 69 | + return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.QR_CODE.getMode(), response, |
| 70 | reqDTO.getOutTradeNo(), response); | 70 | reqDTO.getOutTradeNo(), response); |
| 71 | } | 71 | } |
| 72 | 72 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java
| @@ -58,7 +58,7 @@ public class WxPubPayClient extends AbstractWxPayClient { | @@ -58,7 +58,7 @@ public class WxPubPayClient extends AbstractWxPayClient { | ||
| 58 | WxPayMpOrderResult response = client.createOrder(request); | 58 | WxPayMpOrderResult response = client.createOrder(request); |
| 59 | 59 | ||
| 60 | // 转换结果 | 60 | // 转换结果 |
| 61 | - return new PayOrderRespDTO(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), | 61 | + return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), |
| 62 | reqDTO.getOutTradeNo(), response); | 62 | reqDTO.getOutTradeNo(), response); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| @@ -77,7 +77,7 @@ public class WxPubPayClient extends AbstractWxPayClient { | @@ -77,7 +77,7 @@ public class WxPubPayClient extends AbstractWxPayClient { | ||
| 77 | WxPayUnifiedOrderV3Result.JsapiResult response = client.createOrderV3(TradeTypeEnum.JSAPI, request); | 77 | WxPayUnifiedOrderV3Result.JsapiResult response = client.createOrderV3(TradeTypeEnum.JSAPI, request); |
| 78 | 78 | ||
| 79 | // 转换结果 | 79 | // 转换结果 |
| 80 | - return new PayOrderRespDTO(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), | 80 | + return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), |
| 81 | reqDTO.getOutTradeNo(), response); | 81 | reqDTO.getOutTradeNo(), response); |
| 82 | } | 82 | } |
| 83 | 83 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/order/PayOrderStatusRespEnum.java
| @@ -16,7 +16,8 @@ public enum PayOrderStatusRespEnum { | @@ -16,7 +16,8 @@ public enum PayOrderStatusRespEnum { | ||
| 16 | 16 | ||
| 17 | WAITING(0, "未支付"), | 17 | WAITING(0, "未支付"), |
| 18 | SUCCESS(10, "支付成功"), | 18 | SUCCESS(10, "支付成功"), |
| 19 | - CLOSED(20, "支付关闭"), // 未付款交易超时关闭,或支付完成后全额退款 | 19 | + REFUND(20, "已退款"), |
| 20 | + CLOSED(30, "支付关闭"), | ||
| 20 | ; | 21 | ; |
| 21 | 22 | ||
| 22 | private final Integer status; | 23 | private final Integer status; |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/refund/PayRefundStatusRespEnum.java
| @@ -14,7 +14,7 @@ import java.util.Objects; | @@ -14,7 +14,7 @@ import java.util.Objects; | ||
| 14 | @AllArgsConstructor | 14 | @AllArgsConstructor |
| 15 | public enum PayRefundStatusRespEnum { | 15 | public enum PayRefundStatusRespEnum { |
| 16 | 16 | ||
| 17 | - WAITING(0, "未退款"), | 17 | + WAITING(0, "等待退款"), |
| 18 | SUCCESS(10, "退款成功"), | 18 | SUCCESS(10, "退款成功"), |
| 19 | FAILURE(20, "退款失败"); | 19 | FAILURE(20, "退款失败"); |
| 20 | 20 | ||
| @@ -25,4 +25,8 @@ public enum PayRefundStatusRespEnum { | @@ -25,4 +25,8 @@ public enum PayRefundStatusRespEnum { | ||
| 25 | return Objects.equals(status, SUCCESS.getStatus()); | 25 | return Objects.equals(status, SUCCESS.getStatus()); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | + public static boolean isFailure(Integer status) { | ||
| 29 | + return Objects.equals(status, FAILURE.getStatus()); | ||
| 30 | + } | ||
| 31 | + | ||
| 28 | } | 32 | } |
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.excel.core.convert; | ||
| 2 | + | ||
| 3 | +import com.alibaba.excel.converters.Converter; | ||
| 4 | +import com.alibaba.excel.enums.CellDataTypeEnum; | ||
| 5 | +import com.alibaba.excel.metadata.GlobalConfiguration; | ||
| 6 | +import com.alibaba.excel.metadata.data.WriteCellData; | ||
| 7 | +import com.alibaba.excel.metadata.property.ExcelContentProperty; | ||
| 8 | + | ||
| 9 | +import java.math.BigDecimal; | ||
| 10 | +import java.math.RoundingMode; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 金额转换器 | ||
| 14 | + * | ||
| 15 | + * 金额单位:分 | ||
| 16 | + * | ||
| 17 | + * @author 芋道源码 | ||
| 18 | + */ | ||
| 19 | +public class MoneyConvert implements Converter<Integer> { | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public Class<?> supportJavaTypeKey() { | ||
| 23 | + throw new UnsupportedOperationException("暂不支持,也不需要"); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public CellDataTypeEnum supportExcelTypeKey() { | ||
| 28 | + throw new UnsupportedOperationException("暂不支持,也不需要"); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public WriteCellData<String> convertToExcelData(Integer value, ExcelContentProperty contentProperty, | ||
| 33 | + GlobalConfiguration globalConfiguration) { | ||
| 34 | + BigDecimal result = BigDecimal.valueOf(value) | ||
| 35 | + .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); | ||
| 36 | + return new WriteCellData<>(result.toString()); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | +} |
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 { | @@ -55,6 +55,9 @@ public class RandomUtils { | ||
| 55 | } | 55 | } |
| 56 | return RandomUtil.randomInt(); | 56 | return RandomUtil.randomInt(); |
| 57 | }); | 57 | }); |
| 58 | + // LocalDateTime | ||
| 59 | + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class, | ||
| 60 | + (dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime()); | ||
| 58 | // Boolean | 61 | // Boolean |
| 59 | PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { | 62 | PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { |
| 60 | // 如果是 deleted 的字段,返回非删除 | 63 | // 如果是 deleted 的字段,返回非删除 |
| @@ -82,7 +85,8 @@ public class RandomUtils { | @@ -82,7 +85,8 @@ public class RandomUtils { | ||
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | public static LocalDateTime randomLocalDateTime() { | 87 | public static LocalDateTime randomLocalDateTime() { |
| 85 | - return LocalDateTimeUtil.of(randomDate()); | 88 | + // 设置 Nano 为零的原因,避免 MySQL、H2 存储不到时间戳 |
| 89 | + return LocalDateTimeUtil.of(randomDate()).withNano(0); | ||
| 86 | } | 90 | } |
| 87 | 91 | ||
| 88 | public static Short randomShort() { | 92 | public static Short randomShort() { |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
| @@ -63,6 +63,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -63,6 +63,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 63 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | 63 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; |
| 64 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 64 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 65 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; | 65 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; |
| 66 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; | ||
| 66 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; | 67 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; |
| 67 | 68 | ||
| 68 | /** | 69 | /** |
| @@ -344,7 +345,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -344,7 +345,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 344 | PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); | 345 | PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); |
| 345 | if (payOrder == null) { | 346 | if (payOrder == null) { |
| 346 | log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); | 347 | log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); |
| 347 | - throw exception(PAY_ORDER_NOT_FOUND); | 348 | + throw exception(cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND); |
| 348 | } | 349 | } |
| 349 | // 校验支付单已支付 | 350 | // 校验支付单已支付 |
| 350 | if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { | 351 | if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { |
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java
| @@ -7,13 +7,12 @@ package cn.iocoder.yudao.module.pay.enums; | @@ -7,13 +7,12 @@ package cn.iocoder.yudao.module.pay.enums; | ||
| 7 | */ | 7 | */ |
| 8 | public interface DictTypeConstants { | 8 | public interface DictTypeConstants { |
| 9 | 9 | ||
| 10 | - String CHANNEL_CODE = "pay_channel_code"; // 支付-渠道名 | 10 | + String CHANNEL_CODE = "pay_channel_code"; // 支付渠道编码 |
| 11 | 11 | ||
| 12 | - String ORDER_STATUS = "pay_order_status"; // 支付-订单-订单状态 | ||
| 13 | - String ORDER_NOTIFY_STATUS = "pay_order_notify_status"; // 支付-订单-订单回调商户状态 | 12 | + String ORDER_STATUS = "pay_order_status"; // 支付渠道 |
| 14 | 13 | ||
| 15 | - String ORDER_REFUND_STATUS = "pay_order_refund_status"; // 支付-订单-订单退款状态 | ||
| 16 | - String REFUND_ORDER_STATUS = "pay_refund_order_status"; // 支付-退款订单-退款状态 | ||
| 17 | - String REFUND_ORDER_TYPE = "pay_refund_order_type"; // 支付-退款订单-退款类别 | 14 | + String REFUND_STATUS = "pay_order_status"; // 退款状态 |
| 15 | + | ||
| 16 | + String NOTIFY_STATUS = "pay_notify_status"; // 回调状态 | ||
| 18 | 17 | ||
| 19 | } | 18 | } |
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; | @@ -10,48 +10,46 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 10 | public interface ErrorCodeConstants { | 10 | public interface ErrorCodeConstants { |
| 11 | 11 | ||
| 12 | // ========== APP 模块 1007000000 ========== | 12 | // ========== APP 模块 1007000000 ========== |
| 13 | - ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在"); | ||
| 14 | - ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用"); | ||
| 15 | - ErrorCode PAY_APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在支付订单,无法删除"); | ||
| 16 | - ErrorCode PAY_APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1007000004, "支付应用存在退款订单,无法删除"); | 13 | + ErrorCode APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在"); |
| 14 | + ErrorCode APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用"); | ||
| 15 | + ErrorCode APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在支付订单,无法删除"); | ||
| 16 | + ErrorCode APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1007000004, "支付应用存在退款订单,无法删除"); | ||
| 17 | 17 | ||
| 18 | // ========== CHANNEL 模块 1007001000 ========== | 18 | // ========== CHANNEL 模块 1007001000 ========== |
| 19 | - ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在"); | ||
| 20 | - ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); | ||
| 21 | - ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); | ||
| 22 | - ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在"); | ||
| 23 | - ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道"); | 19 | + ErrorCode CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在"); |
| 20 | + ErrorCode CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); | ||
| 21 | + ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001004, "已存在相同的渠道"); | ||
| 24 | 22 | ||
| 25 | // ========== ORDER 模块 1007002000 ========== | 23 | // ========== ORDER 模块 1007002000 ========== |
| 26 | - ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); | ||
| 27 | - ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); | ||
| 28 | - ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); | ||
| 29 | - ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); | ||
| 30 | - ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); | 24 | + ErrorCode ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); |
| 25 | + ErrorCode ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); | ||
| 26 | + ErrorCode ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); | ||
| 27 | + ErrorCode ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); | ||
| 28 | + ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); | ||
| 29 | + ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); | ||
| 31 | 30 | ||
| 32 | // ========== ORDER 模块(拓展单) 1007003000 ========== | 31 | // ========== ORDER 模块(拓展单) 1007003000 ========== |
| 33 | - ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); | ||
| 34 | - ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); | 32 | + ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); |
| 33 | + ErrorCode ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); | ||
| 35 | 34 | ||
| 36 | // ========== 支付模块(退款) 1007006000 ========== | 35 | // ========== 支付模块(退款) 1007006000 ========== |
| 37 | - ErrorCode PAY_REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); | ||
| 38 | - ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款"); | ||
| 39 | - ErrorCode PAY_REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中"); | ||
| 40 | - ErrorCode PAY_REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单"); | ||
| 41 | - ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); | ||
| 42 | - ErrorCode PAY_REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款"); | 36 | + ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); |
| 37 | + ErrorCode REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中"); | ||
| 38 | + ErrorCode REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单"); | ||
| 39 | + ErrorCode REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); | ||
| 40 | + ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款"); | ||
| 43 | 41 | ||
| 44 | // ========== 示例订单 1007900000 ========== | 42 | // ========== 示例订单 1007900000 ========== |
| 45 | - ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); | ||
| 46 | - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态"); | ||
| 47 | - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配"); | ||
| 48 | - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007900003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态"); | ||
| 49 | - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1007900004, "示例订单更新支付状态失败,支付单金额不匹配"); | ||
| 50 | - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(1007900005, "发起退款失败,示例订单未支付"); | ||
| 51 | - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(1007900006, "发起退款失败,示例订单已退款"); | ||
| 52 | - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007900007, "发起退款失败,退款订单不存在"); | ||
| 53 | - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(1007900008, "发起退款失败,退款订单未退款成功"); | ||
| 54 | - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007900009, "发起退款失败,退款单编号不匹配"); | ||
| 55 | - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007900010, "发起退款失败,退款单金额不匹配"); | 43 | + ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); |
| 44 | + ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态"); | ||
| 45 | + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配"); | ||
| 46 | + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007900003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态"); | ||
| 47 | + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1007900004, "示例订单更新支付状态失败,支付单金额不匹配"); | ||
| 48 | + ErrorCode DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(1007900005, "发起退款失败,示例订单未支付"); | ||
| 49 | + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(1007900006, "发起退款失败,示例订单已退款"); | ||
| 50 | + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007900007, "发起退款失败,退款订单不存在"); | ||
| 51 | + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(1007900008, "发起退款失败,退款订单未退款成功"); | ||
| 52 | + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007900009, "发起退款失败,退款单编号不匹配"); | ||
| 53 | + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007900010, "发起退款失败,退款单金额不匹配"); | ||
| 56 | 54 | ||
| 57 | } | 55 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyStatusEnum.java renamed to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyStatusEnum.java
| @@ -12,11 +12,11 @@ import lombok.Getter; | @@ -12,11 +12,11 @@ import lombok.Getter; | ||
| 12 | @AllArgsConstructor | 12 | @AllArgsConstructor |
| 13 | public enum PayNotifyStatusEnum { | 13 | public enum PayNotifyStatusEnum { |
| 14 | 14 | ||
| 15 | - WAITING(1, "等待通知"), | ||
| 16 | - SUCCESS(2, "通知成功"), | ||
| 17 | - FAILURE(3, "通知失败"), // 多次尝试,彻底失败 | ||
| 18 | - REQUEST_SUCCESS(4, "请求成功,但是结果失败"), | ||
| 19 | - REQUEST_FAILURE(5, "请求失败"), | 15 | + WAITING(0, "等待通知"), |
| 16 | + SUCCESS(10, "通知成功"), | ||
| 17 | + FAILURE(20, "通知失败"), // 多次尝试,彻底失败 | ||
| 18 | + REQUEST_SUCCESS(21, "请求成功,但是结果失败"), | ||
| 19 | + REQUEST_FAILURE(22, "请求失败"), | ||
| 20 | 20 | ||
| 21 | ; | 21 | ; |
| 22 | 22 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyTypeEnum.java renamed to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyTypeEnum.java
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java
| 1 | package cn.iocoder.yudao.module.pay.enums.order; | 1 | package cn.iocoder.yudao.module.pay.enums.order; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | 3 | import cn.iocoder.yudao.framework.common.core.IntArrayValuable; |
| 4 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 4 | import lombok.AllArgsConstructor; | 5 | import lombok.AllArgsConstructor; |
| 5 | import lombok.Getter; | 6 | import lombok.Getter; |
| 6 | 7 | ||
| @@ -17,7 +18,8 @@ public enum PayOrderStatusEnum implements IntArrayValuable { | @@ -17,7 +18,8 @@ public enum PayOrderStatusEnum implements IntArrayValuable { | ||
| 17 | 18 | ||
| 18 | WAITING(0, "未支付"), | 19 | WAITING(0, "未支付"), |
| 19 | SUCCESS(10, "支付成功"), | 20 | SUCCESS(10, "支付成功"), |
| 20 | - CLOSED(20, "支付关闭"), // 未付款交易超时关闭,或支付完成后全额退款 | 21 | + REFUND(20, "已退款"), |
| 22 | + CLOSED(30, "支付关闭"), // 注意:全部退款后,还是 REFUND 状态 | ||
| 21 | ; | 23 | ; |
| 22 | 24 | ||
| 23 | private final Integer status; | 25 | private final Integer status; |
| @@ -39,6 +41,17 @@ public enum PayOrderStatusEnum implements IntArrayValuable { | @@ -39,6 +41,17 @@ public enum PayOrderStatusEnum implements IntArrayValuable { | ||
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | /** | 43 | /** |
| 44 | + * 判断是否支付成功或者已退款 | ||
| 45 | + * | ||
| 46 | + * @param status 状态 | ||
| 47 | + * @return 是否支付成功或者已退款 | ||
| 48 | + */ | ||
| 49 | + public static boolean isSuccessOrRefund(Integer status) { | ||
| 50 | + return ObjectUtils.equalsAny(status, | ||
| 51 | + SUCCESS.getStatus(), REFUND.getStatus()); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /** | ||
| 42 | * 判断是否支付关闭 | 55 | * 判断是否支付关闭 |
| 43 | * | 56 | * |
| 44 | * @param status 状态 | 57 | * @param status 状态 |
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 { | @@ -25,4 +25,8 @@ public enum PayRefundStatusEnum { | ||
| 25 | return Objects.equals(status, SUCCESS.getStatus()); | 25 | return Objects.equals(status, SUCCESS.getStatus()); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | + public static boolean isFailure(Integer status) { | ||
| 29 | + return Objects.equals(status, FAILURE.getStatus()); | ||
| 30 | + } | ||
| 31 | + | ||
| 28 | } | 32 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/PayAppController.java
| @@ -97,4 +97,12 @@ public class PayAppController { | @@ -97,4 +97,12 @@ public class PayAppController { | ||
| 97 | return success(PayAppConvert.INSTANCE.convertPage(pageResult, channels)); | 97 | return success(PayAppConvert.INSTANCE.convertPage(pageResult, channels)); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | + @GetMapping("/list") | ||
| 101 | + @Operation(summary = "获得应用列表") | ||
| 102 | + @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | ||
| 103 | + public CommonResult<List<PayAppRespVO>> getAppList() { | ||
| 104 | + List<PayAppDO> appListDO = appService.getAppList(); | ||
| 105 | + return success(PayAppConvert.INSTANCE.convertList(appListDO)); | ||
| 106 | + } | ||
| 107 | + | ||
| 100 | } | 108 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
| 1 | package cn.iocoder.yudao.module.pay.controller.admin.notify; | 1 | package cn.iocoder.yudao.module.pay.controller.admin.notify; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 5 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 4 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; | 6 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 5 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 7 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 7 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| 10 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; | ||
| 11 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; | ||
| 13 | +import cn.iocoder.yudao.module.pay.convert.notify.PayNotifyTaskConvert; | ||
| 14 | +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | ||
| 15 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | ||
| 16 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | ||
| 17 | +import cn.iocoder.yudao.module.pay.service.app.PayAppService; | ||
| 18 | +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | ||
| 8 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 19 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 9 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | 20 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 10 | import io.swagger.v3.oas.annotations.Operation; | 21 | import io.swagger.v3.oas.annotations.Operation; |
| 22 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 11 | import io.swagger.v3.oas.annotations.tags.Tag; | 23 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 12 | import lombok.extern.slf4j.Slf4j; | 24 | import lombok.extern.slf4j.Slf4j; |
| 25 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 13 | import org.springframework.validation.annotation.Validated; | 26 | import org.springframework.validation.annotation.Validated; |
| 14 | import org.springframework.web.bind.annotation.*; | 27 | import org.springframework.web.bind.annotation.*; |
| 15 | 28 | ||
| 16 | import javax.annotation.Resource; | 29 | import javax.annotation.Resource; |
| 17 | import javax.annotation.security.PermitAll; | 30 | import javax.annotation.security.PermitAll; |
| 31 | +import javax.validation.Valid; | ||
| 32 | +import java.util.List; | ||
| 18 | import java.util.Map; | 33 | import java.util.Map; |
| 19 | 34 | ||
| 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 35 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 21 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND; | 36 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 37 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 38 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND; | ||
| 22 | 39 | ||
| 23 | -@Tag(name = "管理后台 - 支付通知") | 40 | +@Tag(name = "管理后台 - 回调通知") |
| 24 | @RestController | 41 | @RestController |
| 25 | @RequestMapping("/pay/notify") | 42 | @RequestMapping("/pay/notify") |
| 26 | @Validated | 43 | @Validated |
| @@ -31,6 +48,10 @@ public class PayNotifyController { | @@ -31,6 +48,10 @@ public class PayNotifyController { | ||
| 31 | private PayOrderService orderService; | 48 | private PayOrderService orderService; |
| 32 | @Resource | 49 | @Resource |
| 33 | private PayRefundService refundService; | 50 | private PayRefundService refundService; |
| 51 | + @Resource | ||
| 52 | + private PayNotifyService notifyService; | ||
| 53 | + @Resource | ||
| 54 | + private PayAppService appService; | ||
| 34 | 55 | ||
| 35 | @Resource | 56 | @Resource |
| 36 | private PayClientFactory payClientFactory; | 57 | private PayClientFactory payClientFactory; |
| @@ -47,7 +68,7 @@ public class PayNotifyController { | @@ -47,7 +68,7 @@ public class PayNotifyController { | ||
| 47 | PayClient payClient = payClientFactory.getPayClient(channelId); | 68 | PayClient payClient = payClientFactory.getPayClient(channelId); |
| 48 | if (payClient == null) { | 69 | if (payClient == null) { |
| 49 | log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); | 70 | log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); |
| 50 | - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); | 71 | + throw exception(CHANNEL_NOT_FOUND); |
| 51 | } | 72 | } |
| 52 | 73 | ||
| 53 | // 2. 解析通知数据 | 74 | // 2. 解析通知数据 |
| @@ -68,7 +89,7 @@ public class PayNotifyController { | @@ -68,7 +89,7 @@ public class PayNotifyController { | ||
| 68 | PayClient payClient = payClientFactory.getPayClient(channelId); | 89 | PayClient payClient = payClientFactory.getPayClient(channelId); |
| 69 | if (payClient == null) { | 90 | if (payClient == null) { |
| 70 | log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); | 91 | log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); |
| 71 | - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); | 92 | + throw exception(CHANNEL_NOT_FOUND); |
| 72 | } | 93 | } |
| 73 | 94 | ||
| 74 | // 2. 解析通知数据 | 95 | // 2. 解析通知数据 |
| @@ -77,4 +98,29 @@ public class PayNotifyController { | @@ -77,4 +98,29 @@ public class PayNotifyController { | ||
| 77 | return "success"; | 98 | return "success"; |
| 78 | } | 99 | } |
| 79 | 100 | ||
| 101 | + @GetMapping("/get-detail") | ||
| 102 | + @Operation(summary = "获得回调通知的明细") | ||
| 103 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||
| 104 | + @PreAuthorize("@ss.hasPermission('pay:notify:query')") | ||
| 105 | + public CommonResult<PayNotifyTaskDetailRespVO> getNotifyTaskDetail(@RequestParam("id") Long id) { | ||
| 106 | + PayNotifyTaskDO task = notifyService.getNotifyTask(id); | ||
| 107 | + if (task == null) { | ||
| 108 | + return success(null); | ||
| 109 | + } | ||
| 110 | + // 拼接返回 | ||
| 111 | + PayAppDO app = appService.getApp(task.getAppId()); | ||
| 112 | + List<PayNotifyLogDO> logs = notifyService.getNotifyLogList(id); | ||
| 113 | + return success(PayNotifyTaskConvert.INSTANCE.convert(task, app, logs)); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + @GetMapping("/page") | ||
| 117 | + @Operation(summary = "获得回调通知分页") | ||
| 118 | + @PreAuthorize("@ss.hasPermission('pay:notify:query')") | ||
| 119 | + public CommonResult<PageResult<PayNotifyTaskRespVO>> getNotifyTaskPage(@Valid PayNotifyTaskPageReqVO pageVO) { | ||
| 120 | + PageResult<PayNotifyTaskDO> pageResult = notifyService.getNotifyTaskPage(pageVO); | ||
| 121 | + // 拼接返回 | ||
| 122 | + Map<Long, PayAppDO> appMap = appService.getAppMap(convertList(pageResult.getList(), PayNotifyTaskDO::getAppId)); | ||
| 123 | + return success(PayNotifyTaskConvert.INSTANCE.convertPage(pageResult, appMap)); | ||
| 124 | + } | ||
| 125 | + | ||
| 80 | } | 126 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 回调通知 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 10 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +public class PayNotifyTaskBaseVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10636") | ||
| 16 | + private Long appId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "通知类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 19 | + private Byte type; | ||
| 20 | + | ||
| 21 | + @Schema(description = "数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6722") | ||
| 22 | + private Long dataId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "通知状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 25 | + private Byte status; | ||
| 26 | + | ||
| 27 | + @Schema(description = "商户订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26697") | ||
| 28 | + private String merchantOrderId; | ||
| 29 | + | ||
| 30 | + @Schema(description = "下一次通知时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 31 | + private LocalDateTime nextNotifyTime; | ||
| 32 | + | ||
| 33 | + @Schema(description = "最后一次执行时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 34 | + private LocalDateTime lastExecuteTime; | ||
| 35 | + | ||
| 36 | + @Schema(description = "当前通知次数", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 37 | + private Byte notifyTimes; | ||
| 38 | + | ||
| 39 | + @Schema(description = "最大可通知次数", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 40 | + private Byte maxNotifyTimes; | ||
| 41 | + | ||
| 42 | + @Schema(description = "异步通知地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn") | ||
| 43 | + private String notifyUrl; | ||
| 44 | + | ||
| 45 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskDetailRespVO.java
0 → 100644
| 1 | + | ||
| 2 | +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; | ||
| 3 | + | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +@Schema(description = "管理后台 - 回调通知的明细 Response VO") | ||
| 13 | +@Data | ||
| 14 | +@EqualsAndHashCode(callSuper = true) | ||
| 15 | +@ToString(callSuper = true) | ||
| 16 | +public class PayNotifyTaskDetailRespVO extends PayNotifyTaskBaseVO { | ||
| 17 | + | ||
| 18 | + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3380") | ||
| 19 | + private Long id; | ||
| 20 | + | ||
| 21 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + private LocalDateTime createTime; | ||
| 23 | + | ||
| 24 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 25 | + private LocalDateTime updateTime; | ||
| 26 | + | ||
| 27 | + @Schema(description = "应用名称", example = "wx_pay") | ||
| 28 | + private String appName; | ||
| 29 | + | ||
| 30 | + @Schema(description = "回调日志列表") | ||
| 31 | + private List<Log> logs; | ||
| 32 | + | ||
| 33 | + @Schema(description = "管理后台 - 回调日志") | ||
| 34 | + @Data | ||
| 35 | + public static class Log { | ||
| 36 | + | ||
| 37 | + @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8848") | ||
| 38 | + private Long id; | ||
| 39 | + | ||
| 40 | + @Schema(description = "通知状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 41 | + private Byte status; | ||
| 42 | + | ||
| 43 | + @Schema(description = "当前通知次数", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 44 | + private Byte notifyTimes; | ||
| 45 | + | ||
| 46 | + @Schema(description = "HTTP 响应结果", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 47 | + private String response; | ||
| 48 | + | ||
| 49 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 50 | + private LocalDateTime createTime; | ||
| 51 | + | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | + | ||
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 13 | + | ||
| 14 | +@Schema(description = "管理后台 - 回调通知分页 Request VO") | ||
| 15 | +@Data | ||
| 16 | +@EqualsAndHashCode(callSuper = true) | ||
| 17 | +@ToString(callSuper = true) | ||
| 18 | +public class PayNotifyTaskPageReqVO extends PageParam { | ||
| 19 | + | ||
| 20 | + @Schema(description = "应用编号", example = "10636") | ||
| 21 | + private Long appId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "通知类型", example = "2") | ||
| 24 | + private Byte type; | ||
| 25 | + | ||
| 26 | + @Schema(description = "数据编号", example = "6722") | ||
| 27 | + private Long dataId; | ||
| 28 | + | ||
| 29 | + @Schema(description = "通知状态", example = "1") | ||
| 30 | + private Byte status; | ||
| 31 | + | ||
| 32 | + @Schema(description = "商户订单编号", example = "26697") | ||
| 33 | + private String merchantOrderId; | ||
| 34 | + | ||
| 35 | + @Schema(description = "创建时间") | ||
| 36 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 37 | + private LocalDateTime[] createTime; | ||
| 38 | + | ||
| 39 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundRespVO.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskRespVO.java
100755 → 100644
| 1 | -package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; | 1 | +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | -import lombok.Data; | ||
| 5 | -import lombok.EqualsAndHashCode; | ||
| 6 | -import lombok.ToString; | ||
| 7 | - | 4 | +import lombok.*; |
| 8 | import java.time.LocalDateTime; | 5 | import java.time.LocalDateTime; |
| 9 | 6 | ||
| 10 | -@Schema(description = "管理后台 - 退款订单 Response VO") | 7 | +@Schema(description = "管理后台 - 回调通知 Response VO") |
| 11 | @Data | 8 | @Data |
| 12 | @EqualsAndHashCode(callSuper = true) | 9 | @EqualsAndHashCode(callSuper = true) |
| 13 | @ToString(callSuper = true) | 10 | @ToString(callSuper = true) |
| 14 | -public class PayRefundRespVO extends PayRefundBaseVO { | 11 | +public class PayNotifyTaskRespVO extends PayNotifyTaskBaseVO { |
| 15 | 12 | ||
| 16 | - @Schema(description = "支付退款编号", requiredMode = Schema.RequiredMode.REQUIRED) | 13 | + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3380") |
| 17 | private Long id; | 14 | private Long id; |
| 18 | 15 | ||
| 19 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | 16 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 20 | private LocalDateTime createTime; | 17 | private LocalDateTime createTime; |
| 21 | 18 | ||
| 19 | + @Schema(description = "应用名称", example = "wx_pay") | ||
| 20 | + private String appName; | ||
| 21 | + | ||
| 22 | } | 22 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java
| 1 | package cn.iocoder.yudao.module.pay.controller.admin.order; | 1 | package cn.iocoder.yudao.module.pay.controller.admin.order; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollectionUtil; | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | -import cn.hutool.core.util.ObjectUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 6 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 9 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 7 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 10 | -import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | ||
| 11 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; | 8 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; |
| 12 | import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; | 9 | import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; |
| 13 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| 14 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 11 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 15 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | 12 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; |
| 16 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 13 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 17 | -import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; | ||
| 18 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 14 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 19 | import io.swagger.v3.oas.annotations.Operation; | 15 | import io.swagger.v3.oas.annotations.Operation; |
| 20 | import io.swagger.v3.oas.annotations.Parameter; | 16 | import io.swagger.v3.oas.annotations.Parameter; |
| @@ -32,6 +28,7 @@ import java.util.List; | @@ -32,6 +28,7 @@ import java.util.List; | ||
| 32 | import java.util.Map; | 28 | import java.util.Map; |
| 33 | 29 | ||
| 34 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 30 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 31 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 35 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; | 32 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; |
| 36 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 33 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 37 | 34 | ||
| @@ -42,9 +39,7 @@ import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.E | @@ -42,9 +39,7 @@ import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.E | ||
| 42 | public class PayOrderController { | 39 | public class PayOrderController { |
| 43 | 40 | ||
| 44 | @Resource | 41 | @Resource |
| 45 | - private PayOrderService payOrderService; | ||
| 46 | - @Resource | ||
| 47 | - private PayOrderExtensionService orderExtensionService; | 42 | + private PayOrderService orderService; |
| 48 | @Resource | 43 | @Resource |
| 49 | private PayAppService appService; | 44 | private PayAppService appService; |
| 50 | 45 | ||
| @@ -53,40 +48,29 @@ public class PayOrderController { | @@ -53,40 +48,29 @@ public class PayOrderController { | ||
| 53 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 48 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| 54 | @PreAuthorize("@ss.hasPermission('pay:order:query')") | 49 | @PreAuthorize("@ss.hasPermission('pay:order:query')") |
| 55 | public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) { | 50 | public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) { |
| 56 | - return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id))); | 51 | + return success(PayOrderConvert.INSTANCE.convert(orderService.getOrder(id))); |
| 57 | } | 52 | } |
| 58 | 53 | ||
| 59 | - // TODO 芋艿:看看怎么优化下; | ||
| 60 | @GetMapping("/get-detail") | 54 | @GetMapping("/get-detail") |
| 61 | @Operation(summary = "获得支付订单详情") | 55 | @Operation(summary = "获得支付订单详情") |
| 62 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 56 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| 63 | @PreAuthorize("@ss.hasPermission('pay:order:query')") | 57 | @PreAuthorize("@ss.hasPermission('pay:order:query')") |
| 64 | public CommonResult<PayOrderDetailsRespVO> getOrderDetail(@RequestParam("id") Long id) { | 58 | public CommonResult<PayOrderDetailsRespVO> getOrderDetail(@RequestParam("id") Long id) { |
| 65 | - PayOrderDO order = payOrderService.getOrder(id); | ||
| 66 | - if (ObjectUtil.isNull(order)) { | ||
| 67 | - return success(new PayOrderDetailsRespVO()); | ||
| 68 | - } | ||
| 69 | - | ||
| 70 | - PayAppDO appDO = appService.getApp(order.getAppId()); | ||
| 71 | - PayChannelEnum channelEnum = PayChannelEnum.getByCode(order.getChannelCode()); | ||
| 72 | - | ||
| 73 | - // TODO @aquan:文案,都是前端 format; | ||
| 74 | - PayOrderDetailsRespVO respVO = PayOrderConvert.INSTANCE.orderDetailConvert(order); | ||
| 75 | - respVO.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | ||
| 76 | - respVO.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | ||
| 77 | - | ||
| 78 | - PayOrderExtensionDO extensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); | ||
| 79 | - if (ObjectUtil.isNotNull(extensionDO)) { | ||
| 80 | - respVO.setPayOrderExtension(PayOrderConvert.INSTANCE.orderDetailExtensionConvert(extensionDO)); | 59 | + PayOrderDO order = orderService.getOrder(id); |
| 60 | + if (order == null) { | ||
| 61 | + return success(null); | ||
| 81 | } | 62 | } |
| 82 | 63 | ||
| 83 | - return success(respVO); | 64 | + // 拼接返回 |
| 65 | + PayAppDO app = appService.getApp(order.getAppId()); | ||
| 66 | + PayOrderExtensionDO orderExtension = orderService.getOrderExtension(order.getExtensionId()); | ||
| 67 | + return success(PayOrderConvert.INSTANCE.convert(order, orderExtension, app)); | ||
| 84 | } | 68 | } |
| 85 | 69 | ||
| 86 | @PostMapping("/submit") | 70 | @PostMapping("/submit") |
| 87 | @Operation(summary = "提交支付订单") | 71 | @Operation(summary = "提交支付订单") |
| 88 | public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { | 72 | public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { |
| 89 | - PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP()); | 73 | + PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); |
| 90 | return success(respVO); | 74 | return success(respVO); |
| 91 | } | 75 | } |
| 92 | 76 | ||
| @@ -94,62 +78,34 @@ public class PayOrderController { | @@ -94,62 +78,34 @@ public class PayOrderController { | ||
| 94 | @Operation(summary = "获得支付订单分页") | 78 | @Operation(summary = "获得支付订单分页") |
| 95 | @PreAuthorize("@ss.hasPermission('pay:order:query')") | 79 | @PreAuthorize("@ss.hasPermission('pay:order:query')") |
| 96 | public CommonResult<PageResult<PayOrderPageItemRespVO>> getOrderPage(@Valid PayOrderPageReqVO pageVO) { | 80 | public CommonResult<PageResult<PayOrderPageItemRespVO>> getOrderPage(@Valid PayOrderPageReqVO pageVO) { |
| 97 | - PageResult<PayOrderDO> pageResult = payOrderService.getOrderPage(pageVO); | 81 | + PageResult<PayOrderDO> pageResult = orderService.getOrderPage(pageVO); |
| 98 | if (CollectionUtil.isEmpty(pageResult.getList())) { | 82 | if (CollectionUtil.isEmpty(pageResult.getList())) { |
| 99 | return success(new PageResult<>(pageResult.getTotal())); | 83 | return success(new PageResult<>(pageResult.getTotal())); |
| 100 | } | 84 | } |
| 101 | 85 | ||
| 102 | - // 处理应用ID数据 | ||
| 103 | - Map<Long, PayAppDO> appMap = appService.getAppMap( | ||
| 104 | - CollectionUtils.convertList(pageResult.getList(), PayOrderDO::getAppId)); | ||
| 105 | - | ||
| 106 | - List<PayOrderPageItemRespVO> pageList = new ArrayList<>(pageResult.getList().size()); | ||
| 107 | - pageResult.getList().forEach(c -> { | ||
| 108 | - PayAppDO appDO = appMap.get(c.getAppId()); | ||
| 109 | - PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | ||
| 110 | - | ||
| 111 | - PayOrderPageItemRespVO orderItem = PayOrderConvert.INSTANCE.pageConvertItemPage(c); | ||
| 112 | - orderItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | ||
| 113 | - orderItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | ||
| 114 | - pageList.add(orderItem); | ||
| 115 | - }); | ||
| 116 | - return success(new PageResult<>(pageList, pageResult.getTotal())); | 86 | + // 拼接返回 |
| 87 | + Map<Long, PayAppDO> appMap = appService.getAppMap(convertList(pageResult.getList(), PayOrderDO::getAppId)); | ||
| 88 | + return success(PayOrderConvert.INSTANCE.convertPage(pageResult, appMap)); | ||
| 117 | } | 89 | } |
| 118 | 90 | ||
| 119 | @GetMapping("/export-excel") | 91 | @GetMapping("/export-excel") |
| 120 | - @Operation(summary = "导出支付订单Excel") | 92 | + @Operation(summary = "导出支付订单 Excel") |
| 121 | @PreAuthorize("@ss.hasPermission('pay:order:export')") | 93 | @PreAuthorize("@ss.hasPermission('pay:order:export')") |
| 122 | @OperateLog(type = EXPORT) | 94 | @OperateLog(type = EXPORT) |
| 123 | public void exportOrderExcel(@Valid PayOrderExportReqVO exportReqVO, | 95 | public void exportOrderExcel(@Valid PayOrderExportReqVO exportReqVO, |
| 124 | HttpServletResponse response) throws IOException { | 96 | HttpServletResponse response) throws IOException { |
| 125 | - List<PayOrderDO> list = payOrderService.getOrderList(exportReqVO); | 97 | + List<PayOrderDO> list = orderService.getOrderList(exportReqVO); |
| 126 | if (CollectionUtil.isEmpty(list)) { | 98 | if (CollectionUtil.isEmpty(list)) { |
| 127 | ExcelUtils.write(response, "支付订单.xls", "数据", | 99 | ExcelUtils.write(response, "支付订单.xls", "数据", |
| 128 | PayOrderExcelVO.class, new ArrayList<>()); | 100 | PayOrderExcelVO.class, new ArrayList<>()); |
| 101 | + return; | ||
| 129 | } | 102 | } |
| 130 | 103 | ||
| 131 | - // 处理应用ID数据 | ||
| 132 | - Map<Long, PayAppDO> appMap = appService.getAppMap( | ||
| 133 | - CollectionUtils.convertList(list, PayOrderDO::getAppId)); | ||
| 134 | - // 处理扩展订单数据 | ||
| 135 | - Map<Long, PayOrderExtensionDO> orderExtensionMap = orderExtensionService | ||
| 136 | - .getOrderExtensionMap(CollectionUtils.convertList(list, PayOrderDO::getSuccessExtensionId)); | ||
| 137 | - | ||
| 138 | - List<PayOrderExcelVO> excelDatum = new ArrayList<>(list.size()); | ||
| 139 | - list.forEach(c -> { | ||
| 140 | - PayAppDO appDO = appMap.get(c.getAppId()); | ||
| 141 | - PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | ||
| 142 | - PayOrderExtensionDO orderExtensionDO = orderExtensionMap.get(c.getSuccessExtensionId()); | ||
| 143 | - | ||
| 144 | - PayOrderExcelVO excelItem = PayOrderConvert.INSTANCE.excelConvert(c); | ||
| 145 | - excelItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | ||
| 146 | - excelItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | ||
| 147 | - excelItem.setNo(ObjectUtil.isNotNull(orderExtensionDO) ? orderExtensionDO.getNo() : ""); | ||
| 148 | - excelDatum.add(excelItem); | ||
| 149 | - }); | ||
| 150 | - | 104 | + // 拼接返回 |
| 105 | + Map<Long, PayAppDO> appMap = appService.getAppMap(convertList(list, PayOrderDO::getAppId)); | ||
| 106 | + List<PayOrderExcelVO> excelList = PayOrderConvert.INSTANCE.convertList(list, appMap); | ||
| 151 | // 导出 Excel | 107 | // 导出 Excel |
| 152 | - ExcelUtils.write(response, "支付订单.xls", "数据", PayOrderExcelVO.class, excelDatum); | 108 | + ExcelUtils.write(response, "支付订单.xls", "数据", PayOrderExcelVO.class, excelList); |
| 153 | } | 109 | } |
| 154 | 110 | ||
| 155 | } | 111 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderBaseVO.java
| @@ -17,51 +17,47 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -17,51 +17,47 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 17 | @Data | 17 | @Data |
| 18 | public class PayOrderBaseVO { | 18 | public class PayOrderBaseVO { |
| 19 | 19 | ||
| 20 | - @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED) | 20 | + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 21 | @NotNull(message = "应用编号不能为空") | 21 | @NotNull(message = "应用编号不能为空") |
| 22 | private Long appId; | 22 | private Long appId; |
| 23 | 23 | ||
| 24 | - @Schema(description = "渠道编号") | 24 | + @Schema(description = "渠道编号", example = "2048") |
| 25 | private Long channelId; | 25 | private Long channelId; |
| 26 | 26 | ||
| 27 | - @Schema(description = "渠道编码") | 27 | + @Schema(description = "渠道编码", example = "wx_app") |
| 28 | private String channelCode; | 28 | private String channelCode; |
| 29 | 29 | ||
| 30 | - @Schema(description = "商户订单编号", requiredMode = Schema.RequiredMode.REQUIRED) | 30 | + @Schema(description = "商户订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") |
| 31 | @NotNull(message = "商户订单编号不能为空") | 31 | @NotNull(message = "商户订单编号不能为空") |
| 32 | private String merchantOrderId; | 32 | private String merchantOrderId; |
| 33 | 33 | ||
| 34 | - @Schema(description = "商品标题", requiredMode = Schema.RequiredMode.REQUIRED) | 34 | + @Schema(description = "商品标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆") |
| 35 | @NotNull(message = "商品标题不能为空") | 35 | @NotNull(message = "商品标题不能为空") |
| 36 | private String subject; | 36 | private String subject; |
| 37 | 37 | ||
| 38 | - @Schema(description = "商品描述", requiredMode = Schema.RequiredMode.REQUIRED) | 38 | + @Schema(description = "商品描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是土豆") |
| 39 | @NotNull(message = "商品描述不能为空") | 39 | @NotNull(message = "商品描述不能为空") |
| 40 | private String body; | 40 | private String body; |
| 41 | 41 | ||
| 42 | - @Schema(description = "异步通知地址", requiredMode = Schema.RequiredMode.REQUIRED) | 42 | + @Schema(description = "异步通知地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/pay/notify") |
| 43 | @NotNull(message = "异步通知地址不能为空") | 43 | @NotNull(message = "异步通知地址不能为空") |
| 44 | private String notifyUrl; | 44 | private String notifyUrl; |
| 45 | 45 | ||
| 46 | - @Schema(description = "通知商户支付结果的回调状态", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 47 | - @NotNull(message = "通知商户支付结果的回调状态不能为空") | ||
| 48 | - private Integer notifyStatus; | ||
| 49 | - | ||
| 50 | - @Schema(description = "支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED) | 46 | + @Schema(description = "支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 51 | @NotNull(message = "支付金额,单位:分不能为空") | 47 | @NotNull(message = "支付金额,单位:分不能为空") |
| 52 | private Long price; | 48 | private Long price; |
| 53 | 49 | ||
| 54 | - @Schema(description = "渠道手续费,单位:百分比") | 50 | + @Schema(description = "渠道手续费,单位:百分比", example = "10") |
| 55 | private Double channelFeeRate; | 51 | private Double channelFeeRate; |
| 56 | 52 | ||
| 57 | - @Schema(description = "渠道手续金额,单位:分") | ||
| 58 | - private Long channelFeePrice; | 53 | + @Schema(description = "渠道手续金额,单位:分", example = "100") |
| 54 | + private Integer channelFeePrice; | ||
| 59 | 55 | ||
| 60 | - @Schema(description = "支付状态", requiredMode = Schema.RequiredMode.REQUIRED) | 56 | + @Schema(description = "支付状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 61 | @NotNull(message = "支付状态不能为空") | 57 | @NotNull(message = "支付状态不能为空") |
| 62 | private Integer status; | 58 | private Integer status; |
| 63 | 59 | ||
| 64 | - @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED) | 60 | + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") |
| 65 | @NotNull(message = "用户 IP不能为空") | 61 | @NotNull(message = "用户 IP不能为空") |
| 66 | private String userIp; | 62 | private String userIp; |
| 67 | 63 | ||
| @@ -74,29 +70,20 @@ public class PayOrderBaseVO { | @@ -74,29 +70,20 @@ public class PayOrderBaseVO { | ||
| 74 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 70 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 75 | private LocalDateTime successTime; | 71 | private LocalDateTime successTime; |
| 76 | 72 | ||
| 77 | - @Schema(description = "订单支付通知时间") | ||
| 78 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 79 | - private LocalDateTime notifyTime; | ||
| 80 | - | ||
| 81 | - @Schema(description = "支付成功的订单拓展单编号") | ||
| 82 | - private Long successExtensionId; | ||
| 83 | - | ||
| 84 | - @Schema(description = "退款状态", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 85 | - @NotNull(message = "退款状态不能为空") | ||
| 86 | - private Integer refundStatus; | 73 | + @Schema(description = "支付成功的订单拓展单编号", example = "50") |
| 74 | + private Long extensionId; | ||
| 87 | 75 | ||
| 88 | - @Schema(description = "退款次数", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 89 | - @NotNull(message = "退款次数不能为空") | ||
| 90 | - private Integer refundTimes; | 76 | + @Schema(description = "支付订单号", example = "2048888") |
| 77 | + private String no; | ||
| 91 | 78 | ||
| 92 | - @Schema(description = "退款总金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED) | 79 | + @Schema(description = "退款总金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 93 | @NotNull(message = "退款总金额,单位:分不能为空") | 80 | @NotNull(message = "退款总金额,单位:分不能为空") |
| 94 | private Long refundPrice; | 81 | private Long refundPrice; |
| 95 | 82 | ||
| 96 | - @Schema(description = "渠道用户编号") | 83 | + @Schema(description = "渠道用户编号", example = "2048") |
| 97 | private String channelUserId; | 84 | private String channelUserId; |
| 98 | 85 | ||
| 99 | - @Schema(description = "渠道订单号") | 86 | + @Schema(description = "渠道订单号", example = "4096") |
| 100 | private String channelOrderNo; | 87 | private String channelOrderNo; |
| 101 | 88 | ||
| 102 | } | 89 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java
| @@ -13,32 +13,33 @@ import java.time.LocalDateTime; | @@ -13,32 +13,33 @@ import java.time.LocalDateTime; | ||
| 13 | @ToString(callSuper = true) | 13 | @ToString(callSuper = true) |
| 14 | public class PayOrderDetailsRespVO extends PayOrderBaseVO { | 14 | public class PayOrderDetailsRespVO extends PayOrderBaseVO { |
| 15 | 15 | ||
| 16 | - @Schema(description = "支付订单编号") | 16 | + @Schema(description = "支付订单编号", required = true, example = "1024") |
| 17 | private Long id; | 17 | private Long id; |
| 18 | 18 | ||
| 19 | - @Schema(description = "应用名称") | 19 | + @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") |
| 20 | private String appName; | 20 | private String appName; |
| 21 | 21 | ||
| 22 | - @Schema(description = "渠道编号名称") | ||
| 23 | - private String channelCodeName; | ||
| 24 | - | ||
| 25 | - @Schema(description = "创建时间") | 22 | + @Schema(description = "创建时间", required = true) |
| 26 | private LocalDateTime createTime; | 23 | private LocalDateTime createTime; |
| 27 | 24 | ||
| 25 | + @Schema(description = "更新时间", required = true) | ||
| 26 | + private LocalDateTime updateTime; | ||
| 27 | + | ||
| 28 | /** | 28 | /** |
| 29 | * 支付订单扩展 | 29 | * 支付订单扩展 |
| 30 | */ | 30 | */ |
| 31 | - private PayOrderExtension payOrderExtension; | 31 | + private PayOrderExtension extension; |
| 32 | 32 | ||
| 33 | @Data | 33 | @Data |
| 34 | @Schema(description = "支付订单扩展") | 34 | @Schema(description = "支付订单扩展") |
| 35 | public static class PayOrderExtension { | 35 | public static class PayOrderExtension { |
| 36 | 36 | ||
| 37 | - @Schema(description = "支付订单号") | 37 | + @Schema(description = "支付订单号", required = true, example = "1024") |
| 38 | private String no; | 38 | private String no; |
| 39 | 39 | ||
| 40 | @Schema(description = "支付异步通知的内容") | 40 | @Schema(description = "支付异步通知的内容") |
| 41 | private String channelNotifyData; | 41 | private String channelNotifyData; |
| 42 | + | ||
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | } | 45 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.controller.admin.order.vo; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.controller.admin.order.vo; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | 3 | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| 4 | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | 4 | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| 5 | +import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; | ||
| 5 | import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; | 6 | import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; |
| 6 | import com.alibaba.excel.annotation.ExcelProperty; | 7 | import com.alibaba.excel.annotation.ExcelProperty; |
| 7 | import lombok.Data; | 8 | import lombok.Data; |
| @@ -9,53 +10,44 @@ import lombok.Data; | @@ -9,53 +10,44 @@ import lombok.Data; | ||
| 9 | import java.time.LocalDateTime; | 10 | import java.time.LocalDateTime; |
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| 12 | - * 支付订单Excel VO | 13 | + * 支付订单 Excel VO |
| 13 | * | 14 | * |
| 14 | * @author aquan | 15 | * @author aquan |
| 15 | */ | 16 | */ |
| 16 | @Data | 17 | @Data |
| 17 | public class PayOrderExcelVO { | 18 | public class PayOrderExcelVO { |
| 18 | 19 | ||
| 19 | - @ExcelProperty("支付订单编号") | 20 | + @ExcelProperty("编号") |
| 20 | private Long id; | 21 | private Long id; |
| 21 | 22 | ||
| 22 | - @ExcelProperty(value = "应用名称") | ||
| 23 | - private String appName; | ||
| 24 | - | ||
| 25 | - @ExcelProperty("商品标题") | ||
| 26 | - private String subject; | 23 | + @ExcelProperty("创建时间") |
| 24 | + private LocalDateTime createTime; | ||
| 27 | 25 | ||
| 28 | - @ExcelProperty("商户订单编号") | ||
| 29 | - private String merchantOrderId; | 26 | + @ExcelProperty(value = "支付金额", converter = MoneyConvert.class) |
| 27 | + private Integer price; | ||
| 30 | 28 | ||
| 31 | - @ExcelProperty("渠道订单号") | ||
| 32 | - private String channelOrderNo; | 29 | + @ExcelProperty(value = "退款金额", converter = MoneyConvert.class) |
| 30 | + private Integer refundPrice; | ||
| 33 | 31 | ||
| 34 | - @ExcelProperty(value = "支付订单号") | ||
| 35 | - private String no; | 32 | + @ExcelProperty(value = "手续金额", converter = MoneyConvert.class) |
| 33 | + private Integer channelFeePrice; | ||
| 36 | 34 | ||
| 37 | - @ExcelProperty("支付金额,单位:元") | ||
| 38 | - private String price; | 35 | + @ExcelProperty("商户单号") |
| 36 | + private String merchantOrderId; | ||
| 39 | 37 | ||
| 40 | - @ExcelProperty("渠道手续金额,单位:元") | ||
| 41 | - private String channelFeePrice; | 38 | + @ExcelProperty(value = "支付单号") |
| 39 | + private String no; | ||
| 42 | 40 | ||
| 43 | - @ExcelProperty("渠道手续费,单位:百分比") | ||
| 44 | - private String channelFeeRate; | 41 | + @ExcelProperty("渠道单号") |
| 42 | + private String channelOrderNo; | ||
| 45 | 43 | ||
| 46 | - @DictFormat(DictTypeConstants.ORDER_STATUS) | ||
| 47 | @ExcelProperty(value = "支付状态", converter = DictConvert.class) | 44 | @ExcelProperty(value = "支付状态", converter = DictConvert.class) |
| 45 | + @DictFormat(DictTypeConstants.ORDER_STATUS) | ||
| 48 | private Integer status; | 46 | private Integer status; |
| 49 | 47 | ||
| 50 | - @DictFormat(DictTypeConstants.ORDER_NOTIFY_STATUS) | ||
| 51 | - @ExcelProperty(value = "通知商户支付结果的回调状态", converter = DictConvert.class) | ||
| 52 | - private Integer notifyStatus; | ||
| 53 | - | ||
| 54 | - @ExcelProperty("异步通知地址") | ||
| 55 | - private String notifyUrl; | ||
| 56 | - | ||
| 57 | - @ExcelProperty("创建时间") | ||
| 58 | - private LocalDateTime createTime; | 48 | + @ExcelProperty(value = "渠道编号名称", converter = DictConvert.class) |
| 49 | + @DictFormat(DictTypeConstants.CHANNEL_CODE) | ||
| 50 | + private String channelCode; | ||
| 59 | 51 | ||
| 60 | @ExcelProperty("订单支付成功时间") | 52 | @ExcelProperty("订单支付成功时间") |
| 61 | private LocalDateTime successTime; | 53 | private LocalDateTime successTime; |
| @@ -63,24 +55,11 @@ public class PayOrderExcelVO { | @@ -63,24 +55,11 @@ public class PayOrderExcelVO { | ||
| 63 | @ExcelProperty("订单失效时间") | 55 | @ExcelProperty("订单失效时间") |
| 64 | private LocalDateTime expireTime; | 56 | private LocalDateTime expireTime; |
| 65 | 57 | ||
| 66 | - @ExcelProperty("订单支付通知时间") | ||
| 67 | - private LocalDateTime notifyTime; | ||
| 68 | - | ||
| 69 | - @ExcelProperty(value = "渠道编号名称") | ||
| 70 | - private String channelCodeName; | ||
| 71 | - | ||
| 72 | - @ExcelProperty("用户 IP") | ||
| 73 | - private String userIp; | ||
| 74 | - | ||
| 75 | - @DictFormat(DictTypeConstants.ORDER_REFUND_STATUS) | ||
| 76 | - @ExcelProperty(value = "退款状态", converter = DictConvert.class) | ||
| 77 | - private Integer refundStatus; | ||
| 78 | - | ||
| 79 | - @ExcelProperty("退款次数") | ||
| 80 | - private Integer refundTimes; | 58 | + @ExcelProperty(value = "应用名称") |
| 59 | + private String appName; | ||
| 81 | 60 | ||
| 82 | - @ExcelProperty("退款总金额,单位:元") | ||
| 83 | - private String refundPrice; | 61 | + @ExcelProperty("商品标题") |
| 62 | + private String subject; | ||
| 84 | 63 | ||
| 85 | @ExcelProperty("商品描述") | 64 | @ExcelProperty("商品描述") |
| 86 | private String body; | 65 | private String body; |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExportReqVO.java
| @@ -12,75 +12,24 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -12,75 +12,24 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 12 | @Data | 12 | @Data |
| 13 | public class PayOrderExportReqVO { | 13 | public class PayOrderExportReqVO { |
| 14 | 14 | ||
| 15 | - @Schema(description = "应用编号") | 15 | + @Schema(description = "应用编号", example = "1024") |
| 16 | private Long appId; | 16 | private Long appId; |
| 17 | 17 | ||
| 18 | - @Schema(description = "渠道编号") | ||
| 19 | - private Long channelId; | ||
| 20 | - | ||
| 21 | - @Schema(description = "渠道编码") | 18 | + @Schema(description = "渠道编码", example = "wx_app") |
| 22 | private String channelCode; | 19 | private String channelCode; |
| 23 | 20 | ||
| 24 | - @Schema(description = "商户订单编号") | 21 | + @Schema(description = "商户订单编号", example = "4096") |
| 25 | private String merchantOrderId; | 22 | private String merchantOrderId; |
| 26 | 23 | ||
| 27 | - @Schema(description = "商品标题") | ||
| 28 | - private String subject; | ||
| 29 | - | ||
| 30 | - @Schema(description = "商品描述") | ||
| 31 | - private String body; | ||
| 32 | - | ||
| 33 | - @Schema(description = "异步通知地址") | ||
| 34 | - private String notifyUrl; | ||
| 35 | - | ||
| 36 | - @Schema(description = "通知商户支付结果的回调状态") | ||
| 37 | - private Integer notifyStatus; | ||
| 38 | - | ||
| 39 | - @Schema(description = "支付金额,单位:分") | ||
| 40 | - private Long price; | ||
| 41 | - | ||
| 42 | - @Schema(description = "渠道手续费,单位:百分比") | ||
| 43 | - private Double channelFeeRate; | 24 | + @Schema(description = "渠道编号", example = "1888") |
| 25 | + private String channelOrderNo; | ||
| 44 | 26 | ||
| 45 | - @Schema(description = "渠道手续金额,单位:分") | ||
| 46 | - private Long channelFeePrice; | 27 | + @Schema(description = "支付单号", example = "2014888") |
| 28 | + private String no; | ||
| 47 | 29 | ||
| 48 | - @Schema(description = "支付状态") | 30 | + @Schema(description = "支付状态", example = "0") |
| 49 | private Integer status; | 31 | private Integer status; |
| 50 | 32 | ||
| 51 | - @Schema(description = "用户 IP") | ||
| 52 | - private String userIp; | ||
| 53 | - | ||
| 54 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 55 | - @Schema(description = "订单失效时间") | ||
| 56 | - private LocalDateTime[] expireTime; | ||
| 57 | - | ||
| 58 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 59 | - @Schema(description = "开始订单支付成功时间") | ||
| 60 | - private LocalDateTime[] successTime; | ||
| 61 | - | ||
| 62 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 63 | - @Schema(description = "开始订单支付通知时间") | ||
| 64 | - private LocalDateTime[] notifyTime; | ||
| 65 | - | ||
| 66 | - @Schema(description = "支付成功的订单拓展单编号") | ||
| 67 | - private Long successExtensionId; | ||
| 68 | - | ||
| 69 | - @Schema(description = "退款状态") | ||
| 70 | - private Integer refundStatus; | ||
| 71 | - | ||
| 72 | - @Schema(description = "退款次数") | ||
| 73 | - private Integer refundTimes; | ||
| 74 | - | ||
| 75 | - @Schema(description = "退款总金额,单位:分") | ||
| 76 | - private Long refundPrice; | ||
| 77 | - | ||
| 78 | - @Schema(description = "渠道用户编号") | ||
| 79 | - private String channelUserId; | ||
| 80 | - | ||
| 81 | - @Schema(description = "渠道订单号") | ||
| 82 | - private String channelOrderNo; | ||
| 83 | - | ||
| 84 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 33 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 85 | @Schema(description = "创建时间") | 34 | @Schema(description = "创建时间") |
| 86 | private LocalDateTime[] createTime; | 35 | private LocalDateTime[] createTime; |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageItemRespVO.java
| @@ -13,20 +13,13 @@ import java.time.LocalDateTime; | @@ -13,20 +13,13 @@ import java.time.LocalDateTime; | ||
| 13 | @ToString(callSuper = true) | 13 | @ToString(callSuper = true) |
| 14 | public class PayOrderPageItemRespVO extends PayOrderBaseVO { | 14 | public class PayOrderPageItemRespVO extends PayOrderBaseVO { |
| 15 | 15 | ||
| 16 | - @Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED) | 16 | + @Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 17 | private Long id; | 17 | private Long id; |
| 18 | 18 | ||
| 19 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | 19 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 20 | private LocalDateTime createTime; | 20 | private LocalDateTime createTime; |
| 21 | 21 | ||
| 22 | - @Schema(description = "应用名称") | 22 | + @Schema(description = "应用名称", example = "wx_pay") |
| 23 | private String appName; | 23 | private String appName; |
| 24 | 24 | ||
| 25 | - @Schema(description = "渠道名称") | ||
| 26 | - private String channelCodeName; | ||
| 27 | - | ||
| 28 | - @Schema(description = "支付订单号") | ||
| 29 | - private String no; | ||
| 30 | - | ||
| 31 | - | ||
| 32 | } | 25 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageReqVO.java
| @@ -17,75 +17,24 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -17,75 +17,24 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 17 | @ToString(callSuper = true) | 17 | @ToString(callSuper = true) |
| 18 | public class PayOrderPageReqVO extends PageParam { | 18 | public class PayOrderPageReqVO extends PageParam { |
| 19 | 19 | ||
| 20 | - @Schema(description = "应用编号") | 20 | + @Schema(description = "应用编号", example = "1024") |
| 21 | private Long appId; | 21 | private Long appId; |
| 22 | 22 | ||
| 23 | - @Schema(description = "渠道编号") | ||
| 24 | - private Long channelId; | ||
| 25 | - | ||
| 26 | - @Schema(description = "渠道编码") | 23 | + @Schema(description = "渠道编码", example = "wx_app") |
| 27 | private String channelCode; | 24 | private String channelCode; |
| 28 | 25 | ||
| 29 | - @Schema(description = "商户订单编号") | 26 | + @Schema(description = "商户订单编号", example = "4096") |
| 30 | private String merchantOrderId; | 27 | private String merchantOrderId; |
| 31 | 28 | ||
| 32 | - @Schema(description = "商品标题") | ||
| 33 | - private String subject; | ||
| 34 | - | ||
| 35 | - @Schema(description = "商品描述") | ||
| 36 | - private String body; | ||
| 37 | - | ||
| 38 | - @Schema(description = "异步通知地址") | ||
| 39 | - private String notifyUrl; | ||
| 40 | - | ||
| 41 | - @Schema(description = "通知商户支付结果的回调状态") | ||
| 42 | - private Integer notifyStatus; | ||
| 43 | - | ||
| 44 | - @Schema(description = "支付金额,单位:分") | ||
| 45 | - private Long price; | ||
| 46 | - | ||
| 47 | - @Schema(description = "渠道手续费,单位:百分比") | ||
| 48 | - private Double channelFeeRate; | 29 | + @Schema(description = "渠道编号", example = "1888") |
| 30 | + private String channelOrderNo; | ||
| 49 | 31 | ||
| 50 | - @Schema(description = "渠道手续金额,单位:分") | ||
| 51 | - private Long channelFeePrice; | 32 | + @Schema(description = "支付单号", example = "2014888") |
| 33 | + private String no; | ||
| 52 | 34 | ||
| 53 | - @Schema(description = "支付状态") | 35 | + @Schema(description = "支付状态", example = "0") |
| 54 | private Integer status; | 36 | private Integer status; |
| 55 | 37 | ||
| 56 | - @Schema(description = "用户 IP") | ||
| 57 | - private String userIp; | ||
| 58 | - | ||
| 59 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 60 | - @Schema(description = "订单失效时间") | ||
| 61 | - private LocalDateTime[] expireTime; | ||
| 62 | - | ||
| 63 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 64 | - @Schema(description = "订单支付成功时间") | ||
| 65 | - private LocalDateTime[] successTime; | ||
| 66 | - | ||
| 67 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 68 | - @Schema(description = "订单支付通知时间") | ||
| 69 | - private LocalDateTime[] notifyTime; | ||
| 70 | - | ||
| 71 | - @Schema(description = "支付成功的订单拓展单编号") | ||
| 72 | - private Long successExtensionId; | ||
| 73 | - | ||
| 74 | - @Schema(description = "退款状态") | ||
| 75 | - private Integer refundStatus; | ||
| 76 | - | ||
| 77 | - @Schema(description = "退款次数") | ||
| 78 | - private Integer refundTimes; | ||
| 79 | - | ||
| 80 | - @Schema(description = "退款总金额,单位:分") | ||
| 81 | - private Long refundPrice; | ||
| 82 | - | ||
| 83 | - @Schema(description = "渠道用户编号") | ||
| 84 | - private String channelUserId; | ||
| 85 | - | ||
| 86 | - @Schema(description = "渠道订单号") | ||
| 87 | - private String channelOrderNo; | ||
| 88 | - | ||
| 89 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 38 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 90 | @Schema(description = "创建时间") | 39 | @Schema(description = "创建时间") |
| 91 | private LocalDateTime[] createTime; | 40 | private LocalDateTime[] createTime; |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderRespVO.java
100755 → 100644
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/PayRefundController.java
| 1 | package cn.iocoder.yudao.module.pay.controller.admin.refund; | 1 | package cn.iocoder.yudao.module.pay.controller.admin.refund; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollectionUtil; | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | -import cn.hutool.core.util.ObjectUtil; | 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||
| 5 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*; | 8 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*; |
| 6 | import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert; | 9 | import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert; |
| 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| 8 | -import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | ||
| 9 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 11 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 10 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 12 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 11 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 13 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 12 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | 14 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 13 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 14 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 15 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 16 | -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||
| 17 | -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||
| 18 | -import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | ||
| 19 | -import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 20 | -import io.swagger.v3.oas.annotations.Parameter; | ||
| 21 | import io.swagger.v3.oas.annotations.Operation; | 15 | import io.swagger.v3.oas.annotations.Operation; |
| 16 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 17 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 22 | import org.springframework.security.access.prepost.PreAuthorize; | 18 | import org.springframework.security.access.prepost.PreAuthorize; |
| 23 | import org.springframework.validation.annotation.Validated; | 19 | import org.springframework.validation.annotation.Validated; |
| 24 | import org.springframework.web.bind.annotation.GetMapping; | 20 | import org.springframework.web.bind.annotation.GetMapping; |
| @@ -35,6 +31,7 @@ import java.util.List; | @@ -35,6 +31,7 @@ import java.util.List; | ||
| 35 | import java.util.Map; | 31 | import java.util.Map; |
| 36 | 32 | ||
| 37 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 33 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 38 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 35 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 39 | 36 | ||
| 40 | @Tag(name = "管理后台 - 退款订单") | 37 | @Tag(name = "管理后台 - 退款订单") |
| @@ -56,20 +53,13 @@ public class PayRefundController { | @@ -56,20 +53,13 @@ public class PayRefundController { | ||
| 56 | @PreAuthorize("@ss.hasPermission('pay:refund:query')") | 53 | @PreAuthorize("@ss.hasPermission('pay:refund:query')") |
| 57 | public CommonResult<PayRefundDetailsRespVO> getRefund(@RequestParam("id") Long id) { | 54 | public CommonResult<PayRefundDetailsRespVO> getRefund(@RequestParam("id") Long id) { |
| 58 | PayRefundDO refund = refundService.getRefund(id); | 55 | PayRefundDO refund = refundService.getRefund(id); |
| 59 | - if (ObjectUtil.isNull(refund)) { | 56 | + if (refund == null) { |
| 60 | return success(new PayRefundDetailsRespVO()); | 57 | return success(new PayRefundDetailsRespVO()); |
| 61 | } | 58 | } |
| 62 | 59 | ||
| 63 | - PayAppDO appDO = appService.getApp(refund.getAppId()); | ||
| 64 | - PayChannelEnum channelEnum = PayChannelEnum.getByCode(refund.getChannelCode()); | ||
| 65 | - PayOrderDO orderDO = orderService.getOrder(refund.getOrderId()); | ||
| 66 | - | ||
| 67 | - PayRefundDetailsRespVO refundDetail = PayRefundConvert.INSTANCE.refundDetailConvert(refund); | ||
| 68 | - refundDetail.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | ||
| 69 | - refundDetail.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | ||
| 70 | - refundDetail.setSubject(orderDO.getSubject()); | ||
| 71 | - | ||
| 72 | - return success(refundDetail); | 60 | + // 拼接数据 |
| 61 | + PayAppDO app = appService.getApp(refund.getAppId()); | ||
| 62 | + return success(PayRefundConvert.INSTANCE.convert(refund, app)); | ||
| 73 | } | 63 | } |
| 74 | 64 | ||
| 75 | @GetMapping("/page") | 65 | @GetMapping("/page") |
| @@ -82,21 +72,8 @@ public class PayRefundController { | @@ -82,21 +72,8 @@ public class PayRefundController { | ||
| 82 | } | 72 | } |
| 83 | 73 | ||
| 84 | // 处理应用ID数据 | 74 | // 处理应用ID数据 |
| 85 | - Map<Long, PayAppDO> appMap = appService.getAppMap( | ||
| 86 | - CollectionUtils.convertList(pageResult.getList(), PayRefundDO::getAppId)); | ||
| 87 | - List<PayRefundPageItemRespVO> list = new ArrayList<>(pageResult.getList().size()); | ||
| 88 | - pageResult.getList().forEach(c -> { | ||
| 89 | - PayAppDO appDO = appMap.get(c.getAppId()); | ||
| 90 | - PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | ||
| 91 | - | ||
| 92 | - PayRefundPageItemRespVO item = PayRefundConvert.INSTANCE.pageItemConvert(c); | ||
| 93 | - | ||
| 94 | - item.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | ||
| 95 | - item.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | ||
| 96 | - list.add(item); | ||
| 97 | - }); | ||
| 98 | - | ||
| 99 | - return success(new PageResult<>(list, pageResult.getTotal())); | 75 | + Map<Long, PayAppDO> appMap = appService.getAppMap(convertList(pageResult.getList(), PayRefundDO::getAppId)); |
| 76 | + return success(PayRefundConvert.INSTANCE.convertPage(pageResult, appMap)); | ||
| 100 | } | 77 | } |
| 101 | 78 | ||
| 102 | @GetMapping("/export-excel") | 79 | @GetMapping("/export-excel") |
| @@ -105,36 +82,18 @@ public class PayRefundController { | @@ -105,36 +82,18 @@ public class PayRefundController { | ||
| 105 | @OperateLog(type = EXPORT) | 82 | @OperateLog(type = EXPORT) |
| 106 | public void exportRefundExcel(@Valid PayRefundExportReqVO exportReqVO, | 83 | public void exportRefundExcel(@Valid PayRefundExportReqVO exportReqVO, |
| 107 | HttpServletResponse response) throws IOException { | 84 | HttpServletResponse response) throws IOException { |
| 108 | - | ||
| 109 | List<PayRefundDO> list = refundService.getRefundList(exportReqVO); | 85 | List<PayRefundDO> list = refundService.getRefundList(exportReqVO); |
| 110 | if (CollectionUtil.isEmpty(list)) { | 86 | if (CollectionUtil.isEmpty(list)) { |
| 111 | ExcelUtils.write(response, "退款订单.xls", "数据", | 87 | ExcelUtils.write(response, "退款订单.xls", "数据", |
| 112 | PayRefundExcelVO.class, new ArrayList<>()); | 88 | PayRefundExcelVO.class, new ArrayList<>()); |
| 89 | + return; | ||
| 113 | } | 90 | } |
| 114 | 91 | ||
| 115 | - // 处理应用ID数据 | ||
| 116 | - Map<Long, PayAppDO> appMap = appService.getAppMap( | ||
| 117 | - CollectionUtils.convertList(list, PayRefundDO::getAppId)); | ||
| 118 | - | ||
| 119 | - List<PayRefundExcelVO> excelDatum = new ArrayList<>(list.size()); | ||
| 120 | - // 处理商品名称数据 | ||
| 121 | - Map<Long, PayOrderDO> orderMap = orderService.getOrderSubjectMap( | ||
| 122 | - CollectionUtils.convertList(list, PayRefundDO::getOrderId)); | ||
| 123 | - | ||
| 124 | - list.forEach(c -> { | ||
| 125 | - PayAppDO appDO = appMap.get(c.getAppId()); | ||
| 126 | - PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | ||
| 127 | - | ||
| 128 | - PayRefundExcelVO excelItem = PayRefundConvert.INSTANCE.excelConvert(c); | ||
| 129 | - excelItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | ||
| 130 | - excelItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | ||
| 131 | - excelItem.setSubject(orderMap.get(c.getOrderId()).getSubject()); | ||
| 132 | - | ||
| 133 | - excelDatum.add(excelItem); | ||
| 134 | - }); | ||
| 135 | - | 92 | + // 拼接返回 |
| 93 | + Map<Long, PayAppDO> appMap = appService.getAppMap(convertList(list, PayRefundDO::getAppId)); | ||
| 94 | + List<PayRefundExcelVO> excelList = PayRefundConvert.INSTANCE.convertList(list, appMap); | ||
| 136 | // 导出 Excel | 95 | // 导出 Excel |
| 137 | - ExcelUtils.write(response, "退款订单.xls", "数据", PayRefundExcelVO.class, excelDatum); | 96 | + ExcelUtils.write(response, "退款订单.xls", "数据", PayRefundExcelVO.class, excelList); |
| 138 | } | 97 | } |
| 139 | 98 | ||
| 140 | } | 99 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundBaseVO.java
| 1 | package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; | 1 | package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; |
| 2 | + | ||
| 2 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 3 | import lombok.Data; | 4 | import lombok.Data; |
| 4 | -import org.springframework.format.annotation.DateTimeFormat; | ||
| 5 | 5 | ||
| 6 | -import javax.validation.constraints.NotNull; | ||
| 7 | import java.time.LocalDateTime; | 6 | import java.time.LocalDateTime; |
| 8 | 7 | ||
| 9 | -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 10 | - | ||
| 11 | /** | 8 | /** |
| 12 | * 退款订单 Base VO,提供给添加、修改、详细的子 VO 使用 | 9 | * 退款订单 Base VO,提供给添加、修改、详细的子 VO 使用 |
| 13 | * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | 10 | * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 |
| @@ -15,91 +12,67 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -15,91 +12,67 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 15 | @Data | 12 | @Data |
| 16 | public class PayRefundBaseVO { | 13 | public class PayRefundBaseVO { |
| 17 | 14 | ||
| 18 | - @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 19 | - @NotNull(message = "应用编号不能为空") | 15 | + @Schema(description = "外部退款号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110") |
| 16 | + private String no; | ||
| 17 | + | ||
| 18 | + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 20 | private Long appId; | 19 | private Long appId; |
| 21 | 20 | ||
| 22 | - @Schema(description = "渠道编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 23 | - @NotNull(message = "渠道编号不能为空") | 21 | + @Schema(description = "渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") |
| 24 | private Long channelId; | 22 | private Long channelId; |
| 25 | 23 | ||
| 26 | - @Schema(description = "渠道编码", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 27 | - @NotNull(message = "渠道编码不能为空") | 24 | + @Schema(description = "渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx_app") |
| 28 | private String channelCode; | 25 | private String channelCode; |
| 29 | 26 | ||
| 30 | - @Schema(description = "支付订单编号 pay_order 表id", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 31 | - @NotNull(message = "支付订单编号 pay_order 表id不能为空") | 27 | + @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 32 | private Long orderId; | 28 | private Long orderId; |
| 33 | 29 | ||
| 34 | - @Schema(description = "交易订单号 pay_extension 表no 字段", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 35 | - @NotNull(message = "交易订单号 pay_extension 表no 字段不能为空") | ||
| 36 | - private String tradeNo; | 30 | + // ========== 商户相关字段 ========== |
| 37 | 31 | ||
| 38 | - @Schema(description = "商户订单编号(商户系统生成)", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 39 | - @NotNull(message = "商户订单编号(商户系统生成)不能为空") | 32 | + @Schema(description = "商户订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "225") |
| 40 | private String merchantOrderId; | 33 | private String merchantOrderId; |
| 41 | 34 | ||
| 42 | - @Schema(description = "商户退款订单号(商户系统生成)", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 43 | - @NotNull(message = "商户退款订单号(商户系统生成)不能为空") | ||
| 44 | - private String merchantRefundNo; | 35 | + @Schema(description = "商户退款订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") |
| 36 | + private String merchantRefundId; | ||
| 45 | 37 | ||
| 46 | - @Schema(description = "异步通知商户地址", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 47 | - @NotNull(message = "异步通知商户地址不能为空") | 38 | + @Schema(description = "异步通知地址", requiredMode = Schema.RequiredMode.REQUIRED) |
| 48 | private String notifyUrl; | 39 | private String notifyUrl; |
| 49 | 40 | ||
| 50 | - @Schema(description = "通知商户退款结果的回调状态", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 51 | - @NotNull(message = "通知商户退款结果的回调状态不能为空") | ||
| 52 | - private Integer notifyStatus; | 41 | + // ========== 退款相关字段 ========== |
| 53 | 42 | ||
| 54 | - @Schema(description = "退款状态", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 55 | - @NotNull(message = "退款状态不能为空") | 43 | + @Schema(description = "退款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| 56 | private Integer status; | 44 | private Integer status; |
| 57 | 45 | ||
| 58 | - @Schema(description = "退款类型(部分退款,全部退款)", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 59 | - @NotNull(message = "退款类型(部分退款,全部退款)不能为空") | ||
| 60 | - private Integer type; | ||
| 61 | - | ||
| 62 | - @Schema(description = "支付金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 63 | - @NotNull(message = "支付金额,单位分不能为空") | ||
| 64 | - private Long payAmount; | 46 | + @Schema(description = "支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 47 | + private Long payPrice; | ||
| 65 | 48 | ||
| 66 | - @Schema(description = "退款金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 67 | - @NotNull(message = "退款金额,单位分不能为空") | ||
| 68 | - private Long refundAmount; | 49 | + @Schema(description = "退款金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") |
| 50 | + private Long refundPrice; | ||
| 69 | 51 | ||
| 70 | - @Schema(description = "退款原因", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 71 | - @NotNull(message = "退款原因不能为空") | 52 | + @Schema(description = "退款原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "我要退了") |
| 72 | private String reason; | 53 | private String reason; |
| 73 | 54 | ||
| 74 | - @Schema(description = "用户 IP") | 55 | + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") |
| 75 | private String userIp; | 56 | private String userIp; |
| 76 | 57 | ||
| 77 | - @Schema(description = "渠道订单号,pay_order 中的channel_order_no 对应", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 78 | - @NotNull(message = "渠道订单号,pay_order 中的channel_order_no 对应不能为空") | 58 | + // ========== 渠道相关字段 ========== |
| 59 | + | ||
| 60 | + @Schema(description = "渠道订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "233") | ||
| 79 | private String channelOrderNo; | 61 | private String channelOrderNo; |
| 80 | 62 | ||
| 81 | - @Schema(description = "渠道退款单号,渠道返回") | 63 | + @Schema(description = "渠道退款单号", example = "2022") |
| 82 | private String channelRefundNo; | 64 | private String channelRefundNo; |
| 83 | 65 | ||
| 84 | - @Schema(description = "渠道调用报错时,错误码") | 66 | + @Schema(description = "退款成功时间") |
| 67 | + private LocalDateTime successTime; | ||
| 68 | + | ||
| 69 | + @Schema(description = "调用渠道的错误码") | ||
| 85 | private String channelErrorCode; | 70 | private String channelErrorCode; |
| 86 | 71 | ||
| 87 | - @Schema(description = "渠道调用报错时,错误信息") | 72 | + @Schema(description = "调用渠道的错误提示") |
| 88 | private String channelErrorMsg; | 73 | private String channelErrorMsg; |
| 89 | 74 | ||
| 90 | @Schema(description = "支付渠道的额外参数") | 75 | @Schema(description = "支付渠道的额外参数") |
| 91 | - private String channelExtras; | ||
| 92 | - | ||
| 93 | - @Schema(description = "退款失效时间") | ||
| 94 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 95 | - private LocalDateTime expireTime; | ||
| 96 | - | ||
| 97 | - @Schema(description = "退款成功时间") | ||
| 98 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 99 | - private LocalDateTime successTime; | ||
| 100 | - | ||
| 101 | - @Schema(description = "退款通知时间") | ||
| 102 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 103 | - private LocalDateTime notifyTime; | 76 | + private String channelNotifyData; |
| 104 | 77 | ||
| 105 | } | 78 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundCreateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; | ||
| 2 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 3 | -import lombok.*; | ||
| 4 | - | ||
| 5 | -@Schema(description = "管理后台 - 退款订单创建 Request VO") | ||
| 6 | -@Data | ||
| 7 | -@EqualsAndHashCode(callSuper = true) | ||
| 8 | -@ToString(callSuper = true) | ||
| 9 | -public class PayRefundCreateReqVO extends PayRefundBaseVO { | ||
| 10 | - | ||
| 11 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundDetailsRespVO.java
| @@ -5,7 +5,6 @@ import lombok.Data; | @@ -5,7 +5,6 @@ import lombok.Data; | ||
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | import lombok.ToString; | 6 | import lombok.ToString; |
| 7 | 7 | ||
| 8 | -import javax.validation.constraints.NotNull; | ||
| 9 | import java.time.LocalDateTime; | 8 | import java.time.LocalDateTime; |
| 10 | 9 | ||
| 11 | @Schema(description = "管理后台 - 退款订单详情 Response VO") | 10 | @Schema(description = "管理后台 - 退款订单详情 Response VO") |
| @@ -17,14 +16,11 @@ public class PayRefundDetailsRespVO extends PayRefundBaseVO { | @@ -17,14 +16,11 @@ public class PayRefundDetailsRespVO extends PayRefundBaseVO { | ||
| 17 | @Schema(description = "支付退款编号", requiredMode = Schema.RequiredMode.REQUIRED) | 16 | @Schema(description = "支付退款编号", requiredMode = Schema.RequiredMode.REQUIRED) |
| 18 | private Long id; | 17 | private Long id; |
| 19 | 18 | ||
| 20 | - @Schema(description = "应用名称") | 19 | + @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是芋艿") |
| 21 | private String appName; | 20 | private String appName; |
| 22 | 21 | ||
| 23 | - @Schema(description = "渠道编号名称") | ||
| 24 | - private String channelCodeName; | ||
| 25 | - | ||
| 26 | - @NotNull(message = "商品标题不能为空") | ||
| 27 | - private String subject; | 22 | + @Schema(description = "支付订单", requiredMode = Schema.RequiredMode.REQUIRED) |
| 23 | + private Order order; | ||
| 28 | 24 | ||
| 29 | @Schema(description = "创建时间") | 25 | @Schema(description = "创建时间") |
| 30 | private LocalDateTime createTime; | 26 | private LocalDateTime createTime; |
| @@ -32,4 +28,13 @@ public class PayRefundDetailsRespVO extends PayRefundBaseVO { | @@ -32,4 +28,13 @@ public class PayRefundDetailsRespVO extends PayRefundBaseVO { | ||
| 32 | @Schema(description = "更新时间") | 28 | @Schema(description = "更新时间") |
| 33 | private LocalDateTime updateTime; | 29 | private LocalDateTime updateTime; |
| 34 | 30 | ||
| 31 | + @Schema(description = "管理后台 - 支付订单") | ||
| 32 | + @Data | ||
| 33 | + public static class Order { | ||
| 34 | + | ||
| 35 | + @Schema(description = "商品标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆") | ||
| 36 | + private String subject; | ||
| 37 | + | ||
| 38 | + } | ||
| 39 | + | ||
| 35 | } | 40 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | 3 | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| 4 | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | 4 | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| 5 | +import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; | ||
| 5 | import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; | 6 | import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; |
| 6 | import com.alibaba.excel.annotation.ExcelProperty; | 7 | import com.alibaba.excel.annotation.ExcelProperty; |
| 7 | import lombok.Data; | 8 | import lombok.Data; |
| @@ -19,64 +20,42 @@ public class PayRefundExcelVO { | @@ -19,64 +20,42 @@ public class PayRefundExcelVO { | ||
| 19 | @ExcelProperty("支付退款编号") | 20 | @ExcelProperty("支付退款编号") |
| 20 | private Long id; | 21 | private Long id; |
| 21 | 22 | ||
| 22 | - @ExcelProperty("商品名称") | ||
| 23 | - private String subject; | 23 | + @ExcelProperty("创建时间") |
| 24 | + private LocalDateTime createTime; | ||
| 24 | 25 | ||
| 25 | - @ExcelProperty(value = "应用名称") | ||
| 26 | - private String appName; | 26 | + @ExcelProperty(value = "支付金额", converter = MoneyConvert.class) |
| 27 | + private Integer payPrice; | ||
| 27 | 28 | ||
| 28 | - @ExcelProperty(value = "渠道编号名称") | ||
| 29 | - private String channelCodeName; | 29 | + @ExcelProperty(value = "退款金额", converter = MoneyConvert.class) |
| 30 | + private Integer refundPrice; | ||
| 30 | 31 | ||
| 31 | - @ExcelProperty("交易订单号") | ||
| 32 | - private String tradeNo; | 32 | + @ExcelProperty("商户退款单号") |
| 33 | + private String merchantRefundId; | ||
| 34 | + @ExcelProperty("退款单号") | ||
| 35 | + private String no; | ||
| 36 | + @ExcelProperty("渠道退款单号") | ||
| 37 | + private String channelRefundNo; | ||
| 33 | 38 | ||
| 34 | - @ExcelProperty("商户订单编号") | 39 | + @ExcelProperty("商户支付单号") |
| 35 | private String merchantOrderId; | 40 | private String merchantOrderId; |
| 41 | + @ExcelProperty("渠道支付单号") | ||
| 42 | + private String channelOrderNo; | ||
| 36 | 43 | ||
| 37 | - @ExcelProperty("商户退款订单号") | ||
| 38 | - private String merchantRefundNo; | ||
| 39 | - | ||
| 40 | - @ExcelProperty("异步通知商户地址") | ||
| 41 | - private String notifyUrl; | ||
| 42 | - | ||
| 43 | - @DictFormat(DictTypeConstants.ORDER_NOTIFY_STATUS) | ||
| 44 | - @ExcelProperty(value = "商户退款结果回调状态", converter = DictConvert.class) | ||
| 45 | - private Integer notifyStatus; | ||
| 46 | - | ||
| 47 | - @DictFormat(DictTypeConstants.REFUND_ORDER_STATUS) | ||
| 48 | @ExcelProperty(value = "退款状态", converter = DictConvert.class) | 44 | @ExcelProperty(value = "退款状态", converter = DictConvert.class) |
| 45 | + @DictFormat(DictTypeConstants.REFUND_STATUS) | ||
| 49 | private Integer status; | 46 | private Integer status; |
| 50 | 47 | ||
| 51 | - @DictFormat(DictTypeConstants.REFUND_ORDER_TYPE) | ||
| 52 | - @ExcelProperty(value = "退款类型", converter = DictConvert.class) | ||
| 53 | - private Integer type; | 48 | + @ExcelProperty(value = "退款渠道", converter = DictConvert.class) |
| 49 | + @DictFormat(DictTypeConstants.CHANNEL_CODE) | ||
| 50 | + private String channelCode; | ||
| 54 | 51 | ||
| 55 | - @ExcelProperty("支付金额,单位:元") | ||
| 56 | - private String payPrice; | 52 | + @ExcelProperty("成功时间") |
| 53 | + private LocalDateTime successTime; | ||
| 57 | 54 | ||
| 58 | - @ExcelProperty("退款金额,单位:元") | ||
| 59 | - private String refundPrice; | 55 | + @ExcelProperty(value = "支付应用") |
| 56 | + private String appName; | ||
| 60 | 57 | ||
| 61 | @ExcelProperty("退款原因") | 58 | @ExcelProperty("退款原因") |
| 62 | private String reason; | 59 | private String reason; |
| 63 | 60 | ||
| 64 | - @ExcelProperty("用户付款 IP") | ||
| 65 | - private String userIp; | ||
| 66 | - | ||
| 67 | - @ExcelProperty("渠道订单号") | ||
| 68 | - private String channelOrderNo; | ||
| 69 | - | ||
| 70 | - @ExcelProperty("渠道退款单号") | ||
| 71 | - private String channelRefundNo; | ||
| 72 | - | ||
| 73 | - @ExcelProperty("创建时间") | ||
| 74 | - private LocalDateTime createTime; | ||
| 75 | - | ||
| 76 | - @ExcelProperty("退款成功时间") | ||
| 77 | - private LocalDateTime successTime; | ||
| 78 | - | ||
| 79 | - @ExcelProperty("退款失效时间") | ||
| 80 | - private LocalDateTime expireTime; | ||
| 81 | - | ||
| 82 | } | 61 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExportReqVO.java
| @@ -12,77 +12,26 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -12,77 +12,26 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 12 | @Data | 12 | @Data |
| 13 | public class PayRefundExportReqVO { | 13 | public class PayRefundExportReqVO { |
| 14 | 14 | ||
| 15 | - @Schema(description = "应用编号") | 15 | + @Schema(description = "应用编号", example = "1024") |
| 16 | private Long appId; | 16 | private Long appId; |
| 17 | 17 | ||
| 18 | - @Schema(description = "渠道编号") | ||
| 19 | - private Long channelId; | ||
| 20 | - | ||
| 21 | - @Schema(description = "渠道编码") | 18 | + @Schema(description = "渠道编码", example = "wx_app") |
| 22 | private String channelCode; | 19 | private String channelCode; |
| 23 | 20 | ||
| 24 | - @Schema(description = "支付订单编号 pay_order 表id") | ||
| 25 | - private Long orderId; | ||
| 26 | - | ||
| 27 | - @Schema(description = "交易订单号 pay_extension 表no 字段") | ||
| 28 | - private String tradeNo; | ||
| 29 | - | ||
| 30 | - @Schema(description = "商户订单编号(商户系统生成)") | 21 | + @Schema(description = "商户支付单号", example = "10") |
| 31 | private String merchantOrderId; | 22 | private String merchantOrderId; |
| 32 | 23 | ||
| 33 | - @Schema(description = "商户退款订单号(商户系统生成)") | ||
| 34 | - private String merchantRefundNo; | ||
| 35 | - | ||
| 36 | - @Schema(description = "异步通知商户地址") | ||
| 37 | - private String notifyUrl; | ||
| 38 | - | ||
| 39 | - @Schema(description = "通知商户退款结果的回调状态") | ||
| 40 | - private Integer notifyStatus; | ||
| 41 | - | ||
| 42 | - @Schema(description = "退款状态") | ||
| 43 | - private Integer status; | ||
| 44 | - | ||
| 45 | - @Schema(description = "退款类型(部分退款,全部退款)") | ||
| 46 | - private Integer type; | ||
| 47 | - | ||
| 48 | - @Schema(description = "支付金额,单位分") | ||
| 49 | - private Long payPrice; | ||
| 50 | - | ||
| 51 | - @Schema(description = "退款金额,单位分") | ||
| 52 | - private Long refundPrice; | ||
| 53 | - | ||
| 54 | - @Schema(description = "退款原因") | ||
| 55 | - private String reason; | 24 | + @Schema(description = "商户退款单号", example = "20") |
| 25 | + private String merchantRefundId; | ||
| 56 | 26 | ||
| 57 | - @Schema(description = "用户 IP") | ||
| 58 | - private String userIp; | ||
| 59 | - | ||
| 60 | - @Schema(description = "渠道订单号,pay_order 中的channel_order_no 对应") | 27 | + @Schema(description = "渠道支付单号", example = "30") |
| 61 | private String channelOrderNo; | 28 | private String channelOrderNo; |
| 62 | 29 | ||
| 63 | - @Schema(description = "渠道退款单号,渠道返回") | 30 | + @Schema(description = "渠道退款单号", example = "40") |
| 64 | private String channelRefundNo; | 31 | private String channelRefundNo; |
| 65 | 32 | ||
| 66 | - @Schema(description = "渠道调用报错时,错误码") | ||
| 67 | - private String channelErrorCode; | ||
| 68 | - | ||
| 69 | - @Schema(description = "渠道调用报错时,错误信息") | ||
| 70 | - private String channelErrorMsg; | ||
| 71 | - | ||
| 72 | - @Schema(description = "支付渠道的额外参数") | ||
| 73 | - private String channelExtras; | ||
| 74 | - | ||
| 75 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 76 | - @Schema(description = "退款失效时间") | ||
| 77 | - private LocalDateTime[] expireTime; | ||
| 78 | - | ||
| 79 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 80 | - @Schema(description = "退款成功时间") | ||
| 81 | - private LocalDateTime[] successTime; | ||
| 82 | - | ||
| 83 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 84 | - @Schema(description = "退款通知时间") | ||
| 85 | - private LocalDateTime[] notifyTime; | 33 | + @Schema(description = "退款状态", example = "0") |
| 34 | + private Integer status; | ||
| 86 | 35 | ||
| 87 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 36 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 88 | @Schema(description = "创建时间") | 37 | @Schema(description = "创建时间") |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageItemRespVO.java
| @@ -13,15 +13,12 @@ import java.time.LocalDateTime; | @@ -13,15 +13,12 @@ import java.time.LocalDateTime; | ||
| 13 | @ToString(callSuper = true) | 13 | @ToString(callSuper = true) |
| 14 | public class PayRefundPageItemRespVO extends PayRefundBaseVO { | 14 | public class PayRefundPageItemRespVO extends PayRefundBaseVO { |
| 15 | 15 | ||
| 16 | - @Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED) | 16 | + @Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 17 | private Long id; | 17 | private Long id; |
| 18 | 18 | ||
| 19 | - @Schema(description = "应用名称") | 19 | + @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是芋艿") |
| 20 | private String appName; | 20 | private String appName; |
| 21 | 21 | ||
| 22 | - @Schema(description = "渠道名称") | ||
| 23 | - private String channelCodeName; | ||
| 24 | - | ||
| 25 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | 22 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 26 | private LocalDateTime createTime; | 23 | private LocalDateTime createTime; |
| 27 | 24 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageReqVO.java
| @@ -17,77 +17,26 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -17,77 +17,26 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 17 | @ToString(callSuper = true) | 17 | @ToString(callSuper = true) |
| 18 | public class PayRefundPageReqVO extends PageParam { | 18 | public class PayRefundPageReqVO extends PageParam { |
| 19 | 19 | ||
| 20 | - @Schema(description = "应用编号") | 20 | + @Schema(description = "应用编号", example = "1024") |
| 21 | private Long appId; | 21 | private Long appId; |
| 22 | 22 | ||
| 23 | - @Schema(description = "渠道编号") | ||
| 24 | - private Long channelId; | ||
| 25 | - | ||
| 26 | - @Schema(description = "渠道编码") | 23 | + @Schema(description = "渠道编码", example = "wx_app") |
| 27 | private String channelCode; | 24 | private String channelCode; |
| 28 | 25 | ||
| 29 | - @Schema(description = "支付订单编号 pay_order 表id") | ||
| 30 | - private Long orderId; | ||
| 31 | - | ||
| 32 | - @Schema(description = "交易订单号 pay_extension 表no 字段") | ||
| 33 | - private String tradeNo; | ||
| 34 | - | ||
| 35 | - @Schema(description = "商户订单编号(商户系统生成)") | 26 | + @Schema(description = "商户支付单号", example = "10") |
| 36 | private String merchantOrderId; | 27 | private String merchantOrderId; |
| 37 | 28 | ||
| 38 | - @Schema(description = "商户退款订单号(商户系统生成)") | ||
| 39 | - private String merchantRefundNo; | ||
| 40 | - | ||
| 41 | - @Schema(description = "异步通知商户地址") | ||
| 42 | - private String notifyUrl; | ||
| 43 | - | ||
| 44 | - @Schema(description = "通知商户退款结果的回调状态") | ||
| 45 | - private Integer notifyStatus; | ||
| 46 | - | ||
| 47 | - @Schema(description = "退款状态") | ||
| 48 | - private Integer status; | ||
| 49 | - | ||
| 50 | - @Schema(description = "退款类型(部分退款,全部退款)") | ||
| 51 | - private Integer type; | ||
| 52 | - | ||
| 53 | - @Schema(description = "支付金额,单位分") | ||
| 54 | - private Long payPrice; | ||
| 55 | - | ||
| 56 | - @Schema(description = "退款金额,单位分") | ||
| 57 | - private Long refundPrice; | ||
| 58 | - | ||
| 59 | - @Schema(description = "退款原因") | ||
| 60 | - private String reason; | 29 | + @Schema(description = "商户退款单号", example = "20") |
| 30 | + private String merchantRefundId; | ||
| 61 | 31 | ||
| 62 | - @Schema(description = "用户 IP") | ||
| 63 | - private String userIp; | ||
| 64 | - | ||
| 65 | - @Schema(description = "渠道订单号,pay_order 中的channel_order_no 对应") | 32 | + @Schema(description = "渠道支付单号", example = "30") |
| 66 | private String channelOrderNo; | 33 | private String channelOrderNo; |
| 67 | 34 | ||
| 68 | - @Schema(description = "渠道退款单号,渠道返回") | 35 | + @Schema(description = "渠道退款单号", example = "40") |
| 69 | private String channelRefundNo; | 36 | private String channelRefundNo; |
| 70 | 37 | ||
| 71 | - @Schema(description = "渠道调用报错时,错误码") | ||
| 72 | - private String channelErrorCode; | ||
| 73 | - | ||
| 74 | - @Schema(description = "渠道调用报错时,错误信息") | ||
| 75 | - private String channelErrorMsg; | ||
| 76 | - | ||
| 77 | - @Schema(description = "支付渠道的额外参数") | ||
| 78 | - private String channelExtras; | ||
| 79 | - | ||
| 80 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 81 | - @Schema(description = "退款失效时间") | ||
| 82 | - private LocalDateTime[] expireTime; | ||
| 83 | - | ||
| 84 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 85 | - @Schema(description = "退款成功时间") | ||
| 86 | - private LocalDateTime[] successTime; | ||
| 87 | - | ||
| 88 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 89 | - @Schema(description = "退款通知时间") | ||
| 90 | - private LocalDateTime[] notifyTime; | 38 | + @Schema(description = "退款状态", example = "0") |
| 39 | + private Integer status; | ||
| 91 | 40 | ||
| 92 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 41 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 93 | @Schema(description = "创建时间") | 42 | @Schema(description = "创建时间") |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundUpdateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; | ||
| 2 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 3 | -import lombok.*; | ||
| 4 | -import javax.validation.constraints.*; | ||
| 5 | - | ||
| 6 | -@Schema(description = "管理后台 - 退款订单更新 Request VO") | ||
| 7 | -@Data | ||
| 8 | -@EqualsAndHashCode(callSuper = true) | ||
| 9 | -@ToString(callSuper = true) | ||
| 10 | -public class PayRefundUpdateReqVO extends PayRefundBaseVO { | ||
| 11 | - | ||
| 12 | - @Schema(description = "支付退款编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 13 | - @NotNull(message = "支付退款编号不能为空") | ||
| 14 | - private Long id; | ||
| 15 | - | ||
| 16 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/notify/PayNotifyTaskConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.convert.notify; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | ||
| 8 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | ||
| 9 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | ||
| 10 | +import org.mapstruct.Mapper; | ||
| 11 | +import org.mapstruct.factory.Mappers; | ||
| 12 | + | ||
| 13 | +import java.util.List; | ||
| 14 | +import java.util.Map; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 支付通知 Convert | ||
| 18 | + * | ||
| 19 | + * @author 芋道源码 | ||
| 20 | + */ | ||
| 21 | +@Mapper | ||
| 22 | +public interface PayNotifyTaskConvert { | ||
| 23 | + | ||
| 24 | + PayNotifyTaskConvert INSTANCE = Mappers.getMapper(PayNotifyTaskConvert.class); | ||
| 25 | + | ||
| 26 | + PayNotifyTaskRespVO convert(PayNotifyTaskDO bean); | ||
| 27 | + | ||
| 28 | + default PageResult<PayNotifyTaskRespVO> convertPage(PageResult<PayNotifyTaskDO> page, Map<Long, PayAppDO> appMap){ | ||
| 29 | + PageResult<PayNotifyTaskRespVO> result = convertPage(page); | ||
| 30 | + result.getList().forEach(order -> MapUtils.findAndThen(appMap, order.getAppId(), app -> order.setAppName(app.getName()))); | ||
| 31 | + return result; | ||
| 32 | + } | ||
| 33 | + PageResult<PayNotifyTaskRespVO> convertPage(PageResult<PayNotifyTaskDO> page); | ||
| 34 | + | ||
| 35 | + default PayNotifyTaskDetailRespVO convert(PayNotifyTaskDO task, PayAppDO app, List<PayNotifyLogDO> logs) { | ||
| 36 | + PayNotifyTaskDetailRespVO respVO = convert(task, logs); | ||
| 37 | + if (app != null) { | ||
| 38 | + respVO.setAppName(app.getName()); | ||
| 39 | + } | ||
| 40 | + return respVO; | ||
| 41 | + } | ||
| 42 | + PayNotifyTaskDetailRespVO convert(PayNotifyTaskDO task, List<PayNotifyLogDO> logs); | ||
| 43 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java
| 1 | package cn.iocoder.yudao.module.pay.convert.order; | 1 | package cn.iocoder.yudao.module.pay.convert.order; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 5 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | 7 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 6 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; | 8 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; |
| 7 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; | 9 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; |
| 8 | import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; | 10 | import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; |
| 11 | +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | ||
| 9 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 12 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | 13 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; |
| 11 | import org.mapstruct.Mapper; | 14 | import org.mapstruct.Mapper; |
| 12 | import org.mapstruct.Mapping; | 15 | import org.mapstruct.Mapping; |
| 13 | import org.mapstruct.factory.Mappers; | 16 | import org.mapstruct.factory.Mappers; |
| 14 | 17 | ||
| 15 | -import java.math.BigDecimal; | ||
| 16 | -import java.math.RoundingMode; | ||
| 17 | import java.util.List; | 18 | import java.util.List; |
| 19 | +import java.util.Map; | ||
| 18 | 20 | ||
| 19 | /** | 21 | /** |
| 20 | * 支付订单 Convert | 22 | * 支付订单 Convert |
| @@ -30,60 +32,32 @@ public interface PayOrderConvert { | @@ -30,60 +32,32 @@ public interface PayOrderConvert { | ||
| 30 | 32 | ||
| 31 | PayOrderRespDTO convert2(PayOrderDO order); | 33 | PayOrderRespDTO convert2(PayOrderDO order); |
| 32 | 34 | ||
| 33 | - PayOrderDetailsRespVO orderDetailConvert(PayOrderDO bean); | ||
| 34 | - | ||
| 35 | - PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean); | ||
| 36 | - | ||
| 37 | - List<PayOrderRespVO> convertList(List<PayOrderDO> list); | ||
| 38 | - | ||
| 39 | - PageResult<PayOrderRespVO> convertPage(PageResult<PayOrderDO> page); | ||
| 40 | - | ||
| 41 | - /** | ||
| 42 | - * 订单 DO 转自定义分页对象 | ||
| 43 | - * | ||
| 44 | - * @param bean 订单DO | ||
| 45 | - * @return 分页对象 | ||
| 46 | - */ | ||
| 47 | - PayOrderPageItemRespVO pageConvertItemPage(PayOrderDO bean); | ||
| 48 | - | ||
| 49 | - // TODO 芋艿:优化下 convert 逻辑 | ||
| 50 | - default PayOrderExcelVO excelConvert(PayOrderDO bean) { | ||
| 51 | - if (bean == null) { | ||
| 52 | - return null; | 35 | + default PayOrderDetailsRespVO convert(PayOrderDO order, PayOrderExtensionDO orderExtension, PayAppDO app) { |
| 36 | + PayOrderDetailsRespVO respVO = convertDetail(order); | ||
| 37 | + respVO.setExtension(convert(orderExtension)); | ||
| 38 | + if (app != null) { | ||
| 39 | + respVO.setAppName(app.getName()); | ||
| 53 | } | 40 | } |
| 41 | + return respVO; | ||
| 42 | + } | ||
| 43 | + PayOrderDetailsRespVO convertDetail(PayOrderDO bean); | ||
| 44 | + PayOrderDetailsRespVO.PayOrderExtension convert(PayOrderExtensionDO bean); | ||
| 54 | 45 | ||
| 55 | - PayOrderExcelVO payOrderExcelVO = new PayOrderExcelVO(); | ||
| 56 | - | ||
| 57 | - payOrderExcelVO.setId(bean.getId()); | ||
| 58 | - payOrderExcelVO.setSubject(bean.getSubject()); | ||
| 59 | - payOrderExcelVO.setMerchantOrderId(bean.getMerchantOrderId()); | ||
| 60 | - payOrderExcelVO.setChannelOrderNo(bean.getChannelOrderNo()); | ||
| 61 | - payOrderExcelVO.setStatus(bean.getStatus()); | ||
| 62 | - payOrderExcelVO.setNotifyStatus(bean.getNotifyStatus()); | ||
| 63 | - payOrderExcelVO.setNotifyUrl(bean.getNotifyUrl()); | ||
| 64 | - payOrderExcelVO.setCreateTime(bean.getCreateTime()); | ||
| 65 | - payOrderExcelVO.setSuccessTime(bean.getSuccessTime()); | ||
| 66 | - payOrderExcelVO.setExpireTime(bean.getExpireTime()); | ||
| 67 | - payOrderExcelVO.setNotifyTime(bean.getNotifyTime()); | ||
| 68 | - payOrderExcelVO.setUserIp(bean.getUserIp()); | ||
| 69 | - payOrderExcelVO.setRefundStatus(bean.getRefundStatus()); | ||
| 70 | - payOrderExcelVO.setRefundTimes(bean.getRefundTimes()); | ||
| 71 | - payOrderExcelVO.setBody(bean.getBody()); | ||
| 72 | - | ||
| 73 | - BigDecimal multiple = new BigDecimal(100); | ||
| 74 | - | ||
| 75 | - payOrderExcelVO.setPrice(BigDecimal.valueOf(bean.getPrice()) | ||
| 76 | - .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | ||
| 77 | - | ||
| 78 | - payOrderExcelVO.setChannelFeePrice(BigDecimal.valueOf(bean.getChannelFeePrice()) | ||
| 79 | - .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | ||
| 80 | - payOrderExcelVO.setChannelFeeRate(java.math.BigDecimal.valueOf(bean.getChannelFeeRate()) | ||
| 81 | - .multiply(multiple).toString()); | ||
| 82 | - payOrderExcelVO.setRefundPrice(BigDecimal.valueOf(bean.getRefundPrice()) | ||
| 83 | - .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | ||
| 84 | - | ||
| 85 | - return payOrderExcelVO; | 46 | + default PageResult<PayOrderPageItemRespVO> convertPage(PageResult<PayOrderDO> page, Map<Long, PayAppDO> appMap) { |
| 47 | + PageResult<PayOrderPageItemRespVO> result = convertPage(page); | ||
| 48 | + result.getList().forEach(order -> MapUtils.findAndThen(appMap, order.getAppId(), app -> order.setAppName(app.getName()))); | ||
| 49 | + return result; | ||
| 50 | + } | ||
| 51 | + PageResult<PayOrderPageItemRespVO> convertPage(PageResult<PayOrderDO> page); | ||
| 52 | + | ||
| 53 | + default List<PayOrderExcelVO> convertList(List<PayOrderDO> list, Map<Long, PayAppDO> appMap) { | ||
| 54 | + return CollectionUtils.convertList(list, order -> { | ||
| 55 | + PayOrderExcelVO excelVO = convertExcel(order); | ||
| 56 | + MapUtils.findAndThen(appMap, order.getAppId(), app -> excelVO.setAppName(app.getName())); | ||
| 57 | + return excelVO; | ||
| 58 | + }); | ||
| 86 | } | 59 | } |
| 60 | + PayOrderExcelVO convertExcel(PayOrderDO bean); | ||
| 87 | 61 | ||
| 88 | PayOrderDO convert(PayOrderCreateReqDTO bean); | 62 | PayOrderDO convert(PayOrderCreateReqDTO bean); |
| 89 | 63 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java
| 1 | package cn.iocoder.yudao.module.pay.convert.refund; | 1 | package cn.iocoder.yudao.module.pay.convert.refund; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 4 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | 6 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 5 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; | 7 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; |
| 6 | -import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*; | 8 | +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundDetailsRespVO; |
| 9 | +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExcelVO; | ||
| 10 | +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageItemRespVO; | ||
| 11 | +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | ||
| 12 | +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | ||
| 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 13 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 8 | import org.mapstruct.Mapper; | 14 | import org.mapstruct.Mapper; |
| 9 | import org.mapstruct.factory.Mappers; | 15 | import org.mapstruct.factory.Mappers; |
| 10 | 16 | ||
| 11 | -import java.math.BigDecimal; | ||
| 12 | -import java.math.RoundingMode; | ||
| 13 | import java.util.List; | 17 | import java.util.List; |
| 18 | +import java.util.Map; | ||
| 14 | 19 | ||
| 15 | @Mapper | 20 | @Mapper |
| 16 | public interface PayRefundConvert { | 21 | public interface PayRefundConvert { |
| 17 | 22 | ||
| 18 | PayRefundConvert INSTANCE = Mappers.getMapper(PayRefundConvert.class); | 23 | PayRefundConvert INSTANCE = Mappers.getMapper(PayRefundConvert.class); |
| 19 | 24 | ||
| 20 | - PayRefundDO convert(PayRefundCreateReqVO bean); | ||
| 21 | 25 | ||
| 22 | - PayRefundDO convert(PayRefundUpdateReqVO bean); | ||
| 23 | - | ||
| 24 | - PayRefundRespVO convert(PayRefundDO bean); | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * 退款订单 DO 转 退款详情订单 VO | ||
| 28 | - * | ||
| 29 | - * @param bean 退款订单 DO | ||
| 30 | - * @return 退款详情订单 VO | ||
| 31 | - */ | ||
| 32 | - PayRefundDetailsRespVO refundDetailConvert(PayRefundDO bean); | ||
| 33 | - | ||
| 34 | - /** | ||
| 35 | - * 退款订单DO 转 分页退款条目VO | ||
| 36 | - * | ||
| 37 | - * @param bean 退款订单DO | ||
| 38 | - * @return 分页退款条目VO | ||
| 39 | - */ | ||
| 40 | - PayRefundPageItemRespVO pageItemConvert(PayRefundDO bean); | ||
| 41 | - | ||
| 42 | - List<PayRefundRespVO> convertList(List<PayRefundDO> list); | ||
| 43 | - | ||
| 44 | - PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page); | ||
| 45 | - | ||
| 46 | - /** | ||
| 47 | - * 退款订单DO 转 导出excel VO | ||
| 48 | - * | ||
| 49 | - * @param bean 退款订单DO | ||
| 50 | - * @return 导出 excel VO | ||
| 51 | - */ | ||
| 52 | - default PayRefundExcelVO excelConvert(PayRefundDO bean) { | ||
| 53 | - if (bean == null) { | ||
| 54 | - return null; | 26 | + default PayRefundDetailsRespVO convert(PayRefundDO refund, PayAppDO app) { |
| 27 | + PayRefundDetailsRespVO respVO = convert(refund); | ||
| 28 | + if (app != null) { | ||
| 29 | + respVO.setAppName(app.getName()); | ||
| 55 | } | 30 | } |
| 31 | + return respVO; | ||
| 32 | + } | ||
| 33 | + PayRefundDetailsRespVO convert(PayRefundDO bean); | ||
| 34 | + PayRefundDetailsRespVO.Order convert(PayOrderDO bean); | ||
| 56 | 35 | ||
| 57 | - PayRefundExcelVO payRefundExcelVO = new PayRefundExcelVO(); | ||
| 58 | - | ||
| 59 | - payRefundExcelVO.setId(bean.getId()); | ||
| 60 | - payRefundExcelVO.setTradeNo(bean.getNo()); | ||
| 61 | - payRefundExcelVO.setMerchantOrderId(bean.getMerchantOrderId()); | ||
| 62 | - // TODO 芋艿:晚点在改 | ||
| 63 | -// payRefundExcelVO.setMerchantRefundNo(bean.getMerchantRefundNo()); | ||
| 64 | - payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl()); | ||
| 65 | - payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus()); | ||
| 66 | - payRefundExcelVO.setStatus(bean.getStatus()); | ||
| 67 | - payRefundExcelVO.setReason(bean.getReason()); | ||
| 68 | - payRefundExcelVO.setUserIp(bean.getUserIp()); | ||
| 69 | - payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo()); | ||
| 70 | - payRefundExcelVO.setChannelRefundNo(bean.getChannelRefundNo()); | ||
| 71 | - payRefundExcelVO.setSuccessTime(bean.getSuccessTime()); | ||
| 72 | - payRefundExcelVO.setCreateTime(bean.getCreateTime()); | ||
| 73 | - | ||
| 74 | - BigDecimal multiple = new BigDecimal(100); | ||
| 75 | - payRefundExcelVO.setPayPrice(BigDecimal.valueOf(bean.getPayPrice()) | ||
| 76 | - .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | ||
| 77 | - payRefundExcelVO.setRefundPrice(BigDecimal.valueOf(bean.getRefundPrice()) | ||
| 78 | - .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | ||
| 79 | - | ||
| 80 | - return payRefundExcelVO; | 36 | + default PageResult<PayRefundPageItemRespVO> convertPage(PageResult<PayRefundDO> page, Map<Long, PayAppDO> appMap) { |
| 37 | + PageResult<PayRefundPageItemRespVO> result = convertPage(page); | ||
| 38 | + result.getList().forEach(order -> MapUtils.findAndThen(appMap, order.getAppId(), app -> order.setAppName(app.getName()))); | ||
| 39 | + return result; | ||
| 81 | } | 40 | } |
| 41 | + PageResult<PayRefundPageItemRespVO> convertPage(PageResult<PayRefundDO> page); | ||
| 82 | 42 | ||
| 83 | PayRefundDO convert(PayRefundCreateReqDTO bean); | 43 | PayRefundDO convert(PayRefundCreateReqDTO bean); |
| 84 | 44 | ||
| 85 | PayRefundRespDTO convert02(PayRefundDO bean); | 45 | PayRefundRespDTO convert02(PayRefundDO bean); |
| 86 | 46 | ||
| 47 | + default List<PayRefundExcelVO> convertList(List<PayRefundDO> list, Map<Long, PayAppDO> appMap) { | ||
| 48 | + return CollectionUtils.convertList(list, order -> { | ||
| 49 | + PayRefundExcelVO excelVO = convertExcel(order); | ||
| 50 | + MapUtils.findAndThen(appMap, order.getAppId(), app -> excelVO.setAppName(app.getName())); | ||
| 51 | + return excelVO; | ||
| 52 | + }); | ||
| 53 | + } | ||
| 54 | + PayRefundExcelVO convertExcel(PayRefundDO bean); | ||
| 55 | + | ||
| 87 | } | 56 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java
| @@ -15,7 +15,7 @@ import lombok.experimental.Accessors; | @@ -15,7 +15,7 @@ import lombok.experimental.Accessors; | ||
| 15 | import java.time.LocalDateTime; | 15 | import java.time.LocalDateTime; |
| 16 | 16 | ||
| 17 | /** | 17 | /** |
| 18 | - * 商户支付、退款等的通知 | 18 | + * 支付通知 |
| 19 | * 在支付系统收到支付渠道的支付、退款的结果后,需要不断的通知到业务系统,直到成功。 | 19 | * 在支付系统收到支付渠道的支付、退款的结果后,需要不断的通知到业务系统,直到成功。 |
| 20 | * | 20 | * |
| 21 | * @author 芋道源码 | 21 | * @author 芋道源码 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java
| @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 4 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; |
| 7 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; | ||
| 8 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 7 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 9 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum; | ||
| 10 | import com.baomidou.mybatisplus.annotation.KeySequence; | 8 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 11 | import com.baomidou.mybatisplus.annotation.TableName; | 9 | import com.baomidou.mybatisplus.annotation.TableName; |
| 12 | import lombok.*; | 10 | import lombok.*; |
| @@ -71,12 +69,6 @@ public class PayOrderDO extends BaseDO { | @@ -71,12 +69,6 @@ public class PayOrderDO extends BaseDO { | ||
| 71 | * 异步通知地址 | 69 | * 异步通知地址 |
| 72 | */ | 70 | */ |
| 73 | private String notifyUrl; | 71 | private String notifyUrl; |
| 74 | - /** | ||
| 75 | - * 通知商户支付结果的回调状态 | ||
| 76 | - * | ||
| 77 | - * 枚举 {@link PayOrderNotifyStatusEnum} | ||
| 78 | - */ | ||
| 79 | - private Integer notifyStatus; | ||
| 80 | 72 | ||
| 81 | // ========== 订单相关字段 ========== | 73 | // ========== 订单相关字段 ========== |
| 82 | 74 | ||
| @@ -93,7 +85,7 @@ public class PayOrderDO extends BaseDO { | @@ -93,7 +85,7 @@ public class PayOrderDO extends BaseDO { | ||
| 93 | /** | 85 | /** |
| 94 | * 渠道手续金额,单位:分 | 86 | * 渠道手续金额,单位:分 |
| 95 | */ | 87 | */ |
| 96 | - private Long channelFeePrice; | 88 | + private Integer channelFeePrice; |
| 97 | /** | 89 | /** |
| 98 | * 支付状态 | 90 | * 支付状态 |
| 99 | * | 91 | * |
| @@ -113,27 +105,19 @@ public class PayOrderDO extends BaseDO { | @@ -113,27 +105,19 @@ public class PayOrderDO extends BaseDO { | ||
| 113 | */ | 105 | */ |
| 114 | private LocalDateTime successTime; | 106 | private LocalDateTime successTime; |
| 115 | /** | 107 | /** |
| 116 | - * 订单支付通知时间,即支付渠道的通知时间 | ||
| 117 | - */ | ||
| 118 | - private LocalDateTime notifyTime; | ||
| 119 | - /** | ||
| 120 | * 支付成功的订单拓展单编号 | 108 | * 支付成功的订单拓展单编号 |
| 121 | * | 109 | * |
| 122 | - * 关联 {@link PayOrderDO#getId()} | 110 | + * 关联 {@link PayOrderExtensionDO#getId()} |
| 123 | */ | 111 | */ |
| 124 | - private Long successExtensionId; | ||
| 125 | - | ||
| 126 | - // ========== 退款相关字段 ========== | 112 | + private Long extensionId; |
| 127 | /** | 113 | /** |
| 128 | - * 退款状态 | 114 | + * 支付成功的外部订单号 |
| 129 | * | 115 | * |
| 130 | - * 枚举 {@link PayOrderRefundStatusEnum} | ||
| 131 | - */ | ||
| 132 | - private Integer refundStatus; | ||
| 133 | - /** | ||
| 134 | - * 退款次数 | 116 | + * 关联 {@link PayOrderExtensionDO#getNo()} |
| 135 | */ | 117 | */ |
| 136 | - private Integer refundTimes; | 118 | + private String no; |
| 119 | + | ||
| 120 | + // ========== 退款相关字段 ========== | ||
| 137 | /** | 121 | /** |
| 138 | * 退款总金额,单位:分 | 122 | * 退款总金额,单位:分 |
| 139 | */ | 123 | */ |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java
| @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | ||
| 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; |
| 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 9 | -import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; | ||
| 10 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | 9 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; |
| 11 | import com.baomidou.mybatisplus.annotation.KeySequence; | 10 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 12 | import com.baomidou.mybatisplus.annotation.TableId; | 11 | import com.baomidou.mybatisplus.annotation.TableId; |
| @@ -89,12 +88,6 @@ public class PayRefundDO extends BaseDO { | @@ -89,12 +88,6 @@ public class PayRefundDO extends BaseDO { | ||
| 89 | * 异步通知地址 | 88 | * 异步通知地址 |
| 90 | */ | 89 | */ |
| 91 | private String notifyUrl; | 90 | private String notifyUrl; |
| 92 | - /** | ||
| 93 | - * 通知商户退款结果的回调状态 | ||
| 94 | - * | ||
| 95 | - * 枚举 {@link PayNotifyStatusEnum} | ||
| 96 | - */ | ||
| 97 | - private Integer notifyStatus; | ||
| 98 | 91 | ||
| 99 | // ========== 退款相关字段 ========== | 92 | // ========== 退款相关字段 ========== |
| 100 | /** | 93 | /** |
| @@ -147,7 +140,7 @@ public class PayRefundDO extends BaseDO { | @@ -147,7 +140,7 @@ public class PayRefundDO extends BaseDO { | ||
| 147 | */ | 140 | */ |
| 148 | private String channelErrorCode; | 141 | private String channelErrorCode; |
| 149 | /** | 142 | /** |
| 150 | - * 调用渠道报错时,错误信息 | 143 | + * 调用渠道的错误提示 |
| 151 | */ | 144 | */ |
| 152 | private String channelErrorMsg; | 145 | private String channelErrorMsg; |
| 153 | 146 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogMapper.java
| @@ -4,6 +4,13 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | @@ -4,6 +4,13 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | ||
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 5 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 6 | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 7 | @Mapper | 9 | @Mapper |
| 8 | public interface PayNotifyLogMapper extends BaseMapperX<PayNotifyLogDO> { | 10 | public interface PayNotifyLogMapper extends BaseMapperX<PayNotifyLogDO> { |
| 11 | + | ||
| 12 | + default List<PayNotifyLogDO> selectListByTaskId(Long taskId) { | ||
| 13 | + return selectList(PayNotifyLogDO::getTaskId, taskId); | ||
| 14 | + } | ||
| 15 | + | ||
| 9 | } | 16 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java
| 1 | package cn.iocoder.yudao.module.pay.dal.mysql.notify; | 1 | package cn.iocoder.yudao.module.pay.dal.mysql.notify; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; | ||
| 3 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; |
| 4 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; | 8 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; |
| 5 | -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 6 | -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 9 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 7 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 8 | 11 | ||
| 9 | import java.time.LocalDateTime; | 12 | import java.time.LocalDateTime; |
| @@ -21,10 +24,21 @@ public interface PayNotifyTaskMapper extends BaseMapperX<PayNotifyTaskDO> { | @@ -21,10 +24,21 @@ public interface PayNotifyTaskMapper extends BaseMapperX<PayNotifyTaskDO> { | ||
| 21 | * @return PayTransactionNotifyTaskDO 数组 | 24 | * @return PayTransactionNotifyTaskDO 数组 |
| 22 | */ | 25 | */ |
| 23 | default List<PayNotifyTaskDO> selectListByNotify() { | 26 | default List<PayNotifyTaskDO> selectListByNotify() { |
| 24 | - return selectList(new QueryWrapper<PayNotifyTaskDO>() | ||
| 25 | - .in("status", PayNotifyStatusEnum.WAITING.getStatus(), PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus(), | ||
| 26 | - PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()) | ||
| 27 | - .le("next_notify_time", LocalDateTime.now())); | 27 | + return selectList(new LambdaQueryWrapper<PayNotifyTaskDO>() |
| 28 | + .in(PayNotifyTaskDO::getStatus, PayNotifyStatusEnum.WAITING.getStatus(), | ||
| 29 | + PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus(), PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()) | ||
| 30 | + .le(PayNotifyTaskDO::getNextNotifyTime, LocalDateTime.now())); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + default PageResult<PayNotifyTaskDO> selectPage(PayNotifyTaskPageReqVO reqVO) { | ||
| 34 | + return selectPage(reqVO, new LambdaQueryWrapperX<PayNotifyTaskDO>() | ||
| 35 | + .eqIfPresent(PayNotifyTaskDO::getAppId, reqVO.getAppId()) | ||
| 36 | + .eqIfPresent(PayNotifyTaskDO::getType, reqVO.getType()) | ||
| 37 | + .eqIfPresent(PayNotifyTaskDO::getDataId, reqVO.getDataId()) | ||
| 38 | + .eqIfPresent(PayNotifyTaskDO::getStatus, reqVO.getStatus()) | ||
| 39 | + .eqIfPresent(PayNotifyTaskDO::getMerchantOrderId, reqVO.getMerchantOrderId()) | ||
| 40 | + .betweenIfPresent(PayNotifyTaskDO::getCreateTime, reqVO.getCreateTime()) | ||
| 41 | + .orderByDesc(PayNotifyTaskDO::getId)); | ||
| 28 | } | 42 | } |
| 29 | 43 | ||
| 30 | } | 44 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java
| 1 | package cn.iocoder.yudao.module.pay.dal.mysql.order; | 1 | package cn.iocoder.yudao.module.pay.dal.mysql.order; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; | ||
| 4 | -import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 7 | -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; | ||
| 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 9 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 10 | -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 11 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 12 | 11 | ||
| 13 | -import java.util.Collection; | ||
| 14 | import java.util.List; | 12 | import java.util.List; |
| 15 | 13 | ||
| 16 | @Mapper | 14 | @Mapper |
| 17 | public interface PayOrderMapper extends BaseMapperX<PayOrderDO> { | 15 | public interface PayOrderMapper extends BaseMapperX<PayOrderDO> { |
| 18 | 16 | ||
| 19 | default PageResult<PayOrderDO> selectPage(PayOrderPageReqVO reqVO) { | 17 | default PageResult<PayOrderDO> selectPage(PayOrderPageReqVO reqVO) { |
| 20 | - return selectPage(reqVO, new QueryWrapperX<PayOrderDO>() | ||
| 21 | - .eqIfPresent("app_id", reqVO.getAppId()) | ||
| 22 | - .eqIfPresent("channel_id", reqVO.getChannelId()) | ||
| 23 | - .eqIfPresent("channel_code", reqVO.getChannelCode()) | ||
| 24 | - .likeIfPresent("merchant_order_id", reqVO.getMerchantOrderId()) | ||
| 25 | - .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | ||
| 26 | - .eqIfPresent("status", reqVO.getStatus()) | ||
| 27 | - .eqIfPresent("refund_status", reqVO.getRefundStatus()) | ||
| 28 | - .likeIfPresent("channel_order_no", reqVO.getChannelOrderNo()) | ||
| 29 | - .betweenIfPresent("create_time", reqVO.getCreateTime()) | ||
| 30 | - .orderByDesc("id")); | 18 | + return selectPage(reqVO, new LambdaQueryWrapperX<PayOrderDO>() |
| 19 | + .eqIfPresent(PayOrderDO::getAppId, reqVO.getAppId()) | ||
| 20 | + .eqIfPresent(PayOrderDO::getChannelCode, reqVO.getChannelCode()) | ||
| 21 | + .likeIfPresent(PayOrderDO::getMerchantOrderId, reqVO.getMerchantOrderId()) | ||
| 22 | + .likeIfPresent(PayOrderDO::getChannelOrderNo, reqVO.getChannelOrderNo()) | ||
| 23 | + .likeIfPresent(PayOrderDO::getNo, reqVO.getNo()) | ||
| 24 | + .eqIfPresent(PayOrderDO::getStatus, reqVO.getStatus()) | ||
| 25 | + .betweenIfPresent(PayOrderDO::getCreateTime, reqVO.getCreateTime()) | ||
| 26 | + .orderByDesc(PayOrderDO::getId)); | ||
| 31 | } | 27 | } |
| 32 | 28 | ||
| 33 | default List<PayOrderDO> selectList(PayOrderExportReqVO reqVO) { | 29 | default List<PayOrderDO> selectList(PayOrderExportReqVO reqVO) { |
| 34 | - return selectList(new QueryWrapperX<PayOrderDO>() | ||
| 35 | - .eqIfPresent("app_id", reqVO.getAppId()) | ||
| 36 | - .eqIfPresent("channel_id", reqVO.getChannelId()) | ||
| 37 | - .eqIfPresent("channel_code", reqVO.getChannelCode()) | ||
| 38 | - .likeIfPresent("merchant_order_id", reqVO.getMerchantOrderId()) | ||
| 39 | - .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | ||
| 40 | - .eqIfPresent("status", reqVO.getStatus()) | ||
| 41 | - .eqIfPresent("refund_status", reqVO.getRefundStatus()) | ||
| 42 | - .likeIfPresent("channel_order_no", reqVO.getChannelOrderNo()) | ||
| 43 | - .betweenIfPresent("create_time", reqVO.getCreateTime()) | ||
| 44 | - .orderByDesc("id")); | ||
| 45 | - } | ||
| 46 | - | ||
| 47 | - default List<PayOrderDO> findByIdListQueryOrderSubject(Collection<Long> idList) { | ||
| 48 | - return selectList(new LambdaQueryWrapper<PayOrderDO>() | ||
| 49 | - .select(PayOrderDO::getId, PayOrderDO::getSubject) | ||
| 50 | - .in(PayOrderDO::getId, idList)); | 30 | + return selectList(new LambdaQueryWrapperX<PayOrderDO>() |
| 31 | + .eqIfPresent(PayOrderDO::getAppId, reqVO.getAppId()) | ||
| 32 | + .eqIfPresent(PayOrderDO::getChannelCode, reqVO.getChannelCode()) | ||
| 33 | + .likeIfPresent(PayOrderDO::getMerchantOrderId, reqVO.getMerchantOrderId()) | ||
| 34 | + .likeIfPresent(PayOrderDO::getChannelOrderNo, reqVO.getChannelOrderNo()) | ||
| 35 | + .likeIfPresent(PayOrderDO::getNo, reqVO.getNo()) | ||
| 36 | + .eqIfPresent(PayOrderDO::getStatus, reqVO.getStatus()) | ||
| 37 | + .betweenIfPresent(PayOrderDO::getCreateTime, reqVO.getCreateTime()) | ||
| 38 | + .orderByDesc(PayOrderDO::getId)); | ||
| 51 | } | 39 | } |
| 52 | 40 | ||
| 53 | default Long selectCountByAppId(Long appId) { | 41 | default Long selectCountByAppId(Long appId) { |
| @@ -55,13 +43,13 @@ public interface PayOrderMapper extends BaseMapperX<PayOrderDO> { | @@ -55,13 +43,13 @@ public interface PayOrderMapper extends BaseMapperX<PayOrderDO> { | ||
| 55 | } | 43 | } |
| 56 | 44 | ||
| 57 | default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) { | 45 | default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) { |
| 58 | - return selectOne(new QueryWrapper<PayOrderDO>().eq("app_id", appId) | ||
| 59 | - .eq("merchant_order_id", merchantOrderId)); | 46 | + return selectOne(PayOrderDO::getAppId, appId, |
| 47 | + PayOrderDO::getMerchantOrderId, merchantOrderId); | ||
| 60 | } | 48 | } |
| 61 | 49 | ||
| 62 | default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) { | 50 | default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) { |
| 63 | - return update(update, new QueryWrapper<PayOrderDO>() | ||
| 64 | - .eq("id", id).eq("status", status)); | 51 | + return update(update, new LambdaQueryWrapper<PayOrderDO>() |
| 52 | + .eq(PayOrderDO::getId, id).eq(PayOrderDO::getStatus, status)); | ||
| 65 | } | 53 | } |
| 66 | 54 | ||
| 67 | } | 55 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.dal.mysql.refund; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.dal.mysql.refund; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | ||
| 7 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; | 6 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; |
| 8 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; | 7 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; |
| 9 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| @@ -44,27 +43,29 @@ public interface PayRefundMapper extends BaseMapperX<PayRefundDO> { | @@ -44,27 +43,29 @@ public interface PayRefundMapper extends BaseMapperX<PayRefundDO> { | ||
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) { | 45 | default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) { |
| 47 | - return selectPage(reqVO, new QueryWrapperX<PayRefundDO>() | ||
| 48 | - .eqIfPresent("app_id", reqVO.getAppId()) | ||
| 49 | - .eqIfPresent("channel_code", reqVO.getChannelCode()) | ||
| 50 | - .likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo()) | ||
| 51 | - .eqIfPresent("type", reqVO.getType()) | ||
| 52 | - .eqIfPresent("status", reqVO.getStatus()) | ||
| 53 | - .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | ||
| 54 | - .betweenIfPresent("create_time", reqVO.getCreateTime()) | ||
| 55 | - .orderByDesc("id")); | 46 | + return selectPage(reqVO, new LambdaQueryWrapperX<PayRefundDO>() |
| 47 | + .eqIfPresent(PayRefundDO::getAppId, reqVO.getAppId()) | ||
| 48 | + .eqIfPresent(PayRefundDO::getChannelCode, reqVO.getChannelCode()) | ||
| 49 | + .likeIfPresent(PayRefundDO::getMerchantOrderId, reqVO.getMerchantOrderId()) | ||
| 50 | + .likeIfPresent(PayRefundDO::getMerchantRefundId, reqVO.getMerchantRefundId()) | ||
| 51 | + .likeIfPresent(PayRefundDO::getChannelOrderNo, reqVO.getChannelOrderNo()) | ||
| 52 | + .likeIfPresent(PayRefundDO::getChannelRefundNo, reqVO.getChannelRefundNo()) | ||
| 53 | + .eqIfPresent(PayRefundDO::getStatus, reqVO.getStatus()) | ||
| 54 | + .betweenIfPresent(PayRefundDO::getCreateTime, reqVO.getCreateTime()) | ||
| 55 | + .orderByDesc(PayRefundDO::getId)); | ||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | default List<PayRefundDO> selectList(PayRefundExportReqVO reqVO) { | 58 | default List<PayRefundDO> selectList(PayRefundExportReqVO reqVO) { |
| 59 | - return selectList(new QueryWrapperX<PayRefundDO>() | ||
| 60 | - .eqIfPresent("app_id", reqVO.getAppId()) | ||
| 61 | - .eqIfPresent("channel_code", reqVO.getChannelCode()) | ||
| 62 | - .likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo()) | ||
| 63 | - .eqIfPresent("type", reqVO.getType()) | ||
| 64 | - .eqIfPresent("status", reqVO.getStatus()) | ||
| 65 | - .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | ||
| 66 | - .betweenIfPresent("create_time", reqVO.getCreateTime()) | ||
| 67 | - .orderByDesc("id")); | 59 | + return selectList(new LambdaQueryWrapperX<PayRefundDO>() |
| 60 | + .eqIfPresent(PayRefundDO::getAppId, reqVO.getAppId()) | ||
| 61 | + .eqIfPresent(PayRefundDO::getChannelCode, reqVO.getChannelCode()) | ||
| 62 | + .likeIfPresent(PayRefundDO::getMerchantOrderId, reqVO.getMerchantOrderId()) | ||
| 63 | + .likeIfPresent(PayRefundDO::getMerchantRefundId, reqVO.getMerchantRefundId()) | ||
| 64 | + .likeIfPresent(PayRefundDO::getChannelOrderNo, reqVO.getChannelOrderNo()) | ||
| 65 | + .likeIfPresent(PayRefundDO::getChannelRefundNo, reqVO.getChannelRefundNo()) | ||
| 66 | + .eqIfPresent(PayRefundDO::getStatus, reqVO.getStatus()) | ||
| 67 | + .betweenIfPresent(PayRefundDO::getCreateTime, reqVO.getCreateTime()) | ||
| 68 | + .orderByDesc(PayRefundDO::getId)); | ||
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | } | 71 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java
| @@ -14,4 +14,12 @@ public interface RedisKeyConstants { | @@ -14,4 +14,12 @@ public interface RedisKeyConstants { | ||
| 14 | "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类 | 14 | "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类 |
| 15 | RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 | 15 | RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 |
| 16 | 16 | ||
| 17 | + /** | ||
| 18 | + * 支付序号的缓存 | ||
| 19 | + * | ||
| 20 | + * KEY 格式:pay_no:{prefix} | ||
| 21 | + * VALUE 数据格式:编号自增 | ||
| 22 | + */ | ||
| 23 | + String PAY_NO = "pay_no"; | ||
| 24 | + | ||
| 17 | } | 25 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/no/PayNoRedisDAO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.dal.redis.no; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.date.DatePattern;import cn.hutool.core.date.DateUtil;import org.springframework.data.redis.core.StringRedisTemplate; | ||
| 4 | +import org.springframework.stereotype.Repository; | ||
| 5 | + | ||
| 6 | +import javax.annotation.Resource;import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 支付序号的 Redis DAO | ||
| 10 | + * | ||
| 11 | + * @author 芋道源码 | ||
| 12 | + */ | ||
| 13 | +@Repository | ||
| 14 | +public class PayNoRedisDAO { | ||
| 15 | + | ||
| 16 | + @Resource | ||
| 17 | + private StringRedisTemplate stringRedisTemplate; | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 生成序号 | ||
| 21 | + * | ||
| 22 | + * @param prefix 前缀 | ||
| 23 | + * @return 序号 | ||
| 24 | + */ | ||
| 25 | + public String generate(String prefix) { | ||
| 26 | + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN); | ||
| 27 | + Long no = stringRedisTemplate.opsForValue().increment(noPrefix); | ||
| 28 | + return noPrefix + no; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderNotifyStatusEnum.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.enums.order; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | ||
| 4 | -import lombok.AllArgsConstructor; | ||
| 5 | -import lombok.Getter; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * 支付订单的通知状态枚举 | ||
| 9 | - * | ||
| 10 | - * @author 芋道源码 | ||
| 11 | - */ | ||
| 12 | -@Getter | ||
| 13 | -@AllArgsConstructor | ||
| 14 | -public enum PayOrderNotifyStatusEnum implements IntArrayValuable { | ||
| 15 | - | ||
| 16 | - NO(0, "未通知"), | ||
| 17 | - SUCCESS(10, "通知成功"), | ||
| 18 | - FAILURE(20, "通知失败") | ||
| 19 | - ; | ||
| 20 | - | ||
| 21 | - private final Integer status; | ||
| 22 | - private final String name; | ||
| 23 | - | ||
| 24 | - @Override | ||
| 25 | - public int[] array() { | ||
| 26 | - return new int[0]; | ||
| 27 | - } | ||
| 28 | - | ||
| 29 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderRefundStatusEnum.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.enums.order; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | ||
| 4 | -import lombok.AllArgsConstructor; | ||
| 5 | -import lombok.Getter; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * 支付订单的退款状态枚举 | ||
| 9 | - * | ||
| 10 | - * @author 芋道源码 | ||
| 11 | - */ | ||
| 12 | -@Getter | ||
| 13 | -@AllArgsConstructor | ||
| 14 | -public enum PayOrderRefundStatusEnum implements IntArrayValuable { | ||
| 15 | - | ||
| 16 | - NO(0, "未退款"), | ||
| 17 | - PART(10, "部分退款"), | ||
| 18 | - ALL(20, "全部退款") | ||
| 19 | - ; | ||
| 20 | - | ||
| 21 | - private final Integer status; | ||
| 22 | - private final String name; | ||
| 23 | - | ||
| 24 | - @Override | ||
| 25 | - public int[] array() { | ||
| 26 | - return new int[0]; | ||
| 27 | - } | ||
| 28 | - | ||
| 29 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/config/PayConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.framework.pay.config; | ||
| 2 | + | ||
| 3 | +import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| 4 | +import org.springframework.context.annotation.Configuration; | ||
| 5 | + | ||
| 6 | +@Configuration(proxyBeanMethods = false) | ||
| 7 | +@EnableConfigurationProperties(PayProperties.class) | ||
| 8 | +public class PayConfiguration { | ||
| 9 | +} |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/config/PayProperties.java
| 1 | -package cn.iocoder.yudao.framework.pay.config; | 1 | +package cn.iocoder.yudao.module.pay.framework.pay.config; |
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | import org.hibernate.validator.constraints.URL; | 4 | import org.hibernate.validator.constraints.URL; |
| @@ -12,6 +12,9 @@ import javax.validation.constraints.NotEmpty; | @@ -12,6 +12,9 @@ import javax.validation.constraints.NotEmpty; | ||
| 12 | @Data | 12 | @Data |
| 13 | public class PayProperties { | 13 | public class PayProperties { |
| 14 | 14 | ||
| 15 | + private static final String ORDER_NO_PREFIX = "P"; | ||
| 16 | + private static final String REFUND_NO_PREFIX = "R"; | ||
| 17 | + | ||
| 15 | /** | 18 | /** |
| 16 | * 支付回调地址 | 19 | * 支付回调地址 |
| 17 | * | 20 | * |
| @@ -34,4 +37,16 @@ public class PayProperties { | @@ -34,4 +37,16 @@ public class PayProperties { | ||
| 34 | @URL(message = "支付回调地址的格式必须是 URL") | 37 | @URL(message = "支付回调地址的格式必须是 URL") |
| 35 | private String refundNotifyUrl; | 38 | private String refundNotifyUrl; |
| 36 | 39 | ||
| 40 | + /** | ||
| 41 | + * 支付订单 no 的前缀 | ||
| 42 | + */ | ||
| 43 | + @NotEmpty(message = "支付订单 no 的前缀不能为空") | ||
| 44 | + private String orderNoPrefix = ORDER_NO_PREFIX; | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 退款订单 no 的前缀 | ||
| 48 | + */ | ||
| 49 | + @NotEmpty(message = "退款订单 no 的前缀不能为空") | ||
| 50 | + private String refundNoPrefix = REFUND_NO_PREFIX; | ||
| 51 | + | ||
| 37 | } | 52 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/package-info.java
0 → 100644
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppService.java
| @@ -14,29 +14,29 @@ import java.util.List; | @@ -14,29 +14,29 @@ import java.util.List; | ||
| 14 | import java.util.Map; | 14 | import java.util.Map; |
| 15 | 15 | ||
| 16 | /** | 16 | /** |
| 17 | - * 支付应用信息 Service 接口 | 17 | + * 支付应用 Service 接口 |
| 18 | * | 18 | * |
| 19 | * @author 芋艿 | 19 | * @author 芋艿 |
| 20 | */ | 20 | */ |
| 21 | public interface PayAppService { | 21 | public interface PayAppService { |
| 22 | 22 | ||
| 23 | /** | 23 | /** |
| 24 | - * 创建支付应用信息 | 24 | + * 创建支付应用 |
| 25 | * | 25 | * |
| 26 | - * @param createReqVO 创建信息 | 26 | + * @param createReqVO 创建 |
| 27 | * @return 编号 | 27 | * @return 编号 |
| 28 | */ | 28 | */ |
| 29 | Long createApp(@Valid PayAppCreateReqVO createReqVO); | 29 | Long createApp(@Valid PayAppCreateReqVO createReqVO); |
| 30 | 30 | ||
| 31 | /** | 31 | /** |
| 32 | - * 更新支付应用信息 | 32 | + * 更新支付应用 |
| 33 | * | 33 | * |
| 34 | - * @param updateReqVO 更新信息 | 34 | + * @param updateReqVO 更新 |
| 35 | */ | 35 | */ |
| 36 | void updateApp(@Valid PayAppUpdateReqVO updateReqVO); | 36 | void updateApp(@Valid PayAppUpdateReqVO updateReqVO); |
| 37 | 37 | ||
| 38 | /** | 38 | /** |
| 39 | - * 修改应用信息状态 | 39 | + * 修改应用状态 |
| 40 | * | 40 | * |
| 41 | * @param id 应用编号 | 41 | * @param id 应用编号 |
| 42 | * @param status 状态 | 42 | * @param status 状态 |
| @@ -44,33 +44,40 @@ public interface PayAppService { | @@ -44,33 +44,40 @@ public interface PayAppService { | ||
| 44 | void updateAppStatus(Long id, Integer status); | 44 | void updateAppStatus(Long id, Integer status); |
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| 47 | - * 删除支付应用信息 | 47 | + * 删除支付应用 |
| 48 | * | 48 | * |
| 49 | * @param id 编号 | 49 | * @param id 编号 |
| 50 | */ | 50 | */ |
| 51 | void deleteApp(Long id); | 51 | void deleteApp(Long id); |
| 52 | 52 | ||
| 53 | /** | 53 | /** |
| 54 | - * 获得支付应用信息 | 54 | + * 获得支付应用 |
| 55 | * | 55 | * |
| 56 | * @param id 编号 | 56 | * @param id 编号 |
| 57 | - * @return 支付应用信息 | 57 | + * @return 支付应用 |
| 58 | */ | 58 | */ |
| 59 | PayAppDO getApp(Long id); | 59 | PayAppDO getApp(Long id); |
| 60 | 60 | ||
| 61 | /** | 61 | /** |
| 62 | - * 获得支付应用信息列表 | 62 | + * 获得支付应用列表 |
| 63 | * | 63 | * |
| 64 | * @param ids 编号 | 64 | * @param ids 编号 |
| 65 | - * @return 支付应用信息列表 | 65 | + * @return 支付应用列表 |
| 66 | */ | 66 | */ |
| 67 | List<PayAppDO> getAppList(Collection<Long> ids); | 67 | List<PayAppDO> getAppList(Collection<Long> ids); |
| 68 | 68 | ||
| 69 | /** | 69 | /** |
| 70 | - * 获得支付应用信息分页 | 70 | + * 获得支付应用列表 |
| 71 | + * | ||
| 72 | + * @return 支付应用列表 | ||
| 73 | + */ | ||
| 74 | + List<PayAppDO> getAppList(); | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 获得支付应用分页 | ||
| 71 | * | 78 | * |
| 72 | * @param pageReqVO 分页查询 | 79 | * @param pageReqVO 分页查询 |
| 73 | - * @return 支付应用信息分页 | 80 | + * @return 支付应用分页 |
| 74 | */ | 81 | */ |
| 75 | PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO); | 82 | PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO); |
| 76 | 83 | ||
| @@ -91,7 +98,7 @@ public interface PayAppService { | @@ -91,7 +98,7 @@ public interface PayAppService { | ||
| 91 | * 如果不合法,抛出 {@link ServiceException} 业务异常 | 98 | * 如果不合法,抛出 {@link ServiceException} 业务异常 |
| 92 | * | 99 | * |
| 93 | * @param id 应用编号 | 100 | * @param id 应用编号 |
| 94 | - * @return 应用信息 | 101 | + * @return 应用 |
| 95 | */ | 102 | */ |
| 96 | PayAppDO validPayApp(Long id); | 103 | PayAppDO validPayApp(Long id); |
| 97 | 104 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java
| 1 | package cn.iocoder.yudao.module.pay.service.app; | 1 | package cn.iocoder.yudao.module.pay.service.app; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO; | 5 | import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO; |
| 7 | import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO; | 6 | 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; | @@ -9,10 +8,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO; | ||
| 9 | import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert; | 8 | import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert; |
| 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 9 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| 11 | import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper; | 10 | import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper; |
| 12 | -import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; | ||
| 13 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; | 11 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; |
| 14 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | ||
| 15 | -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | ||
| 16 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 12 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 17 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | 13 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 18 | import org.springframework.context.annotation.Lazy; | 14 | import org.springframework.context.annotation.Lazy; |
| @@ -77,10 +73,10 @@ public class PayAppServiceImpl implements PayAppService { | @@ -77,10 +73,10 @@ public class PayAppServiceImpl implements PayAppService { | ||
| 77 | validateAppExists(id); | 73 | validateAppExists(id); |
| 78 | // 校验关联数据是否存在 | 74 | // 校验关联数据是否存在 |
| 79 | if (orderService.getOrderCountByAppId(id) > 0) { | 75 | if (orderService.getOrderCountByAppId(id) > 0) { |
| 80 | - throw exception(PAY_APP_EXIST_ORDER_CANT_DELETE); | 76 | + throw exception(APP_EXIST_ORDER_CANT_DELETE); |
| 81 | } | 77 | } |
| 82 | if (refundService.getRefundCountByAppId(id) > 0) { | 78 | if (refundService.getRefundCountByAppId(id) > 0) { |
| 83 | - throw exception(PAY_APP_EXIST_REFUND_CANT_DELETE); | 79 | + throw exception(APP_EXIST_REFUND_CANT_DELETE); |
| 84 | } | 80 | } |
| 85 | 81 | ||
| 86 | // 删除 | 82 | // 删除 |
| @@ -89,7 +85,7 @@ public class PayAppServiceImpl implements PayAppService { | @@ -89,7 +85,7 @@ public class PayAppServiceImpl implements PayAppService { | ||
| 89 | 85 | ||
| 90 | private void validateAppExists(Long id) { | 86 | private void validateAppExists(Long id) { |
| 91 | if (appMapper.selectById(id) == null) { | 87 | if (appMapper.selectById(id) == null) { |
| 92 | - throw exception(PAY_APP_NOT_FOUND); | 88 | + throw exception(APP_NOT_FOUND); |
| 93 | } | 89 | } |
| 94 | } | 90 | } |
| 95 | 91 | ||
| @@ -104,6 +100,11 @@ public class PayAppServiceImpl implements PayAppService { | @@ -104,6 +100,11 @@ public class PayAppServiceImpl implements PayAppService { | ||
| 104 | } | 100 | } |
| 105 | 101 | ||
| 106 | @Override | 102 | @Override |
| 103 | + public List<PayAppDO> getAppList() { | ||
| 104 | + return appMapper.selectList(); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + @Override | ||
| 107 | public PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO) { | 108 | public PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO) { |
| 108 | return appMapper.selectPage(pageReqVO); | 109 | return appMapper.selectPage(pageReqVO); |
| 109 | } | 110 | } |
| @@ -113,11 +114,11 @@ public class PayAppServiceImpl implements PayAppService { | @@ -113,11 +114,11 @@ public class PayAppServiceImpl implements PayAppService { | ||
| 113 | PayAppDO app = appMapper.selectById(id); | 114 | PayAppDO app = appMapper.selectById(id); |
| 114 | // 校验是否存在 | 115 | // 校验是否存在 |
| 115 | if (app == null) { | 116 | if (app == null) { |
| 116 | - throw exception(ErrorCodeConstants.PAY_APP_NOT_FOUND); | 117 | + throw exception(ErrorCodeConstants.APP_NOT_FOUND); |
| 117 | } | 118 | } |
| 118 | // 校验是否禁用 | 119 | // 校验是否禁用 |
| 119 | if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) { | 120 | if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) { |
| 120 | - throw exception(ErrorCodeConstants.PAY_APP_IS_DISABLE); | 121 | + throw exception(ErrorCodeConstants.APP_IS_DISABLE); |
| 121 | } | 122 | } |
| 122 | return app; | 123 | return app; |
| 123 | } | 124 | } |
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; | @@ -32,8 +32,7 @@ import java.util.List; | ||
| 32 | import java.util.concurrent.TimeUnit; | 32 | import java.util.concurrent.TimeUnit; |
| 33 | 33 | ||
| 34 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 34 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 35 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR; | ||
| 36 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_EXISTS; | 35 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; |
| 37 | 36 | ||
| 38 | /** | 37 | /** |
| 39 | * 支付渠道 Service 实现类 | 38 | * 支付渠道 Service 实现类 |
| @@ -142,7 +141,7 @@ public class PayChannelServiceImpl implements PayChannelService { | @@ -142,7 +141,7 @@ public class PayChannelServiceImpl implements PayChannelService { | ||
| 142 | // 解析配置 | 141 | // 解析配置 |
| 143 | Class<? extends PayClientConfig> payClass = PayChannelEnum.getByCode(code).getConfigClass(); | 142 | Class<? extends PayClientConfig> payClass = PayChannelEnum.getByCode(code).getConfigClass(); |
| 144 | if (ObjectUtil.isNull(payClass)) { | 143 | if (ObjectUtil.isNull(payClass)) { |
| 145 | - throw exception(CHANNEL_NOT_EXISTS); | 144 | + throw exception(CHANNEL_NOT_FOUND); |
| 146 | } | 145 | } |
| 147 | PayClientConfig config = JsonUtils.parseObject2(configStr, payClass); | 146 | PayClientConfig config = JsonUtils.parseObject2(configStr, payClass); |
| 148 | Assert.notNull(config); | 147 | Assert.notNull(config); |
| @@ -167,7 +166,7 @@ public class PayChannelServiceImpl implements PayChannelService { | @@ -167,7 +166,7 @@ public class PayChannelServiceImpl implements PayChannelService { | ||
| 167 | private PayChannelDO validateChannelExists(Long id) { | 166 | private PayChannelDO validateChannelExists(Long id) { |
| 168 | PayChannelDO channel = channelMapper.selectById(id); | 167 | PayChannelDO channel = channelMapper.selectById(id); |
| 169 | if (channel == null) { | 168 | if (channel == null) { |
| 170 | - throw exception(CHANNEL_NOT_EXISTS); | 169 | + throw exception(CHANNEL_NOT_FOUND); |
| 171 | } | 170 | } |
| 172 | return channel; | 171 | return channel; |
| 173 | } | 172 | } |
| @@ -203,10 +202,10 @@ public class PayChannelServiceImpl implements PayChannelService { | @@ -203,10 +202,10 @@ public class PayChannelServiceImpl implements PayChannelService { | ||
| 203 | 202 | ||
| 204 | private void validPayChannel(PayChannelDO channel) { | 203 | private void validPayChannel(PayChannelDO channel) { |
| 205 | if (channel == null) { | 204 | if (channel == null) { |
| 206 | - throw exception(ErrorCodeConstants.PAY_CHANNEL_NOT_FOUND); | 205 | + throw exception(CHANNEL_NOT_FOUND); |
| 207 | } | 206 | } |
| 208 | if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) { | 207 | if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) { |
| 209 | - throw exception(ErrorCodeConstants.PAY_CHANNEL_IS_DISABLE); | 208 | + throw exception(CHANNEL_IS_DISABLE); |
| 210 | } | 209 | } |
| 211 | } | 210 | } |
| 212 | 211 |
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 { | @@ -119,7 +119,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||
| 119 | new PayDemoOrderDO().setPayStatus(true).setPayTime(LocalDateTime.now()) | 119 | new PayDemoOrderDO().setPayStatus(true).setPayTime(LocalDateTime.now()) |
| 120 | .setPayChannelCode(payOrder.getChannelCode())); | 120 | .setPayChannelCode(payOrder.getChannelCode())); |
| 121 | if (updateCount == 0) { | 121 | if (updateCount == 0) { |
| 122 | - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); | 122 | + throw exception(DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); |
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| @@ -137,44 +137,44 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | @@ -137,44 +137,44 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||
| 137 | // 1.1 校验订单是否存在 | 137 | // 1.1 校验订单是否存在 |
| 138 | PayDemoOrderDO order = payDemoOrderMapper.selectById(id); | 138 | PayDemoOrderDO order = payDemoOrderMapper.selectById(id); |
| 139 | if (order == null) { | 139 | if (order == null) { |
| 140 | - throw exception(PAY_DEMO_ORDER_NOT_FOUND); | 140 | + throw exception(DEMO_ORDER_NOT_FOUND); |
| 141 | } | 141 | } |
| 142 | // 1.2 校验订单未支付 | 142 | // 1.2 校验订单未支付 |
| 143 | if (order.getPayStatus()) { | 143 | if (order.getPayStatus()) { |
| 144 | log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", | 144 | log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", |
| 145 | id, toJsonString(order)); | 145 | id, toJsonString(order)); |
| 146 | - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); | 146 | + throw exception(DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); |
| 147 | } | 147 | } |
| 148 | // 1.3 校验支付订单匹配 | 148 | // 1.3 校验支付订单匹配 |
| 149 | if (notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 | 149 | if (notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 |
| 150 | log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", | 150 | log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", |
| 151 | id, payOrderId, toJsonString(order)); | 151 | id, payOrderId, toJsonString(order)); |
| 152 | - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); | 152 | + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | // 2.1 校验支付单是否存在 | 155 | // 2.1 校验支付单是否存在 |
| 156 | PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); | 156 | PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); |
| 157 | if (payOrder == null) { | 157 | if (payOrder == null) { |
| 158 | log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); | 158 | log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); |
| 159 | - throw exception(PAY_ORDER_NOT_FOUND); | 159 | + throw exception(ORDER_NOT_FOUND); |
| 160 | } | 160 | } |
| 161 | // 2.2 校验支付单已支付 | 161 | // 2.2 校验支付单已支付 |
| 162 | if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { | 162 | if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { |
| 163 | log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", | 163 | log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", |
| 164 | id, payOrderId, toJsonString(payOrder)); | 164 | id, payOrderId, toJsonString(payOrder)); |
| 165 | - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); | 165 | + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); |
| 166 | } | 166 | } |
| 167 | // 2.3 校验支付金额一致 | 167 | // 2.3 校验支付金额一致 |
| 168 | if (notEqual(payOrder.getPrice(), order.getPrice())) { | 168 | if (notEqual(payOrder.getPrice(), order.getPrice())) { |
| 169 | log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", | 169 | log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", |
| 170 | id, payOrderId, toJsonString(order), toJsonString(payOrder)); | 170 | id, payOrderId, toJsonString(order), toJsonString(payOrder)); |
| 171 | - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); | 171 | + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); |
| 172 | } | 172 | } |
| 173 | // 2.4 校验支付订单匹配(二次) | 173 | // 2.4 校验支付订单匹配(二次) |
| 174 | if (notEqual(payOrder.getMerchantOrderId(), id.toString())) { | 174 | if (notEqual(payOrder.getMerchantOrderId(), id.toString())) { |
| 175 | log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", | 175 | log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", |
| 176 | id, payOrderId, toJsonString(payOrder)); | 176 | id, payOrderId, toJsonString(payOrder)); |
| 177 | - throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); | 177 | + throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); |
| 178 | } | 178 | } |
| 179 | return payOrder; | 179 | return payOrder; |
| 180 | } | 180 | } |
| @@ -203,15 +203,15 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | @@ -203,15 +203,15 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||
| 203 | // 校验订单是否存在 | 203 | // 校验订单是否存在 |
| 204 | PayDemoOrderDO order = payDemoOrderMapper.selectById(id); | 204 | PayDemoOrderDO order = payDemoOrderMapper.selectById(id); |
| 205 | if (order == null) { | 205 | if (order == null) { |
| 206 | - throw exception(PAY_DEMO_ORDER_NOT_FOUND); | 206 | + throw exception(DEMO_ORDER_NOT_FOUND); |
| 207 | } | 207 | } |
| 208 | // 校验订单是否支付 | 208 | // 校验订单是否支付 |
| 209 | if (!order.getPayStatus()) { | 209 | if (!order.getPayStatus()) { |
| 210 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID); | 210 | + throw exception(DEMO_ORDER_REFUND_FAIL_NOT_PAID); |
| 211 | } | 211 | } |
| 212 | // 校验订单是否已退款 | 212 | // 校验订单是否已退款 |
| 213 | if (order.getPayRefundId() != null) { | 213 | if (order.getPayRefundId() != null) { |
| 214 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED); | 214 | + throw exception(DEMO_ORDER_REFUND_FAIL_REFUNDED); |
| 215 | } | 215 | } |
| 216 | return order; | 216 | return order; |
| 217 | } | 217 | } |
| @@ -229,35 +229,35 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | @@ -229,35 +229,35 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||
| 229 | // 1.1 校验示例订单 | 229 | // 1.1 校验示例订单 |
| 230 | PayDemoOrderDO order = payDemoOrderMapper.selectById(id); | 230 | PayDemoOrderDO order = payDemoOrderMapper.selectById(id); |
| 231 | if (order == null) { | 231 | if (order == null) { |
| 232 | - throw exception(PAY_DEMO_ORDER_NOT_FOUND); | 232 | + throw exception(DEMO_ORDER_NOT_FOUND); |
| 233 | } | 233 | } |
| 234 | // 1.2 校验退款订单匹配 | 234 | // 1.2 校验退款订单匹配 |
| 235 | if (Objects.equals(order.getPayOrderId(), payRefundId)) { | 235 | if (Objects.equals(order.getPayOrderId(), payRefundId)) { |
| 236 | log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]", | 236 | log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]", |
| 237 | id, payRefundId, toJsonString(order)); | 237 | id, payRefundId, toJsonString(order)); |
| 238 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); | 238 | + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | // 2.1 校验退款订单 | 241 | // 2.1 校验退款订单 |
| 242 | PayRefundRespDTO payRefund = payRefundApi.getRefund(payRefundId); | 242 | PayRefundRespDTO payRefund = payRefundApi.getRefund(payRefundId); |
| 243 | if (payRefund == null) { | 243 | if (payRefund == null) { |
| 244 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND); | 244 | + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND); |
| 245 | } | 245 | } |
| 246 | // 2.2 | 246 | // 2.2 |
| 247 | if (!PayRefundStatusEnum.isSuccess(payRefund.getStatus())) { | 247 | if (!PayRefundStatusEnum.isSuccess(payRefund.getStatus())) { |
| 248 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS); | 248 | + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS); |
| 249 | } | 249 | } |
| 250 | // 2.3 校验退款金额一致 | 250 | // 2.3 校验退款金额一致 |
| 251 | if (notEqual(payRefund.getRefundPrice(), order.getPrice())) { | 251 | if (notEqual(payRefund.getRefundPrice(), order.getPrice())) { |
| 252 | log.error("[validateDemoOrderCanRefunded][order({}) payRefund({}) 退款金额不匹配,请进行处理!order 数据是:{},payRefund 数据是:{}]", | 252 | log.error("[validateDemoOrderCanRefunded][order({}) payRefund({}) 退款金额不匹配,请进行处理!order 数据是:{},payRefund 数据是:{}]", |
| 253 | id, payRefundId, toJsonString(order), toJsonString(payRefund)); | 253 | id, payRefundId, toJsonString(order), toJsonString(payRefund)); |
| 254 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH); | 254 | + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH); |
| 255 | } | 255 | } |
| 256 | // 2.4 校验退款订单匹配(二次) | 256 | // 2.4 校验退款订单匹配(二次) |
| 257 | if (notEqual(payRefund.getMerchantOrderId(), id.toString())) { | 257 | if (notEqual(payRefund.getMerchantOrderId(), id.toString())) { |
| 258 | log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!payRefund 数据是:{}]", | 258 | log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!payRefund 数据是:{}]", |
| 259 | id, payRefundId, toJsonString(payRefund)); | 259 | id, payRefundId, toJsonString(payRefund)); |
| 260 | - throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); | 260 | + throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); |
| 261 | } | 261 | } |
| 262 | return payRefund; | 262 | return payRefund; |
| 263 | } | 263 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java
| 1 | package cn.iocoder.yudao.module.pay.service.notify; | 1 | package cn.iocoder.yudao.module.pay.service.notify; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | ||
| 6 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | ||
| 3 | import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | 7 | import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; |
| 4 | 8 | ||
| 5 | import javax.validation.Valid; | 9 | import javax.validation.Valid; |
| 10 | +import java.util.List; | ||
| 6 | 11 | ||
| 7 | /** | 12 | /** |
| 8 | - * 支付通知 Service 接口 | 13 | + * 回调通知 Service 接口 |
| 9 | * | 14 | * |
| 10 | * @author 芋道源码 | 15 | * @author 芋道源码 |
| 11 | */ | 16 | */ |
| 12 | public interface PayNotifyService { | 17 | public interface PayNotifyService { |
| 13 | 18 | ||
| 14 | /** | 19 | /** |
| 15 | - * 创建支付通知任务 | 20 | + * 创建回调通知任务 |
| 16 | * | 21 | * |
| 17 | * @param reqDTO 任务信息 | 22 | * @param reqDTO 任务信息 |
| 18 | */ | 23 | */ |
| 19 | void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO); | 24 | void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO); |
| 20 | 25 | ||
| 21 | /** | 26 | /** |
| 22 | - * 执行支付通知 | 27 | + * 执行回调通知 |
| 23 | * | 28 | * |
| 24 | * 注意,该方法提供给定时任务调用。目前是 yudao-server 进行调用 | 29 | * 注意,该方法提供给定时任务调用。目前是 yudao-server 进行调用 |
| 25 | * @return 通知数量 | 30 | * @return 通知数量 |
| 26 | */ | 31 | */ |
| 27 | int executeNotify() throws InterruptedException; | 32 | int executeNotify() throws InterruptedException; |
| 28 | 33 | ||
| 34 | + /** | ||
| 35 | + * 获得回调通知 | ||
| 36 | + * | ||
| 37 | + * @param id 编号 | ||
| 38 | + * @return 回调通知 | ||
| 39 | + */ | ||
| 40 | + PayNotifyTaskDO getNotifyTask(Long id); | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 获得回调通知分页 | ||
| 44 | + * | ||
| 45 | + * @param pageReqVO 分页查询 | ||
| 46 | + * @return 回调通知分页 | ||
| 47 | + */ | ||
| 48 | + PageResult<PayNotifyTaskDO> getNotifyTaskPage(PayNotifyTaskPageReqVO pageReqVO); | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 获得回调日志列表 | ||
| 52 | + * | ||
| 53 | + * @param taskId 任务编号 | ||
| 54 | + * @return 日志列表 | ||
| 55 | + */ | ||
| 56 | + List<PayNotifyLogDO> getNotifyLogList(Long taskId); | ||
| 57 | + | ||
| 29 | } | 58 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java
| @@ -6,11 +6,13 @@ import cn.hutool.core.util.ObjectUtil; | @@ -6,11 +6,13 @@ import cn.hutool.core.util.ObjectUtil; | ||
| 6 | import cn.hutool.http.HttpResponse; | 6 | import cn.hutool.http.HttpResponse; |
| 7 | import cn.hutool.http.HttpUtil; | 7 | import cn.hutool.http.HttpUtil; |
| 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 9 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 9 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; | 10 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; |
| 10 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 11 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 11 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | 12 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; |
| 12 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; | 13 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; |
| 13 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; | 14 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; |
| 15 | +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; | ||
| 14 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | 16 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; |
| 15 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | 17 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; |
| 16 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 18 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| @@ -72,15 +74,15 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -72,15 +74,15 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 72 | private PayRefundService refundService; | 74 | private PayRefundService refundService; |
| 73 | 75 | ||
| 74 | @Resource | 76 | @Resource |
| 75 | - private PayNotifyTaskMapper payNotifyTaskMapper; | 77 | + private PayNotifyTaskMapper notifyTaskMapper; |
| 76 | @Resource | 78 | @Resource |
| 77 | - private PayNotifyLogMapper payNotifyLogMapper; | 79 | + private PayNotifyLogMapper notifyLogMapper; |
| 78 | 80 | ||
| 79 | @Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR) | 81 | @Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR) |
| 80 | private ThreadPoolTaskExecutor threadPoolTaskExecutor; | 82 | private ThreadPoolTaskExecutor threadPoolTaskExecutor; |
| 81 | 83 | ||
| 82 | @Resource | 84 | @Resource |
| 83 | - private PayNotifyLockRedisDAO payNotifyLockCoreRedisDAO; | 85 | + private PayNotifyLockRedisDAO notifyLockCoreRedisDAO; |
| 84 | 86 | ||
| 85 | @Resource | 87 | @Resource |
| 86 | @Lazy // 循环依赖(自己依赖自己),避免报错 | 88 | @Lazy // 循环依赖(自己依赖自己),避免报错 |
| @@ -105,7 +107,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -105,7 +107,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | // 执行插入 | 109 | // 执行插入 |
| 108 | - payNotifyTaskMapper.insert(task); | 110 | + notifyTaskMapper.insert(task); |
| 109 | 111 | ||
| 110 | // 必须在事务提交后,在发起任务,否则 PayNotifyTaskDO 还没入库,就提前回调接入的业务 | 112 | // 必须在事务提交后,在发起任务,否则 PayNotifyTaskDO 还没入库,就提前回调接入的业务 |
| 111 | TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { | 113 | TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { |
| @@ -119,7 +121,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -119,7 +121,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 119 | @Override | 121 | @Override |
| 120 | public int executeNotify() throws InterruptedException { | 122 | public int executeNotify() throws InterruptedException { |
| 121 | // 获得需要通知的任务 | 123 | // 获得需要通知的任务 |
| 122 | - List<PayNotifyTaskDO> tasks = payNotifyTaskMapper.selectListByNotify(); | 124 | + List<PayNotifyTaskDO> tasks = notifyTaskMapper.selectListByNotify(); |
| 123 | if (CollUtil.isEmpty(tasks)) { | 125 | if (CollUtil.isEmpty(tasks)) { |
| 124 | return 0; | 126 | return 0; |
| 125 | } | 127 | } |
| @@ -164,11 +166,11 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -164,11 +166,11 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 164 | */ | 166 | */ |
| 165 | public void executeNotify(PayNotifyTaskDO task) { | 167 | public void executeNotify(PayNotifyTaskDO task) { |
| 166 | // 分布式锁,避免并发问题 | 168 | // 分布式锁,避免并发问题 |
| 167 | - payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { | 169 | + notifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { |
| 168 | // 校验,当前任务是否已经被通知过 | 170 | // 校验,当前任务是否已经被通知过 |
| 169 | // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 | 171 | // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 |
| 170 | // 因此,此处我们通过第 notifyTimes 通知次数是否匹配来判断 | 172 | // 因此,此处我们通过第 notifyTimes 通知次数是否匹配来判断 |
| 171 | - PayNotifyTaskDO dbTask = payNotifyTaskMapper.selectById(task.getId()); | 173 | + PayNotifyTaskDO dbTask = notifyTaskMapper.selectById(task.getId()); |
| 172 | if (ObjectUtil.notEqual(task.getNotifyTimes(), dbTask.getNotifyTimes())) { | 174 | if (ObjectUtil.notEqual(task.getNotifyTimes(), dbTask.getNotifyTimes())) { |
| 173 | log.warn("[executeNotifySync][task({}) 任务被忽略,原因是它的通知不是第 ({}) 次,可能是因为并发执行了]", | 175 | log.warn("[executeNotifySync][task({}) 任务被忽略,原因是它的通知不是第 ({}) 次,可能是因为并发执行了]", |
| 174 | JsonUtils.toJsonString(task), dbTask.getNotifyTimes()); | 176 | JsonUtils.toJsonString(task), dbTask.getNotifyTimes()); |
| @@ -197,7 +199,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -197,7 +199,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 197 | // 记录 PayNotifyLog 日志 | 199 | // 记录 PayNotifyLog 日志 |
| 198 | String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : | 200 | String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : |
| 199 | JsonUtils.toJsonString(invokeResult); | 201 | JsonUtils.toJsonString(invokeResult); |
| 200 | - payNotifyLogMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) | 202 | + notifyLogMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) |
| 201 | .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); | 203 | .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); |
| 202 | } | 204 | } |
| 203 | 205 | ||
| @@ -250,22 +252,37 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -250,22 +252,37 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 250 | // 情况一:调用成功 | 252 | // 情况一:调用成功 |
| 251 | if (invokeResult != null && invokeResult.isSuccess()) { | 253 | if (invokeResult != null && invokeResult.isSuccess()) { |
| 252 | updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()); | 254 | updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()); |
| 253 | - payNotifyTaskMapper.updateById(updateTask); | 255 | + notifyTaskMapper.updateById(updateTask); |
| 254 | return updateTask.getStatus(); | 256 | return updateTask.getStatus(); |
| 255 | } | 257 | } |
| 256 | // 情况二:调用失败、调用异常 | 258 | // 情况二:调用失败、调用异常 |
| 257 | // 2.1 超过最大回调次数 | 259 | // 2.1 超过最大回调次数 |
| 258 | if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { | 260 | if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { |
| 259 | updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()); | 261 | updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()); |
| 260 | - payNotifyTaskMapper.updateById(updateTask); | 262 | + notifyTaskMapper.updateById(updateTask); |
| 261 | return updateTask.getStatus(); | 263 | return updateTask.getStatus(); |
| 262 | } | 264 | } |
| 263 | // 2.2 未超过最大回调次数 | 265 | // 2.2 未超过最大回调次数 |
| 264 | updateTask.setNextNotifyTime(addTime(Duration.ofSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()]))); | 266 | updateTask.setNextNotifyTime(addTime(Duration.ofSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()]))); |
| 265 | updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus() | 267 | updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus() |
| 266 | : PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()); | 268 | : PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()); |
| 267 | - payNotifyTaskMapper.updateById(updateTask); | 269 | + notifyTaskMapper.updateById(updateTask); |
| 268 | return updateTask.getStatus(); | 270 | return updateTask.getStatus(); |
| 269 | } | 271 | } |
| 270 | 272 | ||
| 273 | + @Override | ||
| 274 | + public PayNotifyTaskDO getNotifyTask(Long id) { | ||
| 275 | + return notifyTaskMapper.selectById(id); | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + @Override | ||
| 279 | + public PageResult<PayNotifyTaskDO> getNotifyTaskPage(PayNotifyTaskPageReqVO pageReqVO) { | ||
| 280 | + return notifyTaskMapper.selectPage(pageReqVO); | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + @Override | ||
| 284 | + public List<PayNotifyLogDO> getNotifyLogList(Long taskId) { | ||
| 285 | + return notifyLogMapper.selectListByTaskId(taskId); | ||
| 286 | + } | ||
| 287 | + | ||
| 271 | } | 288 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionService.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.service.order; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 4 | -import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | ||
| 5 | - | ||
| 6 | -import java.util.Collection; | ||
| 7 | -import java.util.List; | ||
| 8 | -import java.util.Map; | ||
| 9 | - | ||
| 10 | -// TODO 芋艿:合并到 PayOrder 里; | ||
| 11 | -/** | ||
| 12 | - * 支付订单 Service 接口 | ||
| 13 | - * | ||
| 14 | - * @author aquan | ||
| 15 | - */ | ||
| 16 | -public interface PayOrderExtensionService { | ||
| 17 | - | ||
| 18 | - /** | ||
| 19 | - * 获得支付订单 | ||
| 20 | - * | ||
| 21 | - * @param id 编号 | ||
| 22 | - * @return 支付订单 | ||
| 23 | - */ | ||
| 24 | - PayOrderExtensionDO getOrderExtension(Long id); | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * 获得支付订单 | ||
| 28 | - * 列表 | ||
| 29 | - * | ||
| 30 | - * @param ids 编号 | ||
| 31 | - * @return 支付订单 | ||
| 32 | - * 列表 | ||
| 33 | - */ | ||
| 34 | - List<PayOrderExtensionDO> getOrderExtensionList(Collection<Long> ids); | ||
| 35 | - | ||
| 36 | - /** | ||
| 37 | - * 根据订单成功的 扩展订单ID 查询所有的扩展订单转 成 map 返回 | ||
| 38 | - * | ||
| 39 | - * @param successExtensionIdList 订单 ID 集合 | ||
| 40 | - * @return 订单扩展 map 集合 | ||
| 41 | - */ | ||
| 42 | - default Map<Long, PayOrderExtensionDO> getOrderExtensionMap(Collection<Long> successExtensionIdList) { | ||
| 43 | - List<PayOrderExtensionDO> list = getOrderExtensionList(successExtensionIdList); | ||
| 44 | - return CollectionUtils.convertMap(list, PayOrderExtensionDO::getId); | ||
| 45 | - } | ||
| 46 | - | ||
| 47 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionServiceImpl.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.service.order; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | ||
| 4 | -import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; | ||
| 5 | -import org.springframework.stereotype.Service; | ||
| 6 | -import org.springframework.validation.annotation.Validated; | ||
| 7 | - | ||
| 8 | -import javax.annotation.Resource; | ||
| 9 | -import java.util.Collection; | ||
| 10 | -import java.util.List; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * 支付订单 Service 实现类 | ||
| 14 | - * | ||
| 15 | - * @author aquan | ||
| 16 | - */ | ||
| 17 | -@Service | ||
| 18 | -@Validated | ||
| 19 | -public class PayOrderExtensionServiceImpl implements PayOrderExtensionService { | ||
| 20 | - | ||
| 21 | - @Resource | ||
| 22 | - private PayOrderExtensionMapper orderExtensionMapper; | ||
| 23 | - | ||
| 24 | - @Override | ||
| 25 | - public PayOrderExtensionDO getOrderExtension(Long id) { | ||
| 26 | - return orderExtensionMapper.selectById(id); | ||
| 27 | - } | ||
| 28 | - | ||
| 29 | - @Override | ||
| 30 | - public List<PayOrderExtensionDO> getOrderExtensionList(Collection<Long> ids) { | ||
| 31 | - return orderExtensionMapper.selectBatchIds(ids); | ||
| 32 | - } | ||
| 33 | - | ||
| 34 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
| 1 | package cn.iocoder.yudao.module.pay.service.order; | 1 | package cn.iocoder.yudao.module.pay.service.order; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 6 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | 5 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 7 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; | 6 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; |
| @@ -9,12 +8,11 @@ import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; | @@ -9,12 +8,11 @@ import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; | ||
| 9 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitReqVO; | 8 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitReqVO; |
| 10 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO; | 9 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO; |
| 11 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 11 | +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | ||
| 12 | 12 | ||
| 13 | import javax.validation.Valid; | 13 | import javax.validation.Valid; |
| 14 | import javax.validation.constraints.NotEmpty; | 14 | import javax.validation.constraints.NotEmpty; |
| 15 | -import java.util.Collection; | ||
| 16 | import java.util.List; | 15 | import java.util.List; |
| 17 | -import java.util.Map; | ||
| 18 | 16 | ||
| 19 | /** | 17 | /** |
| 20 | * 支付订单 Service 接口 | 18 | * 支付订单 Service 接口 |
| @@ -49,45 +47,22 @@ public interface PayOrderService { | @@ -49,45 +47,22 @@ public interface PayOrderService { | ||
| 49 | Long getOrderCountByAppId(Long appId); | 47 | Long getOrderCountByAppId(Long appId); |
| 50 | 48 | ||
| 51 | /** | 49 | /** |
| 52 | - * 获得支付订单 | ||
| 53 | - * 分页 | 50 | + * 获得支付订单分页 |
| 54 | * | 51 | * |
| 55 | * @param pageReqVO 分页查询 | 52 | * @param pageReqVO 分页查询 |
| 56 | - * @return 支付订单 | ||
| 57 | - * 分页 | 53 | + * @return 支付订单分页 |
| 58 | */ | 54 | */ |
| 59 | PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO); | 55 | PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO); |
| 60 | 56 | ||
| 61 | /** | 57 | /** |
| 62 | - * 获得支付订单 | ||
| 63 | - * 列表, 用于 Excel 导出 | 58 | + * 获得支付订单列表, 用于 Excel 导出 |
| 64 | * | 59 | * |
| 65 | * @param exportReqVO 查询条件 | 60 | * @param exportReqVO 查询条件 |
| 66 | - * @return 支付订单 | ||
| 67 | - * 列表 | 61 | + * @return 支付订单列表 |
| 68 | */ | 62 | */ |
| 69 | List<PayOrderDO> getOrderList(PayOrderExportReqVO exportReqVO); | 63 | List<PayOrderDO> getOrderList(PayOrderExportReqVO exportReqVO); |
| 70 | 64 | ||
| 71 | /** | 65 | /** |
| 72 | - * 根据 ID 集合获取只包含商品名称的订单集合 | ||
| 73 | - * | ||
| 74 | - * @param idList 订单 ID 集合 | ||
| 75 | - * @return 只包含商品名称的订单集合 | ||
| 76 | - */ | ||
| 77 | - List<PayOrderDO> getOrderSubjectList(Collection<Long> idList); | ||
| 78 | - | ||
| 79 | - /** | ||
| 80 | - * 根据订单 ID 集合获取订单商品名称Map集合 | ||
| 81 | - * | ||
| 82 | - * @param ids 订单 ID 集合 | ||
| 83 | - * @return 订单商品 map 集合 | ||
| 84 | - */ | ||
| 85 | - default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> ids) { | ||
| 86 | - List<PayOrderDO> list = getOrderSubjectList(ids); | ||
| 87 | - return CollectionUtils.convertMap(list, PayOrderDO::getId); | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - /** | ||
| 91 | * 创建支付单 | 66 | * 创建支付单 |
| 92 | * | 67 | * |
| 93 | * @param reqDTO 创建请求 | 68 | * @param reqDTO 创建请求 |
| @@ -122,4 +97,12 @@ public interface PayOrderService { | @@ -122,4 +97,12 @@ public interface PayOrderService { | ||
| 122 | */ | 97 | */ |
| 123 | void updateOrderRefundPrice(Long id, Integer incrRefundPrice); | 98 | void updateOrderRefundPrice(Long id, Integer incrRefundPrice); |
| 124 | 99 | ||
| 100 | + /** | ||
| 101 | + * 获得支付订单 | ||
| 102 | + * | ||
| 103 | + * @param id 编号 | ||
| 104 | + * @return 支付订单 | ||
| 105 | + */ | ||
| 106 | + PayOrderExtensionDO getOrderExtension(Long id); | ||
| 107 | + | ||
| 125 | } | 108 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
| 1 | package cn.iocoder.yudao.module.pay.service.order; | 1 | package cn.iocoder.yudao.module.pay.service.order; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.date.DateUtil; | ||
| 4 | import cn.hutool.core.lang.Pair; | 3 | import cn.hutool.core.lang.Pair; |
| 5 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 6 | -import cn.hutool.core.util.RandomUtil; | ||
| 7 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | 8 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 10 | -import cn.iocoder.yudao.framework.pay.config.PayProperties; | ||
| 11 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; | 9 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 12 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 10 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 13 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 11 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| @@ -26,22 +24,21 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | @@ -26,22 +24,21 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | ||
| 26 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | 24 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; |
| 27 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; | 25 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; |
| 28 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; | 26 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; |
| 27 | +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | ||
| 29 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | 28 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| 30 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; | ||
| 31 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum; | ||
| 32 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 29 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 30 | +import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; | ||
| 33 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 31 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 34 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; | 32 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 35 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | 33 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 36 | import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | 34 | import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; |
| 35 | +import cn.iocoder.yudao.module.pay.util.MoneyUtils; | ||
| 37 | import lombok.extern.slf4j.Slf4j; | 36 | import lombok.extern.slf4j.Slf4j; |
| 38 | import org.springframework.stereotype.Service; | 37 | import org.springframework.stereotype.Service; |
| 39 | import org.springframework.transaction.annotation.Transactional; | 38 | import org.springframework.transaction.annotation.Transactional; |
| 40 | import org.springframework.validation.annotation.Validated; | 39 | import org.springframework.validation.annotation.Validated; |
| 41 | 40 | ||
| 42 | import javax.annotation.Resource; | 41 | import javax.annotation.Resource; |
| 43 | -import java.time.LocalDateTime; | ||
| 44 | -import java.util.Collection; | ||
| 45 | import java.util.List; | 42 | import java.util.List; |
| 46 | import java.util.Objects; | 43 | import java.util.Objects; |
| 47 | 44 | ||
| @@ -69,6 +66,8 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -69,6 +66,8 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 69 | private PayOrderMapper orderMapper; | 66 | private PayOrderMapper orderMapper; |
| 70 | @Resource | 67 | @Resource |
| 71 | private PayOrderExtensionMapper orderExtensionMapper; | 68 | private PayOrderExtensionMapper orderExtensionMapper; |
| 69 | + @Resource | ||
| 70 | + private PayNoRedisDAO noRedisDAO; | ||
| 72 | 71 | ||
| 73 | @Resource | 72 | @Resource |
| 74 | private PayAppService appService; | 73 | private PayAppService appService; |
| @@ -102,12 +101,6 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -102,12 +101,6 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 102 | return orderMapper.selectList(exportReqVO); | 101 | return orderMapper.selectList(exportReqVO); |
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | - // TODO @艿艿:需要优化。不确定这个方法的作用 | ||
| 106 | - @Override | ||
| 107 | - public List<PayOrderDO> getOrderSubjectList(Collection<Long> idList) { | ||
| 108 | - return orderMapper.findByIdListQueryOrderSubject(idList); | ||
| 109 | - } | ||
| 110 | - | ||
| 111 | @Override | 104 | @Override |
| 112 | public Long createOrder(PayOrderCreateReqDTO reqDTO) { | 105 | public Long createOrder(PayOrderCreateReqDTO reqDTO) { |
| 113 | // 校验 App | 106 | // 校验 App |
| @@ -125,11 +118,11 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -125,11 +118,11 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 125 | // 创建支付交易单 | 118 | // 创建支付交易单 |
| 126 | order = PayOrderConvert.INSTANCE.convert(reqDTO).setAppId(app.getId()) | 119 | order = PayOrderConvert.INSTANCE.convert(reqDTO).setAppId(app.getId()) |
| 127 | // 商户相关字段 | 120 | // 商户相关字段 |
| 128 | - .setNotifyUrl(app.getOrderNotifyUrl()).setNotifyStatus(PayOrderNotifyStatusEnum.NO.getStatus()) | 121 | + .setNotifyUrl(app.getOrderNotifyUrl()) |
| 129 | // 订单相关字段 | 122 | // 订单相关字段 |
| 130 | .setStatus(PayOrderStatusEnum.WAITING.getStatus()) | 123 | .setStatus(PayOrderStatusEnum.WAITING.getStatus()) |
| 131 | // 退款相关字段 | 124 | // 退款相关字段 |
| 132 | - .setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()).setRefundTimes(0).setRefundPrice(0); | 125 | + .setRefundPrice(0); |
| 133 | orderMapper.insert(order); | 126 | orderMapper.insert(order); |
| 134 | return order.getId(); | 127 | return order.getId(); |
| 135 | } | 128 | } |
| @@ -143,8 +136,9 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -143,8 +136,9 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 143 | PayClient client = payClientFactory.getPayClient(channel.getId()); | 136 | PayClient client = payClientFactory.getPayClient(channel.getId()); |
| 144 | 137 | ||
| 145 | // 2. 插入 PayOrderExtensionDO | 138 | // 2. 插入 PayOrderExtensionDO |
| 139 | + String no = noRedisDAO.generate(payProperties.getOrderNoPrefix()); | ||
| 146 | PayOrderExtensionDO orderExtension = PayOrderConvert.INSTANCE.convert(reqVO, userIp) | 140 | PayOrderExtensionDO orderExtension = PayOrderConvert.INSTANCE.convert(reqVO, userIp) |
| 147 | - .setOrderId(order.getId()).setNo(generateOrderExtensionNo()) | 141 | + .setOrderId(order.getId()).setNo(no) |
| 148 | .setChannelId(channel.getId()).setChannelCode(channel.getCode()) | 142 | .setChannelId(channel.getId()).setChannelCode(channel.getCode()) |
| 149 | .setStatus(PayOrderStatusEnum.WAITING.getStatus()); | 143 | .setStatus(PayOrderStatusEnum.WAITING.getStatus()); |
| 150 | orderExtensionMapper.insert(orderExtension); | 144 | orderExtensionMapper.insert(orderExtension); |
| @@ -162,10 +156,10 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -162,10 +156,10 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 162 | 156 | ||
| 163 | // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功 | 157 | // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功 |
| 164 | if (unifiedOrderResp != null) { | 158 | if (unifiedOrderResp != null) { |
| 165 | - notifyPayOrder(channel, unifiedOrderResp); | 159 | + getSelf().notifyOrder(channel, unifiedOrderResp); |
| 166 | // 如有渠道错误码,则抛出业务异常,提示用户 | 160 | // 如有渠道错误码,则抛出业务异常,提示用户 |
| 167 | if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) { | 161 | if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) { |
| 168 | - throw exception(PAY_ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), | 162 | + throw exception(ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), |
| 169 | unifiedOrderResp.getChannelErrorMsg()); | 163 | unifiedOrderResp.getChannelErrorMsg()); |
| 170 | } | 164 | } |
| 171 | // 此处需要读取最新的状态 | 165 | // 此处需要读取最新的状态 |
| @@ -177,13 +171,13 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -177,13 +171,13 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 177 | private PayOrderDO validateOrderCanSubmit(Long id) { | 171 | private PayOrderDO validateOrderCanSubmit(Long id) { |
| 178 | PayOrderDO order = orderMapper.selectById(id); | 172 | PayOrderDO order = orderMapper.selectById(id); |
| 179 | if (order == null) { // 是否存在 | 173 | if (order == null) { // 是否存在 |
| 180 | - throw exception(PAY_ORDER_NOT_FOUND); | 174 | + throw exception(ORDER_NOT_FOUND); |
| 181 | } | 175 | } |
| 182 | if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 | 176 | if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 |
| 183 | - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); | 177 | + throw exception(ORDER_STATUS_IS_NOT_WAITING); |
| 184 | } | 178 | } |
| 185 | if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期 | 179 | if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期 |
| 186 | - throw exception(PAY_ORDER_IS_EXPIRED); | 180 | + throw exception(ORDER_IS_EXPIRED); |
| 187 | } | 181 | } |
| 188 | return order; | 182 | return order; |
| 189 | } | 183 | } |
| @@ -196,7 +190,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -196,7 +190,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 196 | PayClient client = payClientFactory.getPayClient(channel.getId()); | 190 | PayClient client = payClientFactory.getPayClient(channel.getId()); |
| 197 | if (client == null) { | 191 | if (client == null) { |
| 198 | log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); | 192 | log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); |
| 199 | - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); | 193 | + throw exception(CHANNEL_NOT_FOUND); |
| 200 | } | 194 | } |
| 201 | return channel; | 195 | return channel; |
| 202 | } | 196 | } |
| @@ -211,61 +205,22 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -211,61 +205,22 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 211 | return payProperties.getOrderNotifyUrl() + "/" + channel.getId(); | 205 | return payProperties.getOrderNotifyUrl() + "/" + channel.getId(); |
| 212 | } | 206 | } |
| 213 | 207 | ||
| 214 | - private String generateOrderExtensionNo() { | ||
| 215 | -// wx | ||
| 216 | -// 2014 | ||
| 217 | -// 10 | ||
| 218 | -// 27 | ||
| 219 | -// 20 | ||
| 220 | -// 09 | ||
| 221 | -// 39 | ||
| 222 | -// 5522657 | ||
| 223 | -// a690389285100 | ||
| 224 | - // 目前的算法 | ||
| 225 | - // 时间序列,年月日时分秒 14 位 | ||
| 226 | - // 纯随机,6 位 TODO 芋艿:此处估计是会有问题的,后续在调整 | ||
| 227 | - return DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + // 时间序列 | ||
| 228 | - RandomUtil.randomInt(100000, 999999) // 随机。为什么是这个范围,因为偷懒 | ||
| 229 | - ; | ||
| 230 | - } | ||
| 231 | - | ||
| 232 | @Override | 208 | @Override |
| 233 | - @Transactional(rollbackFor = Exception.class) | ||
| 234 | public void notifyOrder(Long channelId, PayOrderRespDTO notify) { | 209 | public void notifyOrder(Long channelId, PayOrderRespDTO notify) { |
| 235 | // 校验支付渠道是否有效 | 210 | // 校验支付渠道是否有效 |
| 236 | PayChannelDO channel = channelService.validPayChannel(channelId); | 211 | PayChannelDO channel = channelService.validPayChannel(channelId); |
| 237 | // 更新支付订单为已支付 | 212 | // 更新支付订单为已支付 |
| 238 | - TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify)); | 213 | + TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyOrder(channel, notify)); |
| 239 | } | 214 | } |
| 240 | 215 | ||
| 241 | - @Override | ||
| 242 | - public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) { | ||
| 243 | - PayOrderDO order = orderMapper.selectById(id); | ||
| 244 | - if (order == null) { | ||
| 245 | - throw exception(PAY_ORDER_NOT_FOUND); | ||
| 246 | - } | ||
| 247 | - if (!PayOrderStatusEnum.isSuccess(order.getStatus())) { | ||
| 248 | - throw exception(PAY_REFUND_PRICE_EXCEED); | ||
| 249 | - } | ||
| 250 | - if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { | ||
| 251 | - throw exception(PAY_REFUND_PRICE_EXCEED); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | - // 更新订单 | ||
| 255 | - PayOrderDO updateObj = new PayOrderDO() | ||
| 256 | - .setRefundPrice(order.getRefundPrice() + incrRefundPrice) | ||
| 257 | - .setRefundTimes(order.getRefundTimes() + 1); | ||
| 258 | - if (Objects.equals(updateObj.getRefundPrice(), order.getPrice())) { | ||
| 259 | - updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) | ||
| 260 | - .setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()); | ||
| 261 | - } else { | ||
| 262 | - updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) | ||
| 263 | - .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus()); | ||
| 264 | - } | ||
| 265 | - orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj); | ||
| 266 | - } | ||
| 267 | - | ||
| 268 | - private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { | 216 | + /** |
| 217 | + * 通知并更新订单的支付结果 | ||
| 218 | + * | ||
| 219 | + * @param channel 支付渠道 | ||
| 220 | + * @param notify 通知 | ||
| 221 | + */ | ||
| 222 | + @Transactional(rollbackFor = Exception.class) // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyPayOrder(channel, notify) 调用,否则事务不生效 | ||
| 223 | + public void notifyOrder(PayChannelDO channel, PayOrderRespDTO notify) { | ||
| 269 | // 情况一:支付成功的回调 | 224 | // 情况一:支付成功的回调 |
| 270 | if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { | 225 | if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { |
| 271 | notifyOrderSuccess(channel, notify); | 226 | notifyOrderSuccess(channel, notify); |
| @@ -275,20 +230,22 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -275,20 +230,22 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 275 | if (PayOrderStatusRespEnum.isClosed(notify.getStatus())) { | 230 | if (PayOrderStatusRespEnum.isClosed(notify.getStatus())) { |
| 276 | notifyOrderClosed(channel, notify); | 231 | notifyOrderClosed(channel, notify); |
| 277 | } | 232 | } |
| 233 | + // 情况三:WAITING:无需处理 | ||
| 234 | + // 情况四:REFUND:通过退款回调处理 | ||
| 278 | } | 235 | } |
| 279 | 236 | ||
| 280 | private void notifyOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) { | 237 | private void notifyOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) { |
| 281 | // 1. 更新 PayOrderExtensionDO 支付成功 | 238 | // 1. 更新 PayOrderExtensionDO 支付成功 |
| 282 | - PayOrderExtensionDO orderExtension = updateOrderExtensionSuccess(notify); | 239 | + PayOrderExtensionDO orderExtension = updateOrderSuccess(notify); |
| 283 | // 2. 更新 PayOrderDO 支付成功 | 240 | // 2. 更新 PayOrderDO 支付成功 |
| 284 | - Pair<Boolean, PayOrderDO> order = updateOrderExtensionSuccess(channel, orderExtension, notify); | ||
| 285 | - if (order.getKey()) { // 如果之前已经成功回调,则直接返回,不用重复记录支付通知记录;例如说:支付平台重复回调 | 241 | + Boolean paid = updateOrderSuccess(channel, orderExtension, notify); |
| 242 | + if (paid) { // 如果之前已经成功回调,则直接返回,不用重复记录支付通知记录;例如说:支付平台重复回调 | ||
| 286 | return; | 243 | return; |
| 287 | } | 244 | } |
| 288 | 245 | ||
| 289 | // 3. 插入支付通知记录 | 246 | // 3. 插入支付通知记录 |
| 290 | notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | 247 | notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() |
| 291 | - .type(PayNotifyTypeEnum.ORDER.getType()).dataId(order.getValue().getId()).build()); | 248 | + .type(PayNotifyTypeEnum.ORDER.getType()).dataId(orderExtension.getOrderId()).build()); |
| 292 | } | 249 | } |
| 293 | 250 | ||
| 294 | /** | 251 | /** |
| @@ -297,25 +254,25 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -297,25 +254,25 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 297 | * @param notify 通知 | 254 | * @param notify 通知 |
| 298 | * @return PayOrderExtensionDO 对象 | 255 | * @return PayOrderExtensionDO 对象 |
| 299 | */ | 256 | */ |
| 300 | - private PayOrderExtensionDO updateOrderExtensionSuccess(PayOrderRespDTO notify) { | 257 | + private PayOrderExtensionDO updateOrderSuccess(PayOrderRespDTO notify) { |
| 301 | // 1. 查询 PayOrderExtensionDO | 258 | // 1. 查询 PayOrderExtensionDO |
| 302 | PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); | 259 | PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); |
| 303 | if (orderExtension == null) { | 260 | if (orderExtension == null) { |
| 304 | - throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); | 261 | + throw exception(ORDER_EXTENSION_NOT_FOUND); |
| 305 | } | 262 | } |
| 306 | if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 | 263 | if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 |
| 307 | log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新]", orderExtension.getId()); | 264 | log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新]", orderExtension.getId()); |
| 308 | return orderExtension; | 265 | return orderExtension; |
| 309 | } | 266 | } |
| 310 | if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 | 267 | if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 |
| 311 | - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | 268 | + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); |
| 312 | } | 269 | } |
| 313 | 270 | ||
| 314 | // 2. 更新 PayOrderExtensionDO | 271 | // 2. 更新 PayOrderExtensionDO |
| 315 | int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(), | 272 | int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(), |
| 316 | PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build()); | 273 | PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build()); |
| 317 | if (updateCounts == 0) { // 校验状态,必须是待支付 | 274 | if (updateCounts == 0) { // 校验状态,必须是待支付 |
| 318 | - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | 275 | + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); |
| 319 | } | 276 | } |
| 320 | log.info("[updateOrderExtensionSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId()); | 277 | log.info("[updateOrderExtensionSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId()); |
| 321 | return orderExtension; | 278 | return orderExtension; |
| @@ -327,37 +284,37 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -327,37 +284,37 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 327 | * @param channel 支付渠道 | 284 | * @param channel 支付渠道 |
| 328 | * @param orderExtension 支付拓展单 | 285 | * @param orderExtension 支付拓展单 |
| 329 | * @param notify 通知回调 | 286 | * @param notify 通知回调 |
| 330 | - * @return key:是否之前已经成功回调 | ||
| 331 | - * value:PayOrderDO 对象 | 287 | + * @return 是否之前已经成功回调 |
| 332 | */ | 288 | */ |
| 333 | - private Pair<Boolean, PayOrderDO> updateOrderExtensionSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, | ||
| 334 | - PayOrderRespDTO notify) { | 289 | + private Boolean updateOrderSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, |
| 290 | + PayOrderRespDTO notify) { | ||
| 335 | // 1. 判断 PayOrderDO 是否处于待支付 | 291 | // 1. 判断 PayOrderDO 是否处于待支付 |
| 336 | PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); | 292 | PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); |
| 337 | if (order == null) { | 293 | if (order == null) { |
| 338 | - throw exception(PAY_ORDER_NOT_FOUND); | 294 | + throw exception(ORDER_NOT_FOUND); |
| 339 | } | 295 | } |
| 340 | if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 | 296 | if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 |
| 341 | - && Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) { | 297 | + && Objects.equals(order.getExtensionId(), orderExtension.getId())) { |
| 342 | log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新]", order.getId()); | 298 | log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新]", order.getId()); |
| 343 | - return Pair.of(true, order); | 299 | + return true; |
| 344 | } | 300 | } |
| 345 | if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 | 301 | if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 |
| 346 | - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); | 302 | + throw exception(ORDER_STATUS_IS_NOT_WAITING); |
| 347 | } | 303 | } |
| 348 | 304 | ||
| 349 | // 2. 更新 PayOrderDO | 305 | // 2. 更新 PayOrderDO |
| 350 | int updateCounts = orderMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), | 306 | int updateCounts = orderMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), |
| 351 | PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()) | 307 | PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()) |
| 352 | .channelId(channel.getId()).channelCode(channel.getCode()) | 308 | .channelId(channel.getId()).channelCode(channel.getCode()) |
| 353 | - .successTime(notify.getSuccessTime()).successExtensionId(orderExtension.getId()) | 309 | + .successTime(notify.getSuccessTime()).extensionId(orderExtension.getId()).no(orderExtension.getNo()) |
| 354 | .channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId()) | 310 | .channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId()) |
| 355 | - .notifyTime(LocalDateTime.now()).build()); | 311 | + .channelFeeRate(channel.getFeeRate()).channelFeePrice(MoneyUtils.calculateRatePrice(order.getPrice(), channel.getFeeRate())) |
| 312 | + .build()); | ||
| 356 | if (updateCounts == 0) { // 校验状态,必须是待支付 | 313 | if (updateCounts == 0) { // 校验状态,必须是待支付 |
| 357 | - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); | 314 | + throw exception(ORDER_STATUS_IS_NOT_WAITING); |
| 358 | } | 315 | } |
| 359 | log.info("[updateOrderExtensionSuccess][支付订单({}) 更新为已支付]", order.getId()); | 316 | log.info("[updateOrderExtensionSuccess][支付订单({}) 更新为已支付]", order.getId()); |
| 360 | - return Pair.of(false, order); | 317 | + return false; |
| 361 | } | 318 | } |
| 362 | 319 | ||
| 363 | private void notifyOrderClosed(PayChannelDO channel, PayOrderRespDTO notify) { | 320 | private void notifyOrderClosed(PayChannelDO channel, PayOrderRespDTO notify) { |
| @@ -368,7 +325,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -368,7 +325,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 368 | // 1. 查询 PayOrderExtensionDO | 325 | // 1. 查询 PayOrderExtensionDO |
| 369 | PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); | 326 | PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); |
| 370 | if (orderExtension == null) { | 327 | if (orderExtension == null) { |
| 371 | - throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); | 328 | + throw exception(ORDER_EXTENSION_NOT_FOUND); |
| 372 | } | 329 | } |
| 373 | if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { // 如果已经是关闭,直接返回,不用重复更新 | 330 | if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { // 如果已经是关闭,直接返回,不用重复更新 |
| 374 | log.info("[updateOrderExtensionClosed][支付拓展单({}) 已经是支付关闭,无需更新]", orderExtension.getId()); | 331 | log.info("[updateOrderExtensionClosed][支付拓展单({}) 已经是支付关闭,无需更新]", orderExtension.getId()); |
| @@ -380,7 +337,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -380,7 +337,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 380 | return; | 337 | return; |
| 381 | } | 338 | } |
| 382 | if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 | 339 | if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 |
| 383 | - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | 340 | + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); |
| 384 | } | 341 | } |
| 385 | 342 | ||
| 386 | // 2. 更新 PayOrderExtensionDO | 343 | // 2. 更新 PayOrderExtensionDO |
| @@ -388,9 +345,46 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -388,9 +345,46 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 388 | PayOrderExtensionDO.builder().status(PayOrderStatusEnum.CLOSED.getStatus()).channelNotifyData(toJsonString(notify)) | 345 | PayOrderExtensionDO.builder().status(PayOrderStatusEnum.CLOSED.getStatus()).channelNotifyData(toJsonString(notify)) |
| 389 | .channelErrorCode(notify.getChannelErrorCode()).channelErrorMsg(notify.getChannelErrorMsg()).build()); | 346 | .channelErrorCode(notify.getChannelErrorCode()).channelErrorMsg(notify.getChannelErrorMsg()).build()); |
| 390 | if (updateCounts == 0) { // 校验状态,必须是待支付 | 347 | if (updateCounts == 0) { // 校验状态,必须是待支付 |
| 391 | - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | 348 | + throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); |
| 392 | } | 349 | } |
| 393 | log.info("[updateOrderExtensionClosed][支付拓展单({}) 更新为支付关闭]", orderExtension.getId()); | 350 | log.info("[updateOrderExtensionClosed][支付拓展单({}) 更新为支付关闭]", orderExtension.getId()); |
| 394 | } | 351 | } |
| 395 | 352 | ||
| 353 | + @Override | ||
| 354 | + public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) { | ||
| 355 | + PayOrderDO order = orderMapper.selectById(id); | ||
| 356 | + if (order == null) { | ||
| 357 | + throw exception(ORDER_NOT_FOUND); | ||
| 358 | + } | ||
| 359 | + if (!PayOrderStatusEnum.isSuccessOrRefund(order.getStatus())) { | ||
| 360 | + throw exception(ORDER_REFUND_FAIL_STATUS_ERROR); | ||
| 361 | + } | ||
| 362 | + if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { | ||
| 363 | + throw exception(REFUND_PRICE_EXCEED); | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + // 更新订单 | ||
| 367 | + PayOrderDO updateObj = new PayOrderDO() | ||
| 368 | + .setRefundPrice(order.getRefundPrice() + incrRefundPrice) | ||
| 369 | + .setStatus(PayOrderStatusEnum.REFUND.getStatus()); | ||
| 370 | + int updateCount = orderMapper.updateByIdAndStatus(id, order.getStatus(), updateObj); | ||
| 371 | + if (updateCount == 0) { | ||
| 372 | + throw exception(ORDER_REFUND_FAIL_STATUS_ERROR); | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + @Override | ||
| 377 | + public PayOrderExtensionDO getOrderExtension(Long id) { | ||
| 378 | + return orderExtensionMapper.selectById(id); | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + /** | ||
| 382 | + * 获得自身的代理对象,解决 AOP 生效问题 | ||
| 383 | + * | ||
| 384 | + * @return 自己 | ||
| 385 | + */ | ||
| 386 | + private PayOrderServiceImpl getSelf() { | ||
| 387 | + return SpringUtil.getBean(getClass()); | ||
| 388 | + } | ||
| 389 | + | ||
| 396 | } | 390 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.service.refund; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.service.refund; | ||
| 3 | import cn.hutool.core.date.DateUtil; | 3 | import cn.hutool.core.date.DateUtil; |
| 4 | import cn.hutool.core.util.RandomUtil; | 4 | import cn.hutool.core.util.RandomUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.framework.pay.config.PayProperties; | ||
| 7 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; | 6 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 8 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 7 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| @@ -21,16 +20,14 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | @@ -21,16 +20,14 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | ||
| 21 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 20 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 22 | import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; | 21 | import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; |
| 23 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; | 22 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; |
| 24 | -import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; | ||
| 25 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | 23 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| 26 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum; | ||
| 27 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 24 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 28 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | 25 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; |
| 26 | +import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; | ||
| 29 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 27 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 30 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; | 28 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 31 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | 29 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 32 | import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | 30 | import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; |
| 33 | -import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; | ||
| 34 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 31 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 35 | import lombok.extern.slf4j.Slf4j; | 32 | import lombok.extern.slf4j.Slf4j; |
| 36 | import org.springframework.stereotype.Service; | 33 | import org.springframework.stereotype.Service; |
| @@ -43,6 +40,7 @@ import java.util.List; | @@ -43,6 +40,7 @@ import java.util.List; | ||
| 43 | 40 | ||
| 44 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 41 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 45 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 42 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 43 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND; | ||
| 46 | 44 | ||
| 47 | /** | 45 | /** |
| 48 | * 退款订单 Service 实现类 | 46 | * 退款订单 Service 实现类 |
| @@ -66,8 +64,6 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -66,8 +64,6 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 66 | @Resource | 64 | @Resource |
| 67 | private PayOrderService orderService; | 65 | private PayOrderService orderService; |
| 68 | @Resource | 66 | @Resource |
| 69 | - private PayOrderExtensionService orderExtensionService; | ||
| 70 | - @Resource | ||
| 71 | private PayAppService appService; | 67 | private PayAppService appService; |
| 72 | @Resource | 68 | @Resource |
| 73 | private PayChannelService channelService; | 69 | private PayChannelService channelService; |
| @@ -106,13 +102,13 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -106,13 +102,13 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 106 | PayClient client = payClientFactory.getPayClient(channel.getId()); | 102 | PayClient client = payClientFactory.getPayClient(channel.getId()); |
| 107 | if (client == null) { | 103 | if (client == null) { |
| 108 | log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); | 104 | log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); |
| 109 | - throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); | 105 | + throw exception(CHANNEL_NOT_FOUND); |
| 110 | } | 106 | } |
| 111 | // 1.4 校验退款订单是否已经存在 | 107 | // 1.4 校验退款订单是否已经存在 |
| 112 | PayRefundDO refund = refundMapper.selectByAppIdAndMerchantRefundId( | 108 | PayRefundDO refund = refundMapper.selectByAppIdAndMerchantRefundId( |
| 113 | app.getId(), reqDTO.getMerchantRefundId()); | 109 | app.getId(), reqDTO.getMerchantRefundId()); |
| 114 | if (refund != null) { | 110 | if (refund != null) { |
| 115 | - throw exception(ErrorCodeConstants.PAY_REFUND_EXISTS); | 111 | + throw exception(ErrorCodeConstants.REFUND_EXISTS); |
| 116 | } | 112 | } |
| 117 | 113 | ||
| 118 | // 2.1 插入退款单 | 114 | // 2.1 插入退款单 |
| @@ -120,7 +116,7 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -120,7 +116,7 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 120 | .setNo(generateRefundNo()).setOrderId(order.getId()) | 116 | .setNo(generateRefundNo()).setOrderId(order.getId()) |
| 121 | .setChannelId(order.getChannelId()).setChannelCode(order.getChannelCode()) | 117 | .setChannelId(order.getChannelId()).setChannelCode(order.getChannelCode()) |
| 122 | // 商户相关的字段 | 118 | // 商户相关的字段 |
| 123 | - .setNotifyUrl(app.getRefundNotifyUrl()).setNotifyStatus(PayNotifyStatusEnum.WAITING.getStatus()) | 119 | + .setNotifyUrl(app.getRefundNotifyUrl()) |
| 124 | // 渠道相关字段 | 120 | // 渠道相关字段 |
| 125 | .setChannelOrderNo(order.getChannelOrderNo()) | 121 | .setChannelOrderNo(order.getChannelOrderNo()) |
| 126 | // 退款相关字段 | 122 | // 退款相关字段 |
| @@ -128,7 +124,7 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -128,7 +124,7 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 128 | .setPayPrice(order.getPrice()).setRefundPrice(reqDTO.getPrice()); | 124 | .setPayPrice(order.getPrice()).setRefundPrice(reqDTO.getPrice()); |
| 129 | refundMapper.insert(refund); | 125 | refundMapper.insert(refund); |
| 130 | // 2.2 向渠道发起退款申请 | 126 | // 2.2 向渠道发起退款申请 |
| 131 | - PayOrderExtensionDO orderExtension = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); | 127 | + PayOrderExtensionDO orderExtension = orderService.getOrderExtension(order.getExtensionId()); |
| 132 | PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO() | 128 | PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO() |
| 133 | .setPayPrice(order.getPrice()) | 129 | .setPayPrice(order.getPrice()) |
| 134 | .setRefundPrice(reqDTO.getPrice()) | 130 | .setRefundPrice(reqDTO.getPrice()) |
| @@ -136,7 +132,7 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -136,7 +132,7 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 136 | .setOutRefundNo(refund.getNo()) | 132 | .setOutRefundNo(refund.getNo()) |
| 137 | .setNotifyUrl(genChannelRefundNotifyUrl(channel)) | 133 | .setNotifyUrl(genChannelRefundNotifyUrl(channel)) |
| 138 | .setReason(reqDTO.getReason()); | 134 | .setReason(reqDTO.getReason()); |
| 139 | - PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO); // TODO 增加一个 channelErrorCode、channelErrorMsg 字段 | 135 | + PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO); |
| 140 | // 2.3 处理退款返回 | 136 | // 2.3 处理退款返回 |
| 141 | notifyRefund(channel, refundRespDTO); | 137 | notifyRefund(channel, refundRespDTO); |
| 142 | 138 | ||
| @@ -153,25 +149,21 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -153,25 +149,21 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 153 | private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) { | 149 | private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) { |
| 154 | PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId()); | 150 | PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId()); |
| 155 | if (order == null) { | 151 | if (order == null) { |
| 156 | - throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); | 152 | + throw exception(ErrorCodeConstants.ORDER_NOT_FOUND); |
| 157 | } | 153 | } |
| 158 | // 校验状态,必须是支付状态 | 154 | // 校验状态,必须是支付状态 |
| 159 | if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { | 155 | if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { |
| 160 | - throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS); | 156 | + throw exception(ErrorCodeConstants.ORDER_STATUS_IS_NOT_SUCCESS); |
| 161 | } | 157 | } |
| 162 | 158 | ||
| 163 | - // 是否已经全额退款 | ||
| 164 | - if (PayOrderRefundStatusEnum.ALL.getStatus().equals(order.getRefundStatus())) { | ||
| 165 | - throw exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED); | ||
| 166 | - } | ||
| 167 | // 校验金额 退款金额不能大于原定的金额 | 159 | // 校验金额 退款金额不能大于原定的金额 |
| 168 | if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){ | 160 | if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){ |
| 169 | - throw exception(ErrorCodeConstants.PAY_REFUND_PRICE_EXCEED); | 161 | + throw exception(ErrorCodeConstants.REFUND_PRICE_EXCEED); |
| 170 | } | 162 | } |
| 171 | // 是否有退款中的订单 | 163 | // 是否有退款中的订单 |
| 172 | if (refundMapper.selectCountByAppIdAndOrderId(reqDTO.getAppId(), order.getId(), | 164 | if (refundMapper.selectCountByAppIdAndOrderId(reqDTO.getAppId(), order.getId(), |
| 173 | PayRefundStatusEnum.WAITING.getStatus()) > 0) { | 165 | PayRefundStatusEnum.WAITING.getStatus()) > 0) { |
| 174 | - throw exception(ErrorCodeConstants.PAY_REFUND_HAS_REFUNDING); | 166 | + throw exception(ErrorCodeConstants.REFUND_HAS_REFUNDING); |
| 175 | } | 167 | } |
| 176 | return order; | 168 | return order; |
| 177 | } | 169 | } |
| @@ -205,7 +197,6 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -205,7 +197,6 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 205 | } | 197 | } |
| 206 | 198 | ||
| 207 | @Override | 199 | @Override |
| 208 | - @Transactional(rollbackFor = Exception.class) | ||
| 209 | public void notifyRefund(Long channelId, PayRefundRespDTO notify) { | 200 | public void notifyRefund(Long channelId, PayRefundRespDTO notify) { |
| 210 | // 校验支付渠道是否有效 | 201 | // 校验支付渠道是否有效 |
| 211 | channelService.validPayChannel(channelId); | 202 | channelService.validPayChannel(channelId); |
| @@ -217,28 +208,33 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -217,28 +208,33 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 217 | TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify)); | 208 | TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify)); |
| 218 | } | 209 | } |
| 219 | 210 | ||
| 211 | + // TODO 芋艿:事务问题 | ||
| 220 | private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) { | 212 | private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) { |
| 213 | + // 情况一:退款成功 | ||
| 221 | if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) { | 214 | if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) { |
| 222 | notifyRefundSuccess(channel, notify); | 215 | notifyRefundSuccess(channel, notify); |
| 223 | - } else { | 216 | + return; |
| 217 | + } | ||
| 218 | + // 情况二:退款失败 | ||
| 219 | + if (PayRefundStatusRespEnum.isFailure(notify.getStatus())) { | ||
| 224 | notifyRefundFailure(channel, notify); | 220 | notifyRefundFailure(channel, notify); |
| 225 | } | 221 | } |
| 226 | } | 222 | } |
| 227 | 223 | ||
| 228 | - private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { | 224 | + public void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { |
| 229 | // 1.1 查询 PayRefundDO | 225 | // 1.1 查询 PayRefundDO |
| 230 | PayRefundDO refund = refundMapper.selectByAppIdAndNo( | 226 | PayRefundDO refund = refundMapper.selectByAppIdAndNo( |
| 231 | channel.getAppId(), notify.getOutRefundNo()); | 227 | channel.getAppId(), notify.getOutRefundNo()); |
| 232 | if (refund == null) { | 228 | if (refund == null) { |
| 233 | - throw exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND); | 229 | + throw exception(ErrorCodeConstants.REFUND_NOT_FOUND); |
| 234 | } | 230 | } |
| 235 | if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 | 231 | if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 |
| 232 | + log.info("[notifyRefundSuccess][退款订单({}) 已经是退款成功,无需更新]", refund.getId()); | ||
| 236 | return; | 233 | return; |
| 237 | } | 234 | } |
| 238 | if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { | 235 | if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { |
| 239 | - throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING); | 236 | + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); |
| 240 | } | 237 | } |
| 241 | - | ||
| 242 | // 1.2 更新 PayRefundDO | 238 | // 1.2 更新 PayRefundDO |
| 243 | PayRefundDO updateRefundObj = new PayRefundDO() | 239 | PayRefundDO updateRefundObj = new PayRefundDO() |
| 244 | .setSuccessTime(notify.getSuccessTime()) | 240 | .setSuccessTime(notify.getSuccessTime()) |
| @@ -247,19 +243,48 @@ public class PayRefundServiceImpl implements PayRefundService { | @@ -247,19 +243,48 @@ public class PayRefundServiceImpl implements PayRefundService { | ||
| 247 | .setChannelNotifyData(toJsonString(notify)); | 243 | .setChannelNotifyData(toJsonString(notify)); |
| 248 | int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj); | 244 | int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj); |
| 249 | if (updateCounts == 0) { // 校验状态,必须是等待状态 | 245 | if (updateCounts == 0) { // 校验状态,必须是等待状态 |
| 250 | - throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING); | 246 | + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); |
| 251 | } | 247 | } |
| 248 | + log.info("[notifyRefundSuccess][退款订单({}) 更新为退款成功]", refund.getId()); | ||
| 252 | 249 | ||
| 253 | // 2. 更新订单 | 250 | // 2. 更新订单 |
| 254 | orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice()); | 251 | orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice()); |
| 255 | 252 | ||
| 256 | - // 3. 插入退款通知记录 | 253 | + // 3. 插入退款通知记录 TODO 芋艿:退款成功 |
| 257 | notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | 254 | notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() |
| 258 | .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); | 255 | .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); |
| 259 | } | 256 | } |
| 260 | 257 | ||
| 261 | - private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { | ||
| 262 | - // TODO 芋艿:未实现 | 258 | + @Transactional(rollbackFor = Exception.class) |
| 259 | + public void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { | ||
| 260 | + // 1.1 查询 PayRefundDO | ||
| 261 | + PayRefundDO refund = refundMapper.selectByAppIdAndNo( | ||
| 262 | + channel.getAppId(), notify.getOutRefundNo()); | ||
| 263 | + if (refund == null) { | ||
| 264 | + throw exception(ErrorCodeConstants.REFUND_NOT_FOUND); | ||
| 265 | + } | ||
| 266 | + if (PayRefundStatusEnum.isFailure(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 | ||
| 267 | + log.info("[notifyRefundSuccess][退款订单({}) 已经是退款关闭,无需更新]", refund.getId()); | ||
| 268 | + return; | ||
| 269 | + } | ||
| 270 | + if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { | ||
| 271 | + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); | ||
| 272 | + } | ||
| 273 | + // 1.2 更新 PayRefundDO | ||
| 274 | + PayRefundDO updateRefundObj = new PayRefundDO() | ||
| 275 | + .setChannelRefundNo(notify.getChannelRefundNo()) | ||
| 276 | + .setStatus(PayRefundStatusEnum.FAILURE.getStatus()) | ||
| 277 | + .setChannelNotifyData(toJsonString(notify)) | ||
| 278 | + .setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg()); | ||
| 279 | + int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj); | ||
| 280 | + if (updateCounts == 0) { // 校验状态,必须是等待状态 | ||
| 281 | + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); | ||
| 282 | + } | ||
| 283 | + log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId()); | ||
| 284 | + | ||
| 285 | + // 2. 插入退款通知记录 TODO 芋艿:退款失败 | ||
| 286 | + notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | ||
| 287 | + .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); | ||
| 263 | } | 288 | } |
| 264 | 289 | ||
| 265 | } | 290 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.util; | ||
| 2 | + | ||
| 3 | +import java.math.BigDecimal; | ||
| 4 | +import java.math.RoundingMode; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 金额工具类 | ||
| 8 | + * | ||
| 9 | + * @author 芋道源码 | ||
| 10 | + */ | ||
| 11 | +public class MoneyUtils { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 计算百分比金额,四舍五入 | ||
| 15 | + * | ||
| 16 | + * @param price 金额 | ||
| 17 | + * @param rate 百分比,例如说 56.77% 则传入 56.77 | ||
| 18 | + * @return 百分比金额 | ||
| 19 | + */ | ||
| 20 | + public static Integer calculateRatePrice(Integer price, Double rate) { | ||
| 21 | + return new BigDecimal(price) | ||
| 22 | + .multiply(BigDecimal.valueOf(rate)) // 乘以 | ||
| 23 | + .setScale(0, RoundingMode.HALF_UP) // 四舍五入 | ||
| 24 | + .intValue(); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +} |
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 { | @@ -90,7 +90,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 90 | PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> | 90 | PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> |
| 91 | o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); | 91 | o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); |
| 92 | // 调用, 并断言异常 | 92 | // 调用, 并断言异常 |
| 93 | - assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND); | 93 | + assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_FOUND); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | @Test | 96 | @Test |
| @@ -130,7 +130,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | @@ -130,7 +130,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 130 | Long id = randomLongId(); | 130 | Long id = randomLongId(); |
| 131 | 131 | ||
| 132 | // 调用, 并断言异常 | 132 | // 调用, 并断言异常 |
| 133 | - assertServiceException(() -> appService.deleteApp(id), PAY_APP_NOT_FOUND); | 133 | + assertServiceException(() -> appService.deleteApp(id), APP_NOT_FOUND); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | @Test | 136 | @Test |
| @@ -144,7 +144,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | @@ -144,7 +144,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 144 | when(orderService.getOrderCountByAppId(eq(id))).thenReturn(10L); | 144 | when(orderService.getOrderCountByAppId(eq(id))).thenReturn(10L); |
| 145 | 145 | ||
| 146 | // 调用, 并断言异常 | 146 | // 调用, 并断言异常 |
| 147 | - assertServiceException(() -> appService.deleteApp(id), PAY_APP_EXIST_ORDER_CANT_DELETE); | 147 | + assertServiceException(() -> appService.deleteApp(id), APP_EXIST_ORDER_CANT_DELETE); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | @Test | 150 | @Test |
| @@ -158,7 +158,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | @@ -158,7 +158,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 158 | when(refundService.getRefundCountByAppId(eq(id))).thenReturn(10L); | 158 | when(refundService.getRefundCountByAppId(eq(id))).thenReturn(10L); |
| 159 | 159 | ||
| 160 | // 调用, 并断言异常 | 160 | // 调用, 并断言异常 |
| 161 | - assertServiceException(() -> appService.deleteApp(id), PAY_APP_EXIST_REFUND_CANT_DELETE); | 161 | + assertServiceException(() -> appService.deleteApp(id), APP_EXIST_REFUND_CANT_DELETE); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | @Test | 164 | @Test |
| @@ -239,7 +239,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | @@ -239,7 +239,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 239 | 239 | ||
| 240 | @Test | 240 | @Test |
| 241 | public void testValidPayApp_notFound() { | 241 | public void testValidPayApp_notFound() { |
| 242 | - assertServiceException(() -> appService.validPayApp(randomLongId()), PAY_APP_NOT_FOUND); | 242 | + assertServiceException(() -> appService.validPayApp(randomLongId()), APP_NOT_FOUND); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | @Test | 245 | @Test |
| @@ -252,7 +252,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | @@ -252,7 +252,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 252 | Long id = dbApp.getId(); | 252 | Long id = dbApp.getId(); |
| 253 | 253 | ||
| 254 | // 调用,并断言异常 | 254 | // 调用,并断言异常 |
| 255 | - assertServiceException(() -> appService.validPayApp(id), PAY_APP_IS_DISABLE); | 255 | + assertServiceException(() -> appService.validPayApp(id), APP_IS_DISABLE); |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | } | 258 | } |
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; | @@ -26,8 +26,7 @@ import java.util.List; | ||
| 26 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 26 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 27 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 27 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 28 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 28 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 29 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR; | ||
| 30 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_EXISTS; | 29 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; |
| 31 | import static org.junit.jupiter.api.Assertions.*; | 30 | import static org.junit.jupiter.api.Assertions.*; |
| 32 | 31 | ||
| 33 | @Import({PayChannelServiceImpl.class}) | 32 | @Import({PayChannelServiceImpl.class}) |
| @@ -52,6 +51,40 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | @@ -52,6 +51,40 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||
| 52 | } | 51 | } |
| 53 | 52 | ||
| 54 | @Test | 53 | @Test |
| 54 | + public void testInitLocalCache() { | ||
| 55 | + // mock 数据 | ||
| 56 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, | ||
| 57 | + o -> o.setConfig(randomWxPayClientConfig())); | ||
| 58 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | ||
| 59 | + | ||
| 60 | + // 调用 | ||
| 61 | + channelService.initLocalCache(); | ||
| 62 | + // 校验缓存 | ||
| 63 | + assertEquals(1, channelService.getChannelCache().size()); | ||
| 64 | + assertEquals(dbChannel, channelService.getChannelCache().get(0)); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @Test | ||
| 68 | + public void testRefreshLocalCache() { | ||
| 69 | + // mock 数据 01 | ||
| 70 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, | ||
| 71 | + o -> o.setConfig(randomWxPayClientConfig())); | ||
| 72 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | ||
| 73 | + channelService.initLocalCache(); | ||
| 74 | + // mock 数据 02 | ||
| 75 | + PayChannelDO dbChannel02 = randomPojo(PayChannelDO.class, | ||
| 76 | + o -> o.setConfig(randomWxPayClientConfig())); | ||
| 77 | + channelMapper.insert(dbChannel02);// @Sql: 先插入出一条存在的数据 | ||
| 78 | + | ||
| 79 | + // 调用 | ||
| 80 | + channelService.refreshLocalCache(); | ||
| 81 | + // 校验缓存 | ||
| 82 | + assertEquals(2, channelService.getChannelCache().size()); | ||
| 83 | + assertEquals(dbChannel, channelService.getChannelCache().get(0)); | ||
| 84 | + assertEquals(dbChannel02, channelService.getChannelCache().get(1)); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + @Test | ||
| 55 | public void testCreateChannel_success() { | 88 | public void testCreateChannel_success() { |
| 56 | // 准备参数 | 89 | // 准备参数 |
| 57 | WxPayClientConfig config = randomWxPayClientConfig(); | 90 | WxPayClientConfig config = randomWxPayClientConfig(); |
| @@ -125,7 +158,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | @@ -125,7 +158,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||
| 125 | }); | 158 | }); |
| 126 | 159 | ||
| 127 | // 调用, 并断言异常 | 160 | // 调用, 并断言异常 |
| 128 | - assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS); | 161 | + assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_FOUND); |
| 129 | } | 162 | } |
| 130 | 163 | ||
| 131 | @Test | 164 | @Test |
| @@ -153,7 +186,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | @@ -153,7 +186,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||
| 153 | Long id = randomLongId(); | 186 | Long id = randomLongId(); |
| 154 | 187 | ||
| 155 | // 调用, 并断言异常 | 188 | // 调用, 并断言异常 |
| 156 | - assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS); | 189 | + assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_FOUND); |
| 157 | } | 190 | } |
| 158 | 191 | ||
| 159 | @Test | 192 | @Test |
| @@ -214,6 +247,101 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | @@ -214,6 +247,101 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||
| 214 | assertPojoEquals(channel, dbChannel); | 247 | assertPojoEquals(channel, dbChannel); |
| 215 | } | 248 | } |
| 216 | 249 | ||
| 250 | + @Test | ||
| 251 | + public void testValidPayChannel_notExists() { | ||
| 252 | + // 准备参数 | ||
| 253 | + Long id = randomLongId(); | ||
| 254 | + | ||
| 255 | + // 调用, 并断言异常 | ||
| 256 | + assertServiceException(() -> channelService.validPayChannel(id), CHANNEL_NOT_FOUND); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + @Test | ||
| 260 | + public void testValidPayChannel_isDisable() { | ||
| 261 | + // mock 数据 | ||
| 262 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { | ||
| 263 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | ||
| 264 | + o.setConfig(randomAlipayPayClientConfig()); | ||
| 265 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | ||
| 266 | + }); | ||
| 267 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | ||
| 268 | + // 准备参数 | ||
| 269 | + Long id = dbChannel.getId(); | ||
| 270 | + | ||
| 271 | + // 调用, 并断言异常 | ||
| 272 | + assertServiceException(() -> channelService.validPayChannel(id), CHANNEL_IS_DISABLE); | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + @Test | ||
| 276 | + public void testValidPayChannel_success() { | ||
| 277 | + // mock 数据 | ||
| 278 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { | ||
| 279 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | ||
| 280 | + o.setConfig(randomAlipayPayClientConfig()); | ||
| 281 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 282 | + }); | ||
| 283 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | ||
| 284 | + // 准备参数 | ||
| 285 | + Long id = dbChannel.getId(); | ||
| 286 | + | ||
| 287 | + // 调用 | ||
| 288 | + PayChannelDO channel = channelService.validPayChannel(id); | ||
| 289 | + // 断言异常 | ||
| 290 | + assertPojoEquals(channel, dbChannel); | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + @Test | ||
| 294 | + public void testValidPayChannel_appIdAndCode() { | ||
| 295 | + // mock 数据 | ||
| 296 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { | ||
| 297 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | ||
| 298 | + o.setConfig(randomAlipayPayClientConfig()); | ||
| 299 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 300 | + }); | ||
| 301 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | ||
| 302 | + // 准备参数 | ||
| 303 | + Long appId = dbChannel.getAppId(); | ||
| 304 | + String code = dbChannel.getCode(); | ||
| 305 | + | ||
| 306 | + // 调用 | ||
| 307 | + PayChannelDO channel = channelService.validPayChannel(appId, code); | ||
| 308 | + // 断言异常 | ||
| 309 | + assertPojoEquals(channel, dbChannel); | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + @Test | ||
| 313 | + public void testGetEnableChannelList() { | ||
| 314 | + // 准备参数 | ||
| 315 | + Long appId = randomLongId(); | ||
| 316 | + // mock 数据 01(enable 不匹配) | ||
| 317 | + PayChannelDO dbChannel01 = randomPojo(PayChannelDO.class, o -> { | ||
| 318 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | ||
| 319 | + o.setConfig(randomAlipayPayClientConfig()); | ||
| 320 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | ||
| 321 | + }); | ||
| 322 | + channelMapper.insert(dbChannel01);// @Sql: 先插入出一条存在的数据 | ||
| 323 | + // mock 数据 02(appId 不匹配) | ||
| 324 | + PayChannelDO dbChannel02 = randomPojo(PayChannelDO.class, o -> { | ||
| 325 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | ||
| 326 | + o.setConfig(randomAlipayPayClientConfig()); | ||
| 327 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 328 | + }); | ||
| 329 | + channelMapper.insert(dbChannel02);// @Sql: 先插入出一条存在的数据 | ||
| 330 | + // mock 数据 03 | ||
| 331 | + PayChannelDO dbChannel03 = randomPojo(PayChannelDO.class, o -> { | ||
| 332 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | ||
| 333 | + o.setConfig(randomAlipayPayClientConfig()); | ||
| 334 | + o.setAppId(appId); | ||
| 335 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 336 | + }); | ||
| 337 | + channelMapper.insert(dbChannel03);// @Sql: 先插入出一条存在的数据 | ||
| 338 | + | ||
| 339 | + // 调用 | ||
| 340 | + List<PayChannelDO> channel = channelService.getEnableChannelList(appId); | ||
| 341 | + // 断言异常 | ||
| 342 | + assertPojoEquals(channel, dbChannel03); | ||
| 343 | + } | ||
| 344 | + | ||
| 217 | public WxPayClientConfig randomWxPayClientConfig() { | 345 | public WxPayClientConfig randomWxPayClientConfig() { |
| 218 | return new WxPayClientConfig() | 346 | return new WxPayClientConfig() |
| 219 | .setAppId(randomString()) | 347 | .setAppId(randomString()) |
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
| 1 | package cn.iocoder.yudao.module.pay.service.order; | 1 | package cn.iocoder.yudao.module.pay.service.order; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.date.DateUtil; | ||
| 4 | -import cn.hutool.core.util.RandomUtil; | 3 | +import cn.hutool.extra.spring.SpringUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.framework.pay.config.PayProperties; | 5 | +import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 7 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 6 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 7 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 8 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 8 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 9 | -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 9 | +import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 10 | +import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; | ||
| 11 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; | ||
| 12 | +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | ||
| 10 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; | 13 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; |
| 11 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; | 14 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; |
| 15 | +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitReqVO; | ||
| 16 | +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO; | ||
| 17 | +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | ||
| 18 | +import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; | ||
| 12 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 19 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 20 | +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | ||
| 21 | +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; | ||
| 13 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; | 22 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; |
| 14 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; | 23 | +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; |
| 24 | +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | ||
| 15 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 25 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 16 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum; | 26 | +import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 17 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 27 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 18 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; | 28 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 19 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | 29 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 30 | +import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | ||
| 31 | +import org.junit.jupiter.api.BeforeEach; | ||
| 20 | import org.junit.jupiter.api.Test; | 32 | import org.junit.jupiter.api.Test; |
| 33 | +import org.mockito.ArgumentMatcher; | ||
| 34 | +import org.mockito.MockedStatic; | ||
| 21 | import org.springframework.boot.test.mock.mockito.MockBean; | 35 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 22 | import org.springframework.context.annotation.Import; | 36 | import org.springframework.context.annotation.Import; |
| 23 | 37 | ||
| 24 | import javax.annotation.Resource; | 38 | import javax.annotation.Resource; |
| 25 | -import java.time.LocalDateTime; | 39 | +import java.time.Duration; |
| 26 | import java.util.List; | 40 | import java.util.List; |
| 27 | 41 | ||
| 42 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | ||
| 43 | +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||
| 28 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 44 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 29 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 45 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 46 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||
| 30 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | 47 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; |
| 48 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; | ||
| 49 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; | ||
| 50 | +import static org.assertj.core.api.Assertions.assertThat; | ||
| 31 | import static org.junit.jupiter.api.Assertions.assertEquals; | 51 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 52 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
| 53 | +import static org.mockito.ArgumentMatchers.*; | ||
| 54 | +import static org.mockito.Mockito.*; | ||
| 32 | 55 | ||
| 33 | /** | 56 | /** |
| 34 | * {@link PayOrderServiceImpl} 的单元测试类 | 57 | * {@link PayOrderServiceImpl} 的单元测试类 |
| 35 | * | 58 | * |
| 36 | * @author 芋艿 | 59 | * @author 芋艿 |
| 37 | */ | 60 | */ |
| 38 | -@Import({PayOrderServiceImpl.class}) | ||
| 39 | -public class PayOrderServiceTest extends BaseDbUnitTest { | 61 | +@Import({PayOrderServiceImpl.class, PayNoRedisDAO.class}) |
| 62 | +public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { | ||
| 40 | 63 | ||
| 41 | @Resource | 64 | @Resource |
| 42 | private PayOrderServiceImpl orderService; | 65 | private PayOrderServiceImpl orderService; |
| 43 | 66 | ||
| 44 | @Resource | 67 | @Resource |
| 45 | private PayOrderMapper orderMapper; | 68 | private PayOrderMapper orderMapper; |
| 69 | + @Resource | ||
| 70 | + private PayOrderExtensionMapper orderExtensionMapper; | ||
| 46 | 71 | ||
| 47 | @MockBean | 72 | @MockBean |
| 48 | private PayClientFactory payClientFactory; | 73 | private PayClientFactory payClientFactory; |
| @@ -55,140 +80,92 @@ public class PayOrderServiceTest extends BaseDbUnitTest { | @@ -55,140 +80,92 @@ public class PayOrderServiceTest extends BaseDbUnitTest { | ||
| 55 | @MockBean | 80 | @MockBean |
| 56 | private PayNotifyService notifyService; | 81 | private PayNotifyService notifyService; |
| 57 | 82 | ||
| 58 | - public String generateNo() { | ||
| 59 | - return DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); | 83 | + @BeforeEach |
| 84 | + public void setUp() { | ||
| 85 | + when(properties.getOrderNotifyUrl()).thenReturn("http://127.0.0.1"); | ||
| 60 | } | 86 | } |
| 61 | 87 | ||
| 62 | @Test | 88 | @Test |
| 63 | public void testGetOrderPage() { | 89 | public void testGetOrderPage() { |
| 64 | - | ||
| 65 | - String merchantOrderId = generateNo(); | ||
| 66 | - String channelOrderId = generateNo(); | ||
| 67 | - | ||
| 68 | // mock 数据 | 90 | // mock 数据 |
| 69 | PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 | 91 | PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 |
| 70 | o.setAppId(1L); | 92 | o.setAppId(1L); |
| 71 | - o.setChannelId(1L); | ||
| 72 | o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | 93 | o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); |
| 73 | - o.setMerchantOrderId(merchantOrderId); | ||
| 74 | - o.setSubject("灿灿子的炸弹猫"); | ||
| 75 | - o.setBody("斌斌子送给灿灿子的炸弹猫"); | ||
| 76 | - o.setNotifyUrl("https://hc.com/lbh"); | ||
| 77 | - o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | ||
| 78 | - o.setPrice(10000); | ||
| 79 | - o.setChannelFeeRate(0.01); | ||
| 80 | - o.setChannelFeePrice(1L); | 94 | + o.setMerchantOrderId("110"); |
| 95 | + o.setChannelOrderNo("220"); | ||
| 96 | + o.setNo("330"); | ||
| 81 | o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | 97 | o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); |
| 82 | - o.setUserIp("127.0.0.1"); | ||
| 83 | - o.setCreateTime(LocalDateTime.of(2018, 1, 1, 10, 1, 0)); | ||
| 84 | - o.setExpireTime(LocalDateTime.of(2018, 1, 1, 10, 30, 0)); | ||
| 85 | - o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2)); | ||
| 86 | - o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); | ||
| 87 | - o.setSuccessExtensionId(1L); | ||
| 88 | - o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); | ||
| 89 | - o.setRefundTimes(0); | ||
| 90 | - o.setRefundPrice(0); | ||
| 91 | - o.setChannelUserId("1008611"); | ||
| 92 | - o.setChannelOrderNo(channelOrderId); | ||
| 93 | - o.setUpdateTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); | 98 | + o.setCreateTime(buildTime(2018, 1, 15)); |
| 94 | }); | 99 | }); |
| 95 | orderMapper.insert(dbOrder); | 100 | orderMapper.insert(dbOrder); |
| 96 | // 测试 appId 不匹配 | 101 | // 测试 appId 不匹配 |
| 97 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L))); | 102 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L))); |
| 98 | - // 测试 channelId 不匹配 | ||
| 99 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelId(2L))); | ||
| 100 | // 测试 channelCode 不匹配 | 103 | // 测试 channelCode 不匹配 |
| 101 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | 104 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); |
| 102 | // 测试 merchantOrderId 不匹配 | 105 | // 测试 merchantOrderId 不匹配 |
| 103 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo()))); | ||
| 104 | - // 测试 notifyStatus 不匹配 | ||
| 105 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | 106 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(randomString()))); |
| 107 | + // 测试 channelOrderNo 不匹配 | ||
| 108 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelOrderNo(randomString()))); | ||
| 109 | + // 测试 no 不匹配 | ||
| 110 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNo(randomString()))); | ||
| 106 | // 测试 status 不匹配 | 111 | // 测试 status 不匹配 |
| 107 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); | 112 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); |
| 108 | - // 测试 refundStatus 不匹配 | ||
| 109 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()))); | ||
| 110 | // 测试 createTime 不匹配 | 113 | // 测试 createTime 不匹配 |
| 111 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10, | ||
| 112 | - 1)))); | 114 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(buildTime(2019, 1, 1)))); |
| 113 | // 准备参数 | 115 | // 准备参数 |
| 114 | PayOrderPageReqVO reqVO = new PayOrderPageReqVO(); | 116 | PayOrderPageReqVO reqVO = new PayOrderPageReqVO(); |
| 115 | reqVO.setAppId(1L); | 117 | reqVO.setAppId(1L); |
| 116 | - reqVO.setChannelId(1L); | ||
| 117 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | 118 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); |
| 118 | - reqVO.setMerchantOrderId(merchantOrderId); | ||
| 119 | - reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | 119 | + reqVO.setMerchantOrderId("11"); |
| 120 | + reqVO.setChannelOrderNo("22"); | ||
| 121 | + reqVO.setNo("33"); | ||
| 120 | reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | 122 | reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); |
| 121 | - reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); | ||
| 122 | - reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)})); | 123 | + reqVO.setCreateTime(buildBetweenTime(2018, 1, 10, 2018, 1, 30)); |
| 124 | + | ||
| 123 | // 调用 | 125 | // 调用 |
| 124 | PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO); | 126 | PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO); |
| 125 | // 断言 | 127 | // 断言 |
| 126 | assertEquals(1, pageResult.getTotal()); | 128 | assertEquals(1, pageResult.getTotal()); |
| 127 | assertEquals(1, pageResult.getList().size()); | 129 | assertEquals(1, pageResult.getList().size()); |
| 128 | assertPojoEquals(dbOrder, pageResult.getList().get(0)); | 130 | assertPojoEquals(dbOrder, pageResult.getList().get(0)); |
| 129 | - // assertEquals(0, dbOrder.getUpdateTime().compareTo(pageResult.getList().get(0).getUpdateTime())); | ||
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | @Test | 133 | @Test |
| 133 | public void testGetOrderList() { | 134 | public void testGetOrderList() { |
| 134 | // mock 数据 | 135 | // mock 数据 |
| 135 | - String merchantOrderId = generateNo(); | ||
| 136 | - String channelOrderId = generateNo(); | ||
| 137 | PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 | 136 | PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 |
| 138 | o.setAppId(1L); | 137 | o.setAppId(1L); |
| 139 | - o.setChannelId(1L); | ||
| 140 | o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | 138 | o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); |
| 141 | - o.setMerchantOrderId(merchantOrderId); | ||
| 142 | - o.setSubject("灿灿子的炸弹猫"); | ||
| 143 | - o.setBody("斌斌子送给灿灿子的炸弹猫"); | ||
| 144 | - o.setNotifyUrl("https://hc.com/lbh"); | ||
| 145 | - o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | ||
| 146 | - o.setPrice(10000); | ||
| 147 | - o.setChannelFeeRate(0.01); | ||
| 148 | - o.setChannelFeePrice(1L); | 139 | + o.setMerchantOrderId("110"); |
| 140 | + o.setChannelOrderNo("220"); | ||
| 141 | + o.setNo("330"); | ||
| 149 | o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | 142 | o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); |
| 150 | - o.setUserIp("127.0.0.1"); | ||
| 151 | - o.setCreateTime(LocalDateTime.of(2018, 1, 1, 10, 1, 0)); | ||
| 152 | - o.setExpireTime(LocalDateTime.of(2018, 1, 1, 10, 30, 0)); | ||
| 153 | - o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2)); | ||
| 154 | - o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); | ||
| 155 | - o.setSuccessExtensionId(1L); | ||
| 156 | - o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); | ||
| 157 | - o.setRefundTimes(0); | ||
| 158 | - o.setRefundPrice(0); | ||
| 159 | - o.setChannelUserId("1008611"); | ||
| 160 | - o.setChannelOrderNo(channelOrderId); | ||
| 161 | - o.setUpdateTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); | ||
| 162 | - | 143 | + o.setCreateTime(buildTime(2018, 1, 15)); |
| 163 | }); | 144 | }); |
| 164 | orderMapper.insert(dbOrder); | 145 | orderMapper.insert(dbOrder); |
| 165 | // 测试 appId 不匹配 | 146 | // 测试 appId 不匹配 |
| 166 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L))); | 147 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L))); |
| 167 | - // 测试 channelId 不匹配 | ||
| 168 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelId(2L))); | ||
| 169 | // 测试 channelCode 不匹配 | 148 | // 测试 channelCode 不匹配 |
| 170 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | 149 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); |
| 171 | // 测试 merchantOrderId 不匹配 | 150 | // 测试 merchantOrderId 不匹配 |
| 172 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo()))); | ||
| 173 | - // 测试 notifyStatus 不匹配 | ||
| 174 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | 151 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(randomString()))); |
| 152 | + // 测试 channelOrderNo 不匹配 | ||
| 153 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelOrderNo(randomString()))); | ||
| 154 | + // 测试 no 不匹配 | ||
| 155 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNo(randomString()))); | ||
| 175 | // 测试 status 不匹配 | 156 | // 测试 status 不匹配 |
| 176 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); | 157 | orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); |
| 177 | - // 测试 refundStatus 不匹配 | ||
| 178 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus()))); | ||
| 179 | // 测试 createTime 不匹配 | 158 | // 测试 createTime 不匹配 |
| 180 | - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10, | ||
| 181 | - 1)))); | 159 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(buildTime(2019, 1, 1)))); |
| 182 | // 准备参数 | 160 | // 准备参数 |
| 183 | PayOrderExportReqVO reqVO = new PayOrderExportReqVO(); | 161 | PayOrderExportReqVO reqVO = new PayOrderExportReqVO(); |
| 184 | reqVO.setAppId(1L); | 162 | reqVO.setAppId(1L); |
| 185 | - reqVO.setChannelId(1L); | ||
| 186 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | 163 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); |
| 187 | - reqVO.setMerchantOrderId(merchantOrderId); | ||
| 188 | - reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | 164 | + reqVO.setMerchantOrderId("11"); |
| 165 | + reqVO.setChannelOrderNo("22"); | ||
| 166 | + reqVO.setNo("33"); | ||
| 189 | reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | 167 | reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); |
| 190 | - reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()); | ||
| 191 | - reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)})); | 168 | + reqVO.setCreateTime(buildBetweenTime(2018, 1, 10, 2018, 1, 30)); |
| 192 | 169 | ||
| 193 | // 调用 | 170 | // 调用 |
| 194 | List<PayOrderDO> list = orderService.getOrderList(reqVO); | 171 | List<PayOrderDO> list = orderService.getOrderList(reqVO); |
| @@ -197,4 +174,393 @@ public class PayOrderServiceTest extends BaseDbUnitTest { | @@ -197,4 +174,393 @@ public class PayOrderServiceTest extends BaseDbUnitTest { | ||
| 197 | assertPojoEquals(dbOrder, list.get(0)); | 174 | assertPojoEquals(dbOrder, list.get(0)); |
| 198 | } | 175 | } |
| 199 | 176 | ||
| 177 | + @Test | ||
| 178 | + public void testCreateOrder_success() { | ||
| 179 | + // mock 参数 | ||
| 180 | + PayOrderCreateReqDTO reqDTO = randomPojo(PayOrderCreateReqDTO.class, | ||
| 181 | + o -> o.setAppId(1L).setMerchantOrderId("10") | ||
| 182 | + .setSubject(randomString()).setBody(randomString())); | ||
| 183 | + // mock 方法 | ||
| 184 | + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L).setOrderNotifyUrl("http://127.0.0.1")); | ||
| 185 | + when(appService.validPayApp(eq(reqDTO.getAppId()))).thenReturn(app); | ||
| 186 | + | ||
| 187 | + // 调用 | ||
| 188 | + Long orderId = orderService.createOrder(reqDTO); | ||
| 189 | + // 断言 | ||
| 190 | + PayOrderDO order = orderMapper.selectById(orderId); | ||
| 191 | + assertPojoEquals(order, reqDTO); | ||
| 192 | + assertEquals(order.getAppId(), 1L); | ||
| 193 | + assertEquals(order.getNotifyUrl(), "http://127.0.0.1"); | ||
| 194 | + assertEquals(order.getStatus(), PayOrderStatusEnum.WAITING.getStatus()); | ||
| 195 | + assertEquals(order.getRefundPrice(), 0); | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + @Test | ||
| 199 | + public void testCreateOrder_exists() { | ||
| 200 | + // mock 参数 | ||
| 201 | + PayOrderCreateReqDTO reqDTO = randomPojo(PayOrderCreateReqDTO.class, | ||
| 202 | + o -> o.setAppId(1L).setMerchantOrderId("10")); | ||
| 203 | + // mock 数据 | ||
| 204 | + PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> o.setAppId(1L).setMerchantOrderId("10")); | ||
| 205 | + orderMapper.insert(dbOrder); | ||
| 206 | + | ||
| 207 | + // 调用 | ||
| 208 | + Long orderId = orderService.createOrder(reqDTO); | ||
| 209 | + // 断言 | ||
| 210 | + PayOrderDO order = orderMapper.selectById(orderId); | ||
| 211 | + assertPojoEquals(dbOrder, order); | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + @Test | ||
| 215 | + public void testSubmitOrder_notFound() { | ||
| 216 | + // 准备参数 | ||
| 217 | + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class); | ||
| 218 | + String userIp = randomString(); | ||
| 219 | + | ||
| 220 | + // 调用, 并断言异常 | ||
| 221 | + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_NOT_FOUND); | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + @Test | ||
| 225 | + public void testSubmitOrder_notWaiting() { | ||
| 226 | + // mock 数据(order) | ||
| 227 | + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())); | ||
| 228 | + orderMapper.insert(order); | ||
| 229 | + // 准备参数 | ||
| 230 | + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId())); | ||
| 231 | + String userIp = randomString(); | ||
| 232 | + | ||
| 233 | + // 调用, 并断言异常 | ||
| 234 | + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_STATUS_IS_NOT_WAITING); | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + @Test | ||
| 238 | + public void testSubmitOrder_expired() { | ||
| 239 | + // mock 数据(order) | ||
| 240 | + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) | ||
| 241 | + .setExpireTime(addTime(Duration.ofDays(-1)))); | ||
| 242 | + orderMapper.insert(order); | ||
| 243 | + // 准备参数 | ||
| 244 | + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId())); | ||
| 245 | + String userIp = randomString(); | ||
| 246 | + | ||
| 247 | + // 调用, 并断言异常 | ||
| 248 | + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_IS_EXPIRED); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + @Test | ||
| 252 | + public void testSubmitOrder_channelNotFound() { | ||
| 253 | + // mock 数据(order) | ||
| 254 | + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) | ||
| 255 | + .setAppId(1L).setExpireTime(addTime(Duration.ofDays(1)))); | ||
| 256 | + orderMapper.insert(order); | ||
| 257 | + // 准备参数 | ||
| 258 | + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()) | ||
| 259 | + .setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())); | ||
| 260 | + String userIp = randomString(); | ||
| 261 | + // mock 方法(app) | ||
| 262 | + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L)); | ||
| 263 | + when(appService.validPayApp(eq(1L))).thenReturn(app); | ||
| 264 | + // mock 方法(channel) | ||
| 265 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setCode(PayChannelEnum.ALIPAY_APP.getCode())); | ||
| 266 | + when(channelService.validPayChannel(eq(1L), eq(PayChannelEnum.ALIPAY_APP.getCode()))) | ||
| 267 | + .thenReturn(channel); | ||
| 268 | + | ||
| 269 | + // 调用, 并断言异常 | ||
| 270 | + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), CHANNEL_NOT_FOUND); | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + @Test // 调用 unifiedOrder 接口,返回存在渠道错误 | ||
| 274 | + public void testSubmitOrder_channelError() { | ||
| 275 | + PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class); | ||
| 276 | + try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | ||
| 277 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayOrderServiceImpl.class))) | ||
| 278 | + .thenReturn(payOrderServiceImpl); | ||
| 279 | + | ||
| 280 | + // mock 数据(order) | ||
| 281 | + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) | ||
| 282 | + .setAppId(1L).setExpireTime(addTime(Duration.ofDays(1)))); | ||
| 283 | + orderMapper.insert(order); | ||
| 284 | + // 准备参数 | ||
| 285 | + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()) | ||
| 286 | + .setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())); | ||
| 287 | + String userIp = randomString(); | ||
| 288 | + // mock 方法(app) | ||
| 289 | + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L)); | ||
| 290 | + when(appService.validPayApp(eq(1L))).thenReturn(app); | ||
| 291 | + // mock 方法(channel) | ||
| 292 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L) | ||
| 293 | + .setCode(PayChannelEnum.ALIPAY_APP.getCode())); | ||
| 294 | + when(channelService.validPayChannel(eq(1L), eq(PayChannelEnum.ALIPAY_APP.getCode()))) | ||
| 295 | + .thenReturn(channel); | ||
| 296 | + // mock 方法(client) | ||
| 297 | + PayClient client = mock(PayClient.class); | ||
| 298 | + when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); | ||
| 299 | + // mock 方法() | ||
| 300 | + PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o -> | ||
| 301 | + o.setChannelErrorCode("001").setChannelErrorMsg("模拟异常")); | ||
| 302 | + when(client.unifiedOrder(argThat(payOrderUnifiedReqDTO -> { | ||
| 303 | + assertNotNull(payOrderUnifiedReqDTO.getOutTradeNo()); | ||
| 304 | + assertThat(payOrderUnifiedReqDTO) | ||
| 305 | + .extracting("subject", "body", "notifyUrl", "returnUrl", "price", "expireTime") | ||
| 306 | + .containsExactly(order.getSubject(), order.getBody(), "http://127.0.0.1/10", | ||
| 307 | + reqVO.getReturnUrl(), order.getPrice(), order.getExpireTime()); | ||
| 308 | + return true; | ||
| 309 | + }))).thenReturn(unifiedOrderResp); | ||
| 310 | + | ||
| 311 | + // 调用,并断言异常 | ||
| 312 | + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), | ||
| 313 | + ORDER_SUBMIT_CHANNEL_ERROR, "001", "模拟异常"); | ||
| 314 | + // 断言,数据记录(PayOrderExtensionDO) | ||
| 315 | + PayOrderExtensionDO orderExtension = orderExtensionMapper.selectOne(null); | ||
| 316 | + assertNotNull(orderExtension); | ||
| 317 | + assertThat(orderExtension).extracting("no", "orderId").isNotNull(); | ||
| 318 | + assertThat(orderExtension) | ||
| 319 | + .extracting("channelId", "channelCode","userIp" ,"status", "channelExtras", | ||
| 320 | + "channelErrorCode", "channelErrorMsg", "channelNotifyData") | ||
| 321 | + .containsExactly(10L, PayChannelEnum.ALIPAY_APP.getCode(), userIp, | ||
| 322 | + PayOrderStatusEnum.WAITING.getStatus(), reqVO.getChannelExtras(), | ||
| 323 | + null, null, null); | ||
| 324 | + } | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + @Test | ||
| 328 | + public void testSubmitOrder_success() { | ||
| 329 | + PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class); | ||
| 330 | + try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | ||
| 331 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayOrderServiceImpl.class))) | ||
| 332 | + .thenReturn(payOrderServiceImpl); | ||
| 333 | + | ||
| 334 | + // mock 数据(order) | ||
| 335 | + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) | ||
| 336 | + .setAppId(1L).setExpireTime(addTime(Duration.ofDays(1)))); | ||
| 337 | + orderMapper.insert(order); | ||
| 338 | + // 准备参数 | ||
| 339 | + PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()) | ||
| 340 | + .setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())); | ||
| 341 | + String userIp = randomString(); | ||
| 342 | + // mock 方法(app) | ||
| 343 | + PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L)); | ||
| 344 | + when(appService.validPayApp(eq(1L))).thenReturn(app); | ||
| 345 | + // mock 方法(channel) | ||
| 346 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L) | ||
| 347 | + .setCode(PayChannelEnum.ALIPAY_APP.getCode())); | ||
| 348 | + when(channelService.validPayChannel(eq(1L), eq(PayChannelEnum.ALIPAY_APP.getCode()))) | ||
| 349 | + .thenReturn(channel); | ||
| 350 | + // mock 方法(client) | ||
| 351 | + PayClient client = mock(PayClient.class); | ||
| 352 | + when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); | ||
| 353 | + // mock 方法() | ||
| 354 | + PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o -> o.setChannelErrorCode(null).setChannelErrorMsg(null) | ||
| 355 | + .setDisplayMode(PayOrderDisplayModeEnum.URL.getMode()).setDisplayContent("tudou")); | ||
| 356 | + when(client.unifiedOrder(argThat(payOrderUnifiedReqDTO -> { | ||
| 357 | + assertNotNull(payOrderUnifiedReqDTO.getOutTradeNo()); | ||
| 358 | + assertThat(payOrderUnifiedReqDTO) | ||
| 359 | + .extracting("subject", "body", "notifyUrl", "returnUrl", "price", "expireTime") | ||
| 360 | + .containsExactly(order.getSubject(), order.getBody(), "http://127.0.0.1/10", | ||
| 361 | + reqVO.getReturnUrl(), order.getPrice(), order.getExpireTime()); | ||
| 362 | + return true; | ||
| 363 | + }))).thenReturn(unifiedOrderResp); | ||
| 364 | + | ||
| 365 | + // 调用 | ||
| 366 | + PayOrderSubmitRespVO result = orderService.submitOrder(reqVO, userIp); | ||
| 367 | + // 断言,数据记录(PayOrderExtensionDO) | ||
| 368 | + PayOrderExtensionDO orderExtension = orderExtensionMapper.selectOne(null); | ||
| 369 | + assertNotNull(orderExtension); | ||
| 370 | + assertThat(orderExtension).extracting("no", "orderId").isNotNull(); | ||
| 371 | + assertThat(orderExtension) | ||
| 372 | + .extracting("channelId", "channelCode","userIp" ,"status", "channelExtras", | ||
| 373 | + "channelErrorCode", "channelErrorMsg", "channelNotifyData") | ||
| 374 | + .containsExactly(10L, PayChannelEnum.ALIPAY_APP.getCode(), userIp, | ||
| 375 | + PayOrderStatusEnum.WAITING.getStatus(), reqVO.getChannelExtras(), | ||
| 376 | + null, null, null); | ||
| 377 | + // 断言,返回(PayOrderSubmitRespVO) | ||
| 378 | + assertThat(result) | ||
| 379 | + .extracting("status", "displayMode", "displayContent") | ||
| 380 | + .containsExactly(PayOrderStatusEnum.WAITING.getStatus(), PayOrderDisplayModeEnum.URL.getMode(), "tudou"); | ||
| 381 | + // 断言,调用 | ||
| 382 | + verify(payOrderServiceImpl).notifyOrder(same(channel), same(unifiedOrderResp)); | ||
| 383 | + } | ||
| 384 | + } | ||
| 385 | + | ||
| 386 | + @Test | ||
| 387 | + public void testNotifyOrder_channelId() { | ||
| 388 | + PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class); | ||
| 389 | + try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | ||
| 390 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayOrderServiceImpl.class))) | ||
| 391 | + .thenReturn(payOrderServiceImpl); | ||
| 392 | + // 准备参数 | ||
| 393 | + Long channelId = 10L; | ||
| 394 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class); | ||
| 395 | + // mock 方法(channel) | ||
| 396 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||
| 397 | + when(channelService.validPayChannel(eq(10L))).thenReturn(channel); | ||
| 398 | + | ||
| 399 | + // 调用 | ||
| 400 | + orderService.notifyOrder(channelId, notify); | ||
| 401 | + // 断言 | ||
| 402 | + verify(payOrderServiceImpl).notifyOrder(same(channel), same(notify)); | ||
| 403 | + } | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + @Test | ||
| 407 | + public void testNotifyOrderSuccess_orderExtension_notFound() { | ||
| 408 | + // 准备参数 | ||
| 409 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||
| 410 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | ||
| 411 | + o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus())); | ||
| 412 | + | ||
| 413 | + // 调用,并断言异常 | ||
| 414 | + assertServiceException(() -> orderService.notifyOrder(channel, notify), | ||
| 415 | + ORDER_EXTENSION_NOT_FOUND); | ||
| 416 | + } | ||
| 417 | + | ||
| 418 | + @Test | ||
| 419 | + public void testNotifyOrderSuccess_orderExtension_closed() { | ||
| 420 | + // mock 数据(PayOrderExtensionDO) | ||
| 421 | + PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class, | ||
| 422 | + o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) | ||
| 423 | + .setNo("P110")); | ||
| 424 | + orderExtensionMapper.insert(orderExtension); | ||
| 425 | + // 准备参数 | ||
| 426 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||
| 427 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | ||
| 428 | + o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 429 | + .setOutTradeNo("P110")); | ||
| 430 | + | ||
| 431 | + // 调用,并断言异常 | ||
| 432 | + assertServiceException(() -> orderService.notifyOrder(channel, notify), | ||
| 433 | + ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | ||
| 434 | + } | ||
| 435 | + | ||
| 436 | + @Test | ||
| 437 | + public void testNotifyOrderSuccess_order_notFound() { | ||
| 438 | + // mock 数据(PayOrderExtensionDO) | ||
| 439 | + PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class, | ||
| 440 | + o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()) | ||
| 441 | + .setNo("P110")); | ||
| 442 | + orderExtensionMapper.insert(orderExtension); | ||
| 443 | + // 准备参数 | ||
| 444 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||
| 445 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | ||
| 446 | + o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 447 | + .setOutTradeNo("P110")); | ||
| 448 | + | ||
| 449 | + // 调用,并断言异常 | ||
| 450 | + assertServiceException(() -> orderService.notifyOrder(channel, notify), | ||
| 451 | + ORDER_NOT_FOUND); | ||
| 452 | + // 断言 PayOrderExtensionDO :数据更新被回滚 | ||
| 453 | + assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null)); | ||
| 454 | + } | ||
| 455 | + | ||
| 456 | + @Test | ||
| 457 | + public void testNotifyOrderSuccess_order_closed() { | ||
| 458 | + testNotifyOrderSuccess_order_closedOrRefund(PayOrderStatusEnum.CLOSED.getStatus()); | ||
| 459 | + } | ||
| 460 | + | ||
| 461 | + @Test | ||
| 462 | + public void testNotifyOrderSuccess_order_refund() { | ||
| 463 | + testNotifyOrderSuccess_order_closedOrRefund(PayOrderStatusEnum.REFUND.getStatus()); | ||
| 464 | + } | ||
| 465 | + | ||
| 466 | + private void testNotifyOrderSuccess_order_closedOrRefund(Integer status) { | ||
| 467 | + // mock 数据(PayOrderDO) | ||
| 468 | + PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(status)); | ||
| 469 | + orderMapper.insert(order); | ||
| 470 | + // mock 数据(PayOrderExtensionDO) | ||
| 471 | + PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class, | ||
| 472 | + o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()) | ||
| 473 | + .setNo("P110") | ||
| 474 | + .setOrderId(order.getId())); | ||
| 475 | + orderExtensionMapper.insert(orderExtension); | ||
| 476 | + // 准备参数 | ||
| 477 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||
| 478 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | ||
| 479 | + o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 480 | + .setOutTradeNo("P110")); | ||
| 481 | + | ||
| 482 | + // 调用,并断言异常 | ||
| 483 | + assertServiceException(() -> orderService.notifyOrder(channel, notify), | ||
| 484 | + ORDER_STATUS_IS_NOT_WAITING); | ||
| 485 | + // 断言 PayOrderExtensionDO :数据未更新,因为它是 SUCCESS | ||
| 486 | + assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null)); | ||
| 487 | + } | ||
| 488 | + | ||
| 489 | + @Test | ||
| 490 | + public void testNotifyOrderSuccess_order_paid() { | ||
| 491 | + // mock 数据(PayOrderDO) | ||
| 492 | + PayOrderDO order = randomPojo(PayOrderDO.class, | ||
| 493 | + o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())); | ||
| 494 | + orderMapper.insert(order); | ||
| 495 | + // mock 数据(PayOrderExtensionDO) | ||
| 496 | + PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class, | ||
| 497 | + o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()) | ||
| 498 | + .setNo("P110") | ||
| 499 | + .setOrderId(order.getId())); | ||
| 500 | + orderExtensionMapper.insert(orderExtension); | ||
| 501 | + // 重要:需要将 order 的 extensionId 更新下 | ||
| 502 | + order.setExtensionId(orderExtension.getId()); | ||
| 503 | + orderMapper.updateById(order); | ||
| 504 | + // 准备参数 | ||
| 505 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||
| 506 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | ||
| 507 | + o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 508 | + .setOutTradeNo("P110")); | ||
| 509 | + | ||
| 510 | + // 调用,并断言异常 | ||
| 511 | + orderService.notifyOrder(channel, notify); | ||
| 512 | + // 断言 PayOrderExtensionDO :数据未更新,因为它是 SUCCESS | ||
| 513 | + assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null)); | ||
| 514 | + // 断言 PayOrderDO :数据未更新,因为它是 SUCCESS | ||
| 515 | + assertPojoEquals(order, orderMapper.selectOne(null)); | ||
| 516 | + // 断言,调用 | ||
| 517 | + verify(notifyService, never()).createPayNotifyTask(any(PayNotifyTaskCreateReqDTO.class)); | ||
| 518 | + } | ||
| 519 | + | ||
| 520 | + @Test | ||
| 521 | + public void testNotifyOrderSuccess_order_waiting() { | ||
| 522 | + // mock 数据(PayOrderDO) | ||
| 523 | + PayOrderDO order = randomPojo(PayOrderDO.class, | ||
| 524 | + o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) | ||
| 525 | + .setPrice(10)); | ||
| 526 | + orderMapper.insert(order); | ||
| 527 | + // mock 数据(PayOrderExtensionDO) | ||
| 528 | + PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class, | ||
| 529 | + o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()) | ||
| 530 | + .setNo("P110") | ||
| 531 | + .setOrderId(order.getId())); | ||
| 532 | + orderExtensionMapper.insert(orderExtension); | ||
| 533 | + // 准备参数 | ||
| 534 | + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L) | ||
| 535 | + .setFeeRate(0.1D)); | ||
| 536 | + PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | ||
| 537 | + o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 538 | + .setOutTradeNo("P110")); | ||
| 539 | + | ||
| 540 | + // 调用,并断言异常 | ||
| 541 | + orderService.notifyOrder(channel, notify); | ||
| 542 | + // 断言 PayOrderExtensionDO :数据未更新,因为它是 SUCCESS | ||
| 543 | + orderExtension.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()) | ||
| 544 | + .setChannelNotifyData(toJsonString(notify)); | ||
| 545 | + assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null), | ||
| 546 | + "updateTime", "updater"); | ||
| 547 | + // 断言 PayOrderDO :数据未更新,因为它是 SUCCESS | ||
| 548 | + order.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()) | ||
| 549 | + .setChannelId(10L).setChannelCode(channel.getCode()) | ||
| 550 | + .setSuccessTime(notify.getSuccessTime()).setExtensionId(orderExtension.getId()).setNo(orderExtension.getNo()) | ||
| 551 | + .setChannelOrderNo(notify.getChannelOrderNo()).setChannelUserId(notify.getChannelUserId()) | ||
| 552 | + .setChannelFeeRate(0.1D).setChannelFeePrice(1); | ||
| 553 | + assertPojoEquals(order, orderMapper.selectOne(null), | ||
| 554 | + "updateTime", "updater"); | ||
| 555 | + // 断言,调用 | ||
| 556 | + verify(notifyService).createPayNotifyTask(argThat(new ArgumentMatcher<PayNotifyTaskCreateReqDTO>() { | ||
| 557 | + @Override | ||
| 558 | + public boolean matches(PayNotifyTaskCreateReqDTO reqDTO) { | ||
| 559 | + assertEquals(reqDTO.getType(), PayNotifyTypeEnum.ORDER.getType()); | ||
| 560 | + assertEquals(reqDTO.getDataId(), orderExtension.getOrderId()); | ||
| 561 | + return true; | ||
| 562 | + } | ||
| 563 | + })); | ||
| 564 | + } | ||
| 565 | + | ||
| 200 | } | 566 | } |
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java
| 1 | package cn.iocoder.yudao.module.pay.service.refund; | 1 | package cn.iocoder.yudao.module.pay.service.refund; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.framework.pay.config.PayProperties; | ||
| 5 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 4 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 6 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 5 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 6 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; | ||
| 7 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 7 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 8 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; | 8 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; |
| 9 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; | 9 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; |
| 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 11 | import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; | 11 | import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; |
| 12 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; | 12 | +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 13 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | 13 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; |
| 14 | -import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum; | 14 | +import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 15 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 15 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 16 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; | 16 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 17 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | 17 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 18 | -import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; | ||
| 19 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 18 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 20 | import org.junit.jupiter.api.Test; | 19 | import org.junit.jupiter.api.Test; |
| 21 | import org.springframework.boot.test.mock.mockito.MockBean; | 20 | import org.springframework.boot.test.mock.mockito.MockBean; |
| @@ -31,7 +30,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | @@ -31,7 +30,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 31 | import static org.junit.jupiter.api.Assertions.assertEquals; | 30 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 32 | 31 | ||
| 33 | @Import(PayRefundServiceImpl.class) | 32 | @Import(PayRefundServiceImpl.class) |
| 34 | -public class PayRefundServiceTest extends BaseDbUnitTest { | 33 | +public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { |
| 35 | 34 | ||
| 36 | @Resource | 35 | @Resource |
| 37 | private PayRefundServiceImpl refundService; | 36 | private PayRefundServiceImpl refundService; |
| @@ -46,8 +45,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -46,8 +45,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 46 | @MockBean | 45 | @MockBean |
| 47 | private PayOrderService orderService; | 46 | private PayOrderService orderService; |
| 48 | @MockBean | 47 | @MockBean |
| 49 | - private PayOrderExtensionService orderExtensionService; | ||
| 50 | - @MockBean | ||
| 51 | private PayAppService appService; | 48 | private PayAppService appService; |
| 52 | @MockBean | 49 | @MockBean |
| 53 | private PayChannelService channelService; | 50 | private PayChannelService channelService; |
| @@ -66,8 +63,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -66,8 +63,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 66 | o.setMerchantOrderId("MOT0000001"); | 63 | o.setMerchantOrderId("MOT0000001"); |
| 67 | o.setMerchantRefundId("MRF0000001"); | 64 | o.setMerchantRefundId("MRF0000001"); |
| 68 | o.setNotifyUrl("https://www.cancanzi.com"); | 65 | o.setNotifyUrl("https://www.cancanzi.com"); |
| 69 | - o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | ||
| 70 | - o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | 66 | + o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); |
| 71 | o.setPayPrice(100); | 67 | o.setPayPrice(100); |
| 72 | o.setRefundPrice(500); | 68 | o.setRefundPrice(500); |
| 73 | o.setReason("就是想退款了,你有意见吗"); | 69 | o.setReason("就是想退款了,你有意见吗"); |
| @@ -87,11 +83,8 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -87,11 +83,8 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 87 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | 83 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); |
| 88 | // 测试 merchantRefundNo 不匹配 | 84 | // 测试 merchantRefundNo 不匹配 |
| 89 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112"))); | 85 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112"))); |
| 90 | - // 测试 notifyStatus 不匹配 | ||
| 91 | - refundMapper.insert( | ||
| 92 | - cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | ||
| 93 | // 测试 status 不匹配 | 86 | // 测试 status 不匹配 |
| 94 | - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus()))); | 87 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()))); |
| 95 | // 测试 createTime 不匹配 | 88 | // 测试 createTime 不匹配 |
| 96 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> | 89 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> |
| 97 | o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10)))); | 90 | o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10)))); |
| @@ -99,8 +92,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -99,8 +92,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 99 | PayRefundPageReqVO reqVO = new PayRefundPageReqVO(); | 92 | PayRefundPageReqVO reqVO = new PayRefundPageReqVO(); |
| 100 | reqVO.setAppId(1L); | 93 | reqVO.setAppId(1L); |
| 101 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | 94 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); |
| 102 | - reqVO.setMerchantRefundNo("MRF0000001"); | ||
| 103 | - reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | 95 | + reqVO.setMerchantRefundId("MRF0000001"); |
| 104 | reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | 96 | reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); |
| 105 | reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)})); | 97 | reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)})); |
| 106 | 98 | ||
| @@ -124,8 +116,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -124,8 +116,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 124 | o.setMerchantOrderId("MOT0000001"); | 116 | o.setMerchantOrderId("MOT0000001"); |
| 125 | o.setMerchantRefundId("MRF0000001"); | 117 | o.setMerchantRefundId("MRF0000001"); |
| 126 | o.setNotifyUrl("https://www.cancanzi.com"); | 118 | o.setNotifyUrl("https://www.cancanzi.com"); |
| 127 | - o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | ||
| 128 | - o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | 119 | + o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); |
| 129 | o.setPayPrice(100); | 120 | o.setPayPrice(100); |
| 130 | o.setRefundPrice(500); | 121 | o.setRefundPrice(500); |
| 131 | o.setReason("就是想退款了,你有意见吗"); | 122 | o.setReason("就是想退款了,你有意见吗"); |
| @@ -145,11 +136,8 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -145,11 +136,8 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 145 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | 136 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); |
| 146 | // 测试 merchantRefundNo 不匹配 | 137 | // 测试 merchantRefundNo 不匹配 |
| 147 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112"))); | 138 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112"))); |
| 148 | - // 测试 notifyStatus 不匹配 | ||
| 149 | - refundMapper.insert( | ||
| 150 | - cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | ||
| 151 | // 测试 status 不匹配 | 139 | // 测试 status 不匹配 |
| 152 | - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus()))); | 140 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()))); |
| 153 | // 测试 createTime 不匹配 | 141 | // 测试 createTime 不匹配 |
| 154 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> | 142 | refundMapper.insert(cloneIgnoreId(dbRefund, o -> |
| 155 | o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10)))); | 143 | o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10)))); |
| @@ -158,10 +146,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | @@ -158,10 +146,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { | ||
| 158 | PayRefundExportReqVO reqVO = new PayRefundExportReqVO(); | 146 | PayRefundExportReqVO reqVO = new PayRefundExportReqVO(); |
| 159 | reqVO.setAppId(1L); | 147 | reqVO.setAppId(1L); |
| 160 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | 148 | reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); |
| 161 | - reqVO.setMerchantRefundNo("MRF0000001"); | ||
| 162 | - reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | ||
| 163 | reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | 149 | reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); |
| 164 | - reqVO.setType(PayOrderRefundStatusEnum.PART.getStatus()); | ||
| 165 | reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)})); | 150 | reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)})); |
| 166 | 151 | ||
| 167 | // 调用 | 152 | // 调用 |
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/clean.sql
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql
| @@ -39,19 +39,17 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( | @@ -39,19 +39,17 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( | ||
| 39 | `subject` varchar(32) NOT NULL, | 39 | `subject` varchar(32) NOT NULL, |
| 40 | `body` varchar(128) NOT NULL, | 40 | `body` varchar(128) NOT NULL, |
| 41 | `notify_url` varchar(1024) NOT NULL, | 41 | `notify_url` varchar(1024) NOT NULL, |
| 42 | - `notify_status` tinyint(4) NOT NULL, | ||
| 43 | - `amount` bigint(20) NOT NULL, | 42 | + `price` bigint(20) NOT NULL, |
| 44 | `channel_fee_rate` double DEFAULT 0, | 43 | `channel_fee_rate` double DEFAULT 0, |
| 45 | - `channel_fee_amount` bigint(20) DEFAULT 0, | 44 | + `channel_fee_price` bigint(20) DEFAULT 0, |
| 46 | `status` tinyint(4) NOT NULL, | 45 | `status` tinyint(4) NOT NULL, |
| 47 | `user_ip` varchar(50) NOT NULL, | 46 | `user_ip` varchar(50) NOT NULL, |
| 48 | - `expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, | 47 | + `expire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 49 | `success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, | 48 | `success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, |
| 50 | `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, | 49 | `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, |
| 51 | - `success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号', | ||
| 52 | - `refund_status` tinyint(4) NOT NULL, | ||
| 53 | - `refund_times` tinyint(4) NOT NULL, | ||
| 54 | - `refund_amount` bigint(20) NOT NULL, | 50 | + `extension_id` bigint(20) DEFAULT NULL, |
| 51 | + `no` varchar(64) NULL, | ||
| 52 | + `refund_price` bigint(20) NOT NULL, | ||
| 55 | `channel_user_id` varchar(255) DEFAULT NULL, | 53 | `channel_user_id` varchar(255) DEFAULT NULL, |
| 56 | `channel_order_no` varchar(64) DEFAULT NULL, | 54 | `channel_order_no` varchar(64) DEFAULT NULL, |
| 57 | `creator` varchar(64) DEFAULT '', | 55 | `creator` varchar(64) DEFAULT '', |
| @@ -62,6 +60,26 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( | @@ -62,6 +60,26 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( | ||
| 62 | PRIMARY KEY ("id") | 60 | PRIMARY KEY ("id") |
| 63 | ) COMMENT = '支付订单'; | 61 | ) COMMENT = '支付订单'; |
| 64 | 62 | ||
| 63 | +CREATE TABLE IF NOT EXISTS `pay_order_extension` ( | ||
| 64 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | ||
| 65 | + `no` varchar(64) NOT NULL, | ||
| 66 | + `order_id` bigint(20) NOT NULL, | ||
| 67 | + `channel_id` bigint(20) NOT NULL, | ||
| 68 | + `channel_code` varchar(32) NOT NULL, | ||
| 69 | + `user_ip` varchar(50) NULL DEFAULT NULL, | ||
| 70 | + `status` tinyint(4) NOT NULL, | ||
| 71 | + `channel_extras` varchar(1024) NULL DEFAULT NULL, | ||
| 72 | + `channel_error_code` varchar(64) NULL, | ||
| 73 | + `channel_error_msg` varchar(64) NULL, | ||
| 74 | + `channel_notify_data` varchar(1024) NULL, | ||
| 75 | + `creator` varchar(64) NULL DEFAULT '', | ||
| 76 | + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| 77 | + `updater` varchar(64) NULL DEFAULT '', | ||
| 78 | + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| 79 | + `deleted` bit(1) NOT NULL DEFAULT FALSE, | ||
| 80 | + PRIMARY KEY ("id") | ||
| 81 | +) COMMENT = '支付订单拓展'; | ||
| 82 | + | ||
| 65 | CREATE TABLE IF NOT EXISTS `pay_refund` ( | 83 | CREATE TABLE IF NOT EXISTS `pay_refund` ( |
| 66 | "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | 84 | "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, |
| 67 | `app_id` bigint(20) NOT NULL, | 85 | `app_id` bigint(20) NOT NULL, |
yudao-ui-admin/src/api/pay/app.js
| 1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
| 2 | 2 | ||
| 3 | -// 创建支付应用信息 | 3 | +// 创建支付应用 |
| 4 | export function createApp(data) { | 4 | export function createApp(data) { |
| 5 | return request({ | 5 | return request({ |
| 6 | url: '/pay/app/create', | 6 | url: '/pay/app/create', |
| @@ -9,7 +9,7 @@ export function createApp(data) { | @@ -9,7 +9,7 @@ export function createApp(data) { | ||
| 9 | }) | 9 | }) |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | -// 更新支付应用信息 | 12 | +// 更新支付应用 |
| 13 | export function updateApp(data) { | 13 | export function updateApp(data) { |
| 14 | return request({ | 14 | return request({ |
| 15 | url: '/pay/app/update', | 15 | url: '/pay/app/update', |
| @@ -18,7 +18,7 @@ export function updateApp(data) { | @@ -18,7 +18,7 @@ export function updateApp(data) { | ||
| 18 | }) | 18 | }) |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | -// 支付应用信息状态修改 | 21 | +// 支付应用状态修改 |
| 22 | export function changeAppStatus(id, status) { | 22 | export function changeAppStatus(id, status) { |
| 23 | const data = { | 23 | const data = { |
| 24 | id, | 24 | id, |
| @@ -31,7 +31,7 @@ export function changeAppStatus(id, status) { | @@ -31,7 +31,7 @@ export function changeAppStatus(id, status) { | ||
| 31 | }) | 31 | }) |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | -// 删除支付应用信息 | 34 | +// 删除支付应用 |
| 35 | export function deleteApp(id) { | 35 | export function deleteApp(id) { |
| 36 | return request({ | 36 | return request({ |
| 37 | url: '/pay/app/delete?id=' + id, | 37 | url: '/pay/app/delete?id=' + id, |
| @@ -39,7 +39,7 @@ export function deleteApp(id) { | @@ -39,7 +39,7 @@ export function deleteApp(id) { | ||
| 39 | }) | 39 | }) |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | -// 获得支付应用信息 | 42 | +// 获得支付应用 |
| 43 | export function getApp(id) { | 43 | export function getApp(id) { |
| 44 | return request({ | 44 | return request({ |
| 45 | url: '/pay/app/get?id=' + id, | 45 | url: '/pay/app/get?id=' + id, |
| @@ -47,7 +47,7 @@ export function getApp(id) { | @@ -47,7 +47,7 @@ export function getApp(id) { | ||
| 47 | }) | 47 | }) |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | -// 获得支付应用信息分页 | 50 | +// 获得支付应用分页 |
| 51 | export function getAppPage(query) { | 51 | export function getAppPage(query) { |
| 52 | return request({ | 52 | return request({ |
| 53 | url: '/pay/app/page', | 53 | url: '/pay/app/page', |
| @@ -56,23 +56,10 @@ export function getAppPage(query) { | @@ -56,23 +56,10 @@ export function getAppPage(query) { | ||
| 56 | }) | 56 | }) |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | -// 导出支付应用信息 Excel | ||
| 60 | -export function exportAppExcel(query) { | 59 | +// 获得支付应用列表 |
| 60 | +export function getAppList() { | ||
| 61 | return request({ | 61 | return request({ |
| 62 | - url: '/pay/app/export-excel', | ||
| 63 | - method: 'get', | ||
| 64 | - params: query, | ||
| 65 | - responseType: 'blob' | ||
| 66 | - }) | ||
| 67 | -} | ||
| 68 | - | ||
| 69 | -// 根据商ID称搜索应用列表 | ||
| 70 | -export function getAppListByMerchantId(merchantId) { | ||
| 71 | - return request({ | ||
| 72 | - url: '/pay/app/list-merchant-id', | ||
| 73 | - params:{ | ||
| 74 | - merchantId:merchantId | ||
| 75 | - }, | 62 | + url: '/pay/app/list', |
| 76 | method: 'get' | 63 | method: 'get' |
| 77 | }) | 64 | }) |
| 78 | } | 65 | } |
yudao-ui-admin/src/api/pay/notify.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获得支付通知明细 | ||
| 4 | +export function getNotifyTaskDetail(id) { | ||
| 5 | + return request({ | ||
| 6 | + url: '/pay/notify/get-detail?id=' + id, | ||
| 7 | + method: 'get' | ||
| 8 | + }) | ||
| 9 | +} | ||
| 10 | + | ||
| 11 | +// 获得支付通知分页 | ||
| 12 | +export function getNotifyTaskPage(query) { | ||
| 13 | + return request({ | ||
| 14 | + url: '/pay/notify/page', | ||
| 15 | + method: 'get', | ||
| 16 | + params: query | ||
| 17 | + }) | ||
| 18 | +} |
yudao-ui-admin/src/utils/constants.js
| @@ -207,42 +207,6 @@ export const PayOrderStatusEnum = { | @@ -207,42 +207,6 @@ export const PayOrderStatusEnum = { | ||
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | /** | 209 | /** |
| 210 | - * 支付订单回调状态枚举 | ||
| 211 | - */ | ||
| 212 | -export const PayOrderNotifyStatusEnum = { | ||
| 213 | - NO: { | ||
| 214 | - status: 0, | ||
| 215 | - name: '未通知' | ||
| 216 | - }, | ||
| 217 | - SUCCESS: { | ||
| 218 | - status: 10, | ||
| 219 | - name: '通知成功' | ||
| 220 | - }, | ||
| 221 | - FAILURE: { | ||
| 222 | - status: 20, | ||
| 223 | - name: '通知失败' | ||
| 224 | - } | ||
| 225 | -} | ||
| 226 | - | ||
| 227 | -/** | ||
| 228 | - * 支付订单退款状态枚举 | ||
| 229 | - */ | ||
| 230 | -export const PayOrderRefundStatusEnum = { | ||
| 231 | - NO: { | ||
| 232 | - status: 0, | ||
| 233 | - name: '未退款' | ||
| 234 | - }, | ||
| 235 | - SOME: { | ||
| 236 | - status: 10, | ||
| 237 | - name: '部分退款' | ||
| 238 | - }, | ||
| 239 | - ALL: { | ||
| 240 | - status: 20, | ||
| 241 | - name: '全部退款' | ||
| 242 | - } | ||
| 243 | -} | ||
| 244 | - | ||
| 245 | -/** | ||
| 246 | * 支付退款订单状态枚举 | 210 | * 支付退款订单状态枚举 |
| 247 | */ | 211 | */ |
| 248 | export const PayRefundStatusEnum = { | 212 | export const PayRefundStatusEnum = { |
yudao-ui-admin/src/utils/dict.js
| @@ -51,15 +51,12 @@ export const DICT_TYPE = { | @@ -51,15 +51,12 @@ export const DICT_TYPE = { | ||
| 51 | 51 | ||
| 52 | // ========== PAY 模块 ========== | 52 | // ========== PAY 模块 ========== |
| 53 | PAY_CHANNEL_WECHAT_VERSION: 'pay_channel_wechat_version', // 微信渠道版本 | 53 | PAY_CHANNEL_WECHAT_VERSION: 'pay_channel_wechat_version', // 微信渠道版本 |
| 54 | - PAY_CHANNEL_ALIPAY_SIGN_TYPE: 'pay_channel_alipay_sign_type', // 支付渠道支付宝算法类型 | ||
| 55 | - PAY_CHANNEL_ALIPAY_MODE: 'pay_channel_alipay_mode', // 支付宝公钥类型 | ||
| 56 | - PAY_CHANNEL_ALIPAY_SERVER_TYPE: 'pay_channel_alipay_server_type', // 支付宝网关地址 | 54 | + |
| 57 | PAY_CHANNEL_CODE: 'pay_channel_code', // 支付渠道编码类型 | 55 | PAY_CHANNEL_CODE: 'pay_channel_code', // 支付渠道编码类型 |
| 58 | - PAY_ORDER_NOTIFY_STATUS: 'pay_order_notify_status', // 商户支付订单回调状态 | ||
| 59 | PAY_ORDER_STATUS: 'pay_order_status', // 商户支付订单状态 | 56 | PAY_ORDER_STATUS: 'pay_order_status', // 商户支付订单状态 |
| 60 | - PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status', // 商户支付订单退款状态 | ||
| 61 | - PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', // 退款订单状态 | ||
| 62 | - PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', // 退款订单类别 | 57 | + PAY_REFUND_STATUS: 'pay_refund_status', // 退款订单状态 |
| 58 | + PAY_NOTIFY_STATUS: 'pay_notify_status', // 商户支付回调状态 | ||
| 59 | + PAY_NOTIFY_TYPE: 'pay_notify_type', // 商户支付回调状态 | ||
| 63 | 60 | ||
| 64 | // ========== MP 模块 ========== | 61 | // ========== MP 模块 ========== |
| 65 | MP_AUTO_REPLY_REQUEST_MATCH: 'mp_auto_reply_request_match', // 自动回复请求匹配类型 | 62 | MP_AUTO_REPLY_REQUEST_MATCH: 'mp_auto_reply_request_match', // 自动回复请求匹配类型 |
yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue deleted
| 1 | -<template> | ||
| 2 | - <div> | ||
| 3 | - <el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px"> | ||
| 4 | - <el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px" | ||
| 5 | - v-loading="transferParam.loading"> | ||
| 6 | - <el-form-item label-width="180px" label="渠道费率" prop="feeRate"> | ||
| 7 | - <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}"> | ||
| 8 | - <template slot="append">%</template> | ||
| 9 | - </el-input> | ||
| 10 | - </el-form-item> | ||
| 11 | - <el-form-item label-width="180px" label="开放平台APPID" prop="aliPayConfig.appId"> | ||
| 12 | - <el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :style="{width: '100%'}"> | ||
| 13 | - </el-input> | ||
| 14 | - </el-form-item> | ||
| 15 | - <el-form-item label-width="180px" label="渠道状态" prop="status"> | ||
| 16 | - <el-radio-group v-model="form.status" size="medium"> | ||
| 17 | - <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | ||
| 18 | - {{ dict.label }} | ||
| 19 | - </el-radio> | ||
| 20 | - </el-radio-group> | ||
| 21 | - </el-form-item> | ||
| 22 | - <el-form-item label-width="180px" label="网关地址" prop="aliPayConfig.serverUrl"> | ||
| 23 | - <el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium"> | ||
| 24 | - <el-radio v-for="dict in aliPayServerDatas" :key="dict.value" :label="dict.value"> | ||
| 25 | - {{ dict.label }} | ||
| 26 | - </el-radio> | ||
| 27 | - </el-radio-group> | ||
| 28 | - </el-form-item> | ||
| 29 | - <el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType"> | ||
| 30 | - <el-radio-group v-model="form.aliPayConfig.signType" size="medium"> | ||
| 31 | - <el-radio v-for="dict in aliPaySignTypeDatas" :key="dict.value" :label="dict.value"> | ||
| 32 | - {{ dict.label }} | ||
| 33 | - </el-radio> | ||
| 34 | - </el-radio-group> | ||
| 35 | - </el-form-item> | ||
| 36 | - <el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode"> | ||
| 37 | - <el-radio-group v-model="form.aliPayConfig.mode" size="medium"> | ||
| 38 | - <el-radio v-for="dict in aliPayModeDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | ||
| 39 | - {{ dict.label }} | ||
| 40 | - </el-radio> | ||
| 41 | - </el-radio-group> | ||
| 42 | - </el-form-item> | ||
| 43 | - <div v-if="form.aliPayConfig.mode === 1"> | ||
| 44 | - <el-form-item label-width="180px" label="应用私钥" prop="aliPayConfig.privateKey"> | ||
| 45 | - <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey" | ||
| 46 | - placeholder="请输入应用私钥" clearable :style="{width: '100%'}"> | ||
| 47 | - </el-input> | ||
| 48 | - </el-form-item> | ||
| 49 | - <el-form-item label-width="180px" label="支付宝公钥" prop="aliPayConfig.alipayPublicKey"> | ||
| 50 | - <el-input | ||
| 51 | - type="textarea" | ||
| 52 | - :autosize="{minRows: 8, maxRows: 8}" | ||
| 53 | - v-model="form.aliPayConfig.alipayPublicKey" | ||
| 54 | - placeholder="请输入支付宝公钥" clearable | ||
| 55 | - :style="{width: '100%'}"> | ||
| 56 | - </el-input> | ||
| 57 | - </el-form-item> | ||
| 58 | - </div> | ||
| 59 | - <div v-if="form.aliPayConfig.mode === 2"> | ||
| 60 | - <el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent"> | ||
| 61 | - <el-input v-model="form.aliPayConfig.appCertContent" type="textarea" | ||
| 62 | - placeholder="请上传商户公钥应用证书" | ||
| 63 | - readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | ||
| 64 | - </el-form-item> | ||
| 65 | - <el-form-item label-width="180px" label=""> | ||
| 66 | - <el-upload | ||
| 67 | - action="" | ||
| 68 | - ref="privateKeyContentFile" | ||
| 69 | - :limit="1" | ||
| 70 | - :accept="fileAccept" | ||
| 71 | - :http-request="appCertUpload" | ||
| 72 | - :before-upload="fileBeforeUpload"> | ||
| 73 | - <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | ||
| 74 | - </el-upload> | ||
| 75 | - </el-form-item> | ||
| 76 | - <el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent"> | ||
| 77 | - <el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea" | ||
| 78 | - placeholder="请上传支付宝公钥证书" | ||
| 79 | - readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | ||
| 80 | - </el-form-item> | ||
| 81 | - <el-form-item label-width="180px" label=""> | ||
| 82 | - <el-upload | ||
| 83 | - ref="privateCertContentFile" | ||
| 84 | - action="" | ||
| 85 | - :limit="1" | ||
| 86 | - :accept="fileAccept" | ||
| 87 | - :before-upload="fileBeforeUpload" | ||
| 88 | - :http-request="alipayPublicCertUpload"> | ||
| 89 | - <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | ||
| 90 | - </el-upload> | ||
| 91 | - </el-form-item> | ||
| 92 | - <el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent"> | ||
| 93 | - <el-input | ||
| 94 | - v-model="form.aliPayConfig.rootCertContent" | ||
| 95 | - type="textarea" | ||
| 96 | - placeholder="请上传根证书" | ||
| 97 | - readonly :autosize="{minRows: 8, maxRows: 8}" | ||
| 98 | - :style="{width: '100%'}"> | ||
| 99 | - </el-input> | ||
| 100 | - </el-form-item> | ||
| 101 | - <el-form-item label-width="180px" label=""> | ||
| 102 | - <el-upload | ||
| 103 | - ref="privateCertContentFile" | ||
| 104 | - :limit="1" | ||
| 105 | - :accept="fileAccept" | ||
| 106 | - action="" | ||
| 107 | - :before-upload="fileBeforeUpload" | ||
| 108 | - :http-request="rootCertUpload"> | ||
| 109 | - <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | ||
| 110 | - </el-upload> | ||
| 111 | - </el-form-item> | ||
| 112 | - </div> | ||
| 113 | - <el-form-item label-width="180px" label="备注" prop="remark"> | ||
| 114 | - <el-input v-model="form.remark" :style="{width: '100%'}"></el-input> | ||
| 115 | - </el-form-item> | ||
| 116 | - </el-form> | ||
| 117 | - <div slot="footer" class="dialog-footer"> | ||
| 118 | - <el-button @click="close">取消</el-button> | ||
| 119 | - <el-button type="primary" @click="handleConfirm">确定</el-button> | ||
| 120 | - </div> | ||
| 121 | - </el-dialog> | ||
| 122 | - </div> | ||
| 123 | -</template> | ||
| 124 | -<script> | ||
| 125 | -import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | ||
| 126 | -import {createChannel, getChannel, updateChannel} from "@/api/pay/channel"; | ||
| 127 | - | ||
| 128 | -const defaultForm = { | ||
| 129 | - code: '', | ||
| 130 | - status: null, | ||
| 131 | - remark: '', | ||
| 132 | - feeRate: null, | ||
| 133 | - appId: '', | ||
| 134 | - aliPayConfig: { | ||
| 135 | - appId: '', | ||
| 136 | - serverUrl: null, | ||
| 137 | - signType: '', | ||
| 138 | - mode: null, | ||
| 139 | - privateKey: '', | ||
| 140 | - alipayPublicKey: '', | ||
| 141 | - appCertContent: '', | ||
| 142 | - alipayPublicCertContent: '', | ||
| 143 | - rootCertContent: '' | ||
| 144 | - } | ||
| 145 | -}; | ||
| 146 | - | ||
| 147 | -export default { | ||
| 148 | - name: "aliPayChannelForm", | ||
| 149 | - components: {}, | ||
| 150 | - props: { | ||
| 151 | - // 传输的参数 | ||
| 152 | - transferParam: { | ||
| 153 | - // 加载动画 | ||
| 154 | - "loading": false, | ||
| 155 | - // 是否修改 | ||
| 156 | - "edit": false, | ||
| 157 | - // 是否显示 | ||
| 158 | - "aliPayOpen": false, | ||
| 159 | - // 应用ID | ||
| 160 | - "appId": null, | ||
| 161 | - // 渠道编码 | ||
| 162 | - "payCode": null, | ||
| 163 | - } | ||
| 164 | - }, | ||
| 165 | - data() { | ||
| 166 | - return { | ||
| 167 | - title:'', | ||
| 168 | - form: JSON.parse(JSON.stringify(defaultForm)), | ||
| 169 | - rules: { | ||
| 170 | - feeRate: [{ | ||
| 171 | - required: true, | ||
| 172 | - message: '请输入渠道费率', | ||
| 173 | - trigger: 'blur' | ||
| 174 | - }], | ||
| 175 | - 'aliPayConfig.appId': [{ | ||
| 176 | - required: true, | ||
| 177 | - message: '请输入开放平台上创建的应用的 ID', | ||
| 178 | - trigger: 'blur' | ||
| 179 | - }], | ||
| 180 | - status: [{ | ||
| 181 | - required: true, | ||
| 182 | - message: '渠道状态不能为空', | ||
| 183 | - trigger: 'blur' | ||
| 184 | - }], | ||
| 185 | - 'aliPayConfig.serverUrl': [{ | ||
| 186 | - required: true, | ||
| 187 | - message: '请传入网关地址', | ||
| 188 | - trigger: 'blur' | ||
| 189 | - }], | ||
| 190 | - 'aliPayConfig.signType': [{ | ||
| 191 | - required: true, | ||
| 192 | - message: '请传入签名算法类型', | ||
| 193 | - trigger: 'blur' | ||
| 194 | - }], | ||
| 195 | - 'aliPayConfig.mode': [{ | ||
| 196 | - required: true, | ||
| 197 | - message: '公钥类型不能为空', | ||
| 198 | - trigger: 'blur' | ||
| 199 | - }], | ||
| 200 | - 'aliPayConfig.privateKey': [{ | ||
| 201 | - required: true, | ||
| 202 | - message: '请输入商户私钥', | ||
| 203 | - trigger: 'blur' | ||
| 204 | - }], | ||
| 205 | - 'aliPayConfig.alipayPublicKey': [{ | ||
| 206 | - required: true, | ||
| 207 | - message: '请输入支付宝公钥字符串', | ||
| 208 | - trigger: 'blur' | ||
| 209 | - }], | ||
| 210 | - 'aliPayConfig.appCertContent': [{ | ||
| 211 | - required: true, | ||
| 212 | - message: '请上传商户公钥应用证书', | ||
| 213 | - trigger: 'blur' | ||
| 214 | - }], | ||
| 215 | - 'aliPayConfig.alipayPublicCertContent': [{ | ||
| 216 | - required: true, | ||
| 217 | - message: '请上传支付宝公钥证书', | ||
| 218 | - trigger: 'blur' | ||
| 219 | - }], | ||
| 220 | - 'aliPayConfig.rootCertContent': [{ | ||
| 221 | - required: true, | ||
| 222 | - message: '请上传指定根证书', | ||
| 223 | - trigger: 'blur' | ||
| 224 | - }], | ||
| 225 | - }, | ||
| 226 | - fileAccept: ".crt", | ||
| 227 | - // 渠道状态 数据字典 | ||
| 228 | - statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS), | ||
| 229 | - // 支付宝加密方式 | ||
| 230 | - aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE), | ||
| 231 | - // 版本状态 数据字典 | ||
| 232 | - aliPayModeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_MODE), | ||
| 233 | - // 支付宝网关地址 | ||
| 234 | - aliPayServerDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SERVER_TYPE), | ||
| 235 | - } | ||
| 236 | - }, | ||
| 237 | - watch: { | ||
| 238 | - transferParam: { | ||
| 239 | - deep: true, // 深度监听 | ||
| 240 | - handler(newVal) { | ||
| 241 | - if (newVal.aliPayOpen) { | ||
| 242 | - this.form.code = newVal.payCode; | ||
| 243 | - this.form.appId = newVal.appId; | ||
| 244 | - // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据 | ||
| 245 | - if (newVal.edit === true && newVal.loading) { | ||
| 246 | - this.title = "编辑支付渠道"; | ||
| 247 | - this.init(); | ||
| 248 | - } else { | ||
| 249 | - this.title = "创建支付渠道"; | ||
| 250 | - } | ||
| 251 | - } | ||
| 252 | - } | ||
| 253 | - } | ||
| 254 | - }, | ||
| 255 | - | ||
| 256 | - methods: { | ||
| 257 | - init() { | ||
| 258 | - getChannel(this.transferParam.appId, this.transferParam.payCode) | ||
| 259 | - .then(response => { | ||
| 260 | - this.form.id = response.data.id; | ||
| 261 | - this.form.feeRate = response.data.feeRate; | ||
| 262 | - this.form.status = response.data.status; | ||
| 263 | - this.form.remark = response.data.remark; | ||
| 264 | - | ||
| 265 | - let config = JSON.parse(response.data.config); | ||
| 266 | - this.form.aliPayConfig.appId = config.appId; | ||
| 267 | - this.form.aliPayConfig.serverUrl = config.serverUrl; | ||
| 268 | - this.form.aliPayConfig.signType = config.signType; | ||
| 269 | - this.form.aliPayConfig.mode = config.mode; | ||
| 270 | - this.form.aliPayConfig.privateKey = config.privateKey; | ||
| 271 | - this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey; | ||
| 272 | - this.form.aliPayConfig.appCertContent = config.appCertContent; | ||
| 273 | - this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent; | ||
| 274 | - this.form.aliPayConfig.rootCertContent = config.rootCertContent; | ||
| 275 | - this.transferParam.loading = false; | ||
| 276 | - }) | ||
| 277 | - }, | ||
| 278 | - close() { | ||
| 279 | - this.transferParam.aliPayOpen = false; | ||
| 280 | - this.form = JSON.parse(JSON.stringify(defaultForm)); | ||
| 281 | - }, | ||
| 282 | - handleConfirm() { | ||
| 283 | - this.$refs['aliPayForm'].validate(valid => { | ||
| 284 | - if (!valid) { | ||
| 285 | - return | ||
| 286 | - } | ||
| 287 | - let data = this.form; | ||
| 288 | - data.config = JSON.stringify(this.form.aliPayConfig); | ||
| 289 | - if (this.transferParam.edit) { | ||
| 290 | - updateChannel(data).then(response => { | ||
| 291 | - if (response.code === 0) { | ||
| 292 | - this.$modal.msgSuccess("修改成功"); | ||
| 293 | - this.close(); | ||
| 294 | - } | ||
| 295 | - | ||
| 296 | - }) | ||
| 297 | - } else { | ||
| 298 | - | ||
| 299 | - createChannel(data).then(response => { | ||
| 300 | - if (response.code === 0) { | ||
| 301 | - this.$modal.msgSuccess("新增成功"); | ||
| 302 | - this.$parent.refreshTable(); | ||
| 303 | - this.close(); | ||
| 304 | - } | ||
| 305 | - }); | ||
| 306 | - } | ||
| 307 | - }); | ||
| 308 | - }, | ||
| 309 | - fileBeforeUpload(file) { | ||
| 310 | - let format = '.' + file.name.split(".")[1]; | ||
| 311 | - if (format !== this.fileAccept) { | ||
| 312 | - this.$message.error('请上传指定格式"' + this.fileAccept + '"文件'); | ||
| 313 | - return false; | ||
| 314 | - } | ||
| 315 | - let isRightSize = file.size / 1024 / 1024 < 2 | ||
| 316 | - if (!isRightSize) { | ||
| 317 | - this.$message.error('文件大小超过 2MB') | ||
| 318 | - } | ||
| 319 | - return isRightSize | ||
| 320 | - }, | ||
| 321 | - appCertUpload(event) { | ||
| 322 | - const readFile = new FileReader() | ||
| 323 | - readFile.onload = (e) => { | ||
| 324 | - this.form.aliPayConfig.appCertContent = e.target.result | ||
| 325 | - } | ||
| 326 | - readFile.readAsText(event.file); | ||
| 327 | - }, | ||
| 328 | - alipayPublicCertUpload(event) { | ||
| 329 | - const readFile = new FileReader() | ||
| 330 | - readFile.onload = (e) => { | ||
| 331 | - this.form.aliPayConfig.alipayPublicCertContent = e.target.result | ||
| 332 | - } | ||
| 333 | - readFile.readAsText(event.file); | ||
| 334 | - }, | ||
| 335 | - rootCertUpload(event) { | ||
| 336 | - const readFile = new FileReader() | ||
| 337 | - readFile.onload = (e) => { | ||
| 338 | - this.form.aliPayConfig.rootCertContent = e.target.result | ||
| 339 | - } | ||
| 340 | - readFile.readAsText(event.file); | ||
| 341 | - }, | ||
| 342 | - | ||
| 343 | - } | ||
| 344 | -} | ||
| 345 | - | ||
| 346 | -</script> | ||
| 347 | -<style scoped> | ||
| 348 | - | ||
| 349 | -</style> |
yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div> | ||
| 3 | + <el-dialog :visible.sync="dialogVisible" :title="title" @closed="close" append-to-body width="800px"> | ||
| 4 | + <el-form ref="form" :model="formData" :rules="rules" size="medium" label-width="100px" v-loading="formLoading"> | ||
| 5 | + <el-form-item label-width="180px" label="渠道费率" prop="feeRate"> | ||
| 6 | + <el-input v-model="formData.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}"> | ||
| 7 | + <template slot="append">%</template> | ||
| 8 | + </el-input> | ||
| 9 | + </el-form-item> | ||
| 10 | + <el-form-item label-width="180px" label="开放平台 APPID" prop="config.appId"> | ||
| 11 | + <el-input v-model="formData.config.appId" placeholder="请输入开放平台 APPID" clearable :style="{width: '100%'}"> | ||
| 12 | + </el-input> | ||
| 13 | + </el-form-item> | ||
| 14 | + <el-form-item label-width="180px" label="渠道状态" prop="status"> | ||
| 15 | + <el-radio-group v-model="formData.status" size="medium"> | ||
| 16 | + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" | ||
| 17 | + :label="parseInt(dict.value)"> | ||
| 18 | + {{ dict.label }} | ||
| 19 | + </el-radio> | ||
| 20 | + </el-radio-group> | ||
| 21 | + </el-form-item> | ||
| 22 | + <el-form-item label-width="180px" label="网关地址" prop="config.serverUrl"> | ||
| 23 | + <el-radio-group v-model="formData.config.serverUrl" size="medium"> | ||
| 24 | + <el-radio label="https://openapi.alipay.com/gateway.do">线上环境</el-radio> | ||
| 25 | + <el-radio label="https://openapi-sandbox.dl.alipaydev.com/gateway.do">沙箱环境</el-radio> | ||
| 26 | + </el-radio-group> | ||
| 27 | + </el-form-item> | ||
| 28 | + <el-form-item label-width="180px" label="算法类型" prop="config.signType"> | ||
| 29 | + <el-radio-group v-model="formData.config.signType" size="medium"> | ||
| 30 | + <el-radio key="RSA2" label="RSA2">RSA2</el-radio> | ||
| 31 | + </el-radio-group> | ||
| 32 | + </el-form-item> | ||
| 33 | + <el-form-item label-width="180px" label="公钥类型" prop="config.mode"> | ||
| 34 | + <el-radio-group v-model="formData.config.mode" size="medium"> | ||
| 35 | + <el-radio key="公钥模式" :label="1">公钥模式</el-radio> | ||
| 36 | + <el-radio key="证书模式" :label="2">证书模式</el-radio> | ||
| 37 | + </el-radio-group> | ||
| 38 | + </el-form-item> | ||
| 39 | + <div v-if="formData.config.mode === 1"> | ||
| 40 | + <el-form-item label-width="180px" label="应用私钥" prop="config.privateKey"> | ||
| 41 | + <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="formData.config.privateKey" | ||
| 42 | + placeholder="请输入应用私钥" clearable :style="{width: '100%'}"> | ||
| 43 | + </el-input> | ||
| 44 | + </el-form-item> | ||
| 45 | + <el-form-item label-width="180px" label="支付宝公钥" prop="config.alipayPublicKey"> | ||
| 46 | + <el-input | ||
| 47 | + type="textarea" | ||
| 48 | + :autosize="{minRows: 8, maxRows: 8}" | ||
| 49 | + v-model="formData.config.alipayPublicKey" | ||
| 50 | + placeholder="请输入支付宝公钥" clearable | ||
| 51 | + :style="{width: '100%'}"> | ||
| 52 | + </el-input> | ||
| 53 | + </el-form-item> | ||
| 54 | + </div> | ||
| 55 | + <div v-if="formData.config.mode === 2"> | ||
| 56 | + <el-form-item label-width="180px" label="商户公钥应用证书" prop="config.appCertContent"> | ||
| 57 | + <el-input v-model="formData.config.appCertContent" type="textarea" | ||
| 58 | + placeholder="请上传商户公钥应用证书" | ||
| 59 | + readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | ||
| 60 | + </el-form-item> | ||
| 61 | + <el-form-item label-width="180px" label=""> | ||
| 62 | + <el-upload | ||
| 63 | + action="" | ||
| 64 | + ref="privateKeyContentFile" | ||
| 65 | + :limit="1" | ||
| 66 | + :accept="fileAccept" | ||
| 67 | + :http-request="appCertUpload" | ||
| 68 | + :before-upload="fileBeforeUpload"> | ||
| 69 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | ||
| 70 | + </el-upload> | ||
| 71 | + </el-form-item> | ||
| 72 | + <el-form-item label-width="180px" label="支付宝公钥证书" prop="config.alipayPublicCertContent"> | ||
| 73 | + <el-input v-model="formData.config.alipayPublicCertContent" type="textarea" | ||
| 74 | + placeholder="请上传支付宝公钥证书" | ||
| 75 | + readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | ||
| 76 | + </el-form-item> | ||
| 77 | + <el-form-item label-width="180px" label=""> | ||
| 78 | + <el-upload | ||
| 79 | + ref="privateCertContentFile" | ||
| 80 | + action="" | ||
| 81 | + :limit="1" | ||
| 82 | + :accept="fileAccept" | ||
| 83 | + :before-upload="fileBeforeUpload" | ||
| 84 | + :http-request="alipayPublicCertUpload"> | ||
| 85 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | ||
| 86 | + </el-upload> | ||
| 87 | + </el-form-item> | ||
| 88 | + <el-form-item label-width="180px" label="根证书" prop="config.rootCertContent"> | ||
| 89 | + <el-input | ||
| 90 | + v-model="formData.config.rootCertContent" | ||
| 91 | + type="textarea" | ||
| 92 | + placeholder="请上传根证书" | ||
| 93 | + readonly :autosize="{minRows: 8, maxRows: 8}" | ||
| 94 | + :style="{width: '100%'}"> | ||
| 95 | + </el-input> | ||
| 96 | + </el-form-item> | ||
| 97 | + <el-form-item label-width="180px" label=""> | ||
| 98 | + <el-upload | ||
| 99 | + ref="privateCertContentFile" | ||
| 100 | + :limit="1" | ||
| 101 | + :accept="fileAccept" | ||
| 102 | + action="" | ||
| 103 | + :before-upload="fileBeforeUpload" | ||
| 104 | + :http-request="rootCertUpload"> | ||
| 105 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | ||
| 106 | + </el-upload> | ||
| 107 | + </el-form-item> | ||
| 108 | + </div> | ||
| 109 | + <el-form-item label-width="180px" label="备注" prop="remark"> | ||
| 110 | + <el-input v-model="formData.remark" :style="{width: '100%'}"></el-input> | ||
| 111 | + </el-form-item> | ||
| 112 | + </el-form> | ||
| 113 | + <div slot="footer" class="dialog-footer"> | ||
| 114 | + <el-button @click="close">取消</el-button> | ||
| 115 | + <el-button type="primary" @click="submitForm">确定</el-button> | ||
| 116 | + </div> | ||
| 117 | + </el-dialog> | ||
| 118 | + </div> | ||
| 119 | +</template> | ||
| 120 | +<script> | ||
| 121 | +import { createChannel, getChannel, updateChannel } from "@/api/pay/channel"; | ||
| 122 | +import { CommonStatusEnum } from "@/utils/constants"; | ||
| 123 | + | ||
| 124 | +export default { | ||
| 125 | + name: "alipayChannelForm", | ||
| 126 | + data() { | ||
| 127 | + return { | ||
| 128 | + dialogVisible: false, | ||
| 129 | + formLoading: false, | ||
| 130 | + title:'', | ||
| 131 | + formData: { | ||
| 132 | + appId: '', | ||
| 133 | + code: '', | ||
| 134 | + status: undefined, | ||
| 135 | + feeRate: undefined, | ||
| 136 | + remark: '', | ||
| 137 | + config: { | ||
| 138 | + appId: '', | ||
| 139 | + serverUrl: null, | ||
| 140 | + signType: '', | ||
| 141 | + mode: null, | ||
| 142 | + privateKey: '', | ||
| 143 | + alipayPublicKey: '', | ||
| 144 | + appCertContent: '', | ||
| 145 | + alipayPublicCertContent: '', | ||
| 146 | + rootCertContent: '' | ||
| 147 | + } | ||
| 148 | + }, | ||
| 149 | + rules: { | ||
| 150 | + feeRate: [{ required: true, message: '请输入渠道费率', trigger: 'blur' }], | ||
| 151 | + status: [{ required: true, message: '渠道状态不能为空', trigger: 'blur' }], | ||
| 152 | + 'config.appId': [{ required: true, message: '请输入开放平台上创建的应用的 ID', trigger: 'blur' }], | ||
| 153 | + 'config.serverUrl': [{ required: true, message: '请传入网关地址', trigger: 'blur' }], | ||
| 154 | + 'config.signType': [{ required: true, message: '请传入签名算法类型', trigger: 'blur' }], | ||
| 155 | + 'config.mode': [{ required: true, message: '公钥类型不能为空', trigger: 'blur'}], | ||
| 156 | + 'config.privateKey': [{ required: true, message: '请输入商户私钥', trigger: 'blur' }], | ||
| 157 | + 'config.alipayPublicKey': [{ required: true, message: '请输入支付宝公钥字符串', trigger: 'blur' }], | ||
| 158 | + 'config.appCertContent': [{ required: true, message: '请上传商户公钥应用证书', trigger: 'blur' }], | ||
| 159 | + 'config.alipayPublicCertContent': [{ required: true, message: '请上传支付宝公钥证书', trigger: 'blur'}], | ||
| 160 | + 'config.rootCertContent': [{ required: true, message: '请上传指定根证书', trigger: 'blur' }], | ||
| 161 | + }, | ||
| 162 | + fileAccept: ".crt", | ||
| 163 | + } | ||
| 164 | + }, | ||
| 165 | + methods: { | ||
| 166 | + open(appId, code) { | ||
| 167 | + this.dialogVisible = true; | ||
| 168 | + this.formLoading = true; | ||
| 169 | + this.reset(appId, code); | ||
| 170 | + getChannel(appId, code).then(response => { | ||
| 171 | + if (response.data && response.data.id) { | ||
| 172 | + this.formData = response.data; | ||
| 173 | + this.formData.config = JSON.parse(response.data.config); | ||
| 174 | + } | ||
| 175 | + this.title = this.formData.id ? '创建支付渠道' : '编辑支付渠道' | ||
| 176 | + }).finally(() => { | ||
| 177 | + this.formLoading = false; | ||
| 178 | + }); | ||
| 179 | + }, | ||
| 180 | + close() { | ||
| 181 | + this.dialogVisible = false; | ||
| 182 | + this.reset(undefined, undefined); | ||
| 183 | + }, | ||
| 184 | + submitForm() { | ||
| 185 | + this.$refs['form'].validate(valid => { | ||
| 186 | + if (!valid) { | ||
| 187 | + return | ||
| 188 | + } | ||
| 189 | + const data = { ...this.formData }; | ||
| 190 | + data.config = JSON.stringify(this.formData.config); | ||
| 191 | + if (!data.id) { | ||
| 192 | + createChannel(data).then(response => { | ||
| 193 | + this.$modal.msgSuccess("新增成功"); | ||
| 194 | + this.$emit('success') | ||
| 195 | + this.close(); | ||
| 196 | + }); | ||
| 197 | + } else { | ||
| 198 | + updateChannel(data).then(response => { | ||
| 199 | + this.$modal.msgSuccess("修改成功"); | ||
| 200 | + this.$emit('success') | ||
| 201 | + this.close(); | ||
| 202 | + }) | ||
| 203 | + } | ||
| 204 | + }); | ||
| 205 | + }, | ||
| 206 | + /** 重置表单 */ | ||
| 207 | + reset(appId, code) { | ||
| 208 | + this.formData = { | ||
| 209 | + appId: appId, | ||
| 210 | + code: code, | ||
| 211 | + status: CommonStatusEnum.ENABLE, | ||
| 212 | + remark: '', | ||
| 213 | + feeRate: null, | ||
| 214 | + config: { | ||
| 215 | + appId: '', | ||
| 216 | + serverUrl: null, | ||
| 217 | + signType: 'RSA2', | ||
| 218 | + mode: null, | ||
| 219 | + privateKey: '', | ||
| 220 | + alipayPublicKey: '', | ||
| 221 | + appCertContent: '', | ||
| 222 | + alipayPublicCertContent: '', | ||
| 223 | + rootCertContent: '' | ||
| 224 | + } | ||
| 225 | + } | ||
| 226 | + this.resetForm('form') | ||
| 227 | + }, | ||
| 228 | + fileBeforeUpload(file) { | ||
| 229 | + let format = '.' + file.name.split(".")[1]; | ||
| 230 | + if (format !== this.fileAccept) { | ||
| 231 | + this.$message.error('请上传指定格式"' + this.fileAccept + '"文件'); | ||
| 232 | + return false; | ||
| 233 | + } | ||
| 234 | + let isRightSize = file.size / 1024 / 1024 < 2 | ||
| 235 | + if (!isRightSize) { | ||
| 236 | + this.$message.error('文件大小超过 2MB') | ||
| 237 | + } | ||
| 238 | + return isRightSize | ||
| 239 | + }, | ||
| 240 | + appCertUpload(event) { | ||
| 241 | + const readFile = new FileReader() | ||
| 242 | + readFile.onload = (e) => { | ||
| 243 | + this.formData.config.appCertContent = e.target.result | ||
| 244 | + } | ||
| 245 | + readFile.readAsText(event.file); | ||
| 246 | + }, | ||
| 247 | + alipayPublicCertUpload(event) { | ||
| 248 | + const readFile = new FileReader() | ||
| 249 | + readFile.onload = (e) => { | ||
| 250 | + this.formData.config.alipayPublicCertContent = e.target.result | ||
| 251 | + } | ||
| 252 | + readFile.readAsText(event.file); | ||
| 253 | + }, | ||
| 254 | + rootCertUpload(event) { | ||
| 255 | + const readFile = new FileReader() | ||
| 256 | + readFile.onload = (e) => { | ||
| 257 | + this.formData.config.rootCertContent = e.target.result | ||
| 258 | + } | ||
| 259 | + readFile.readAsText(event.file); | ||
| 260 | + }, | ||
| 261 | + | ||
| 262 | + } | ||
| 263 | +} | ||
| 264 | + | ||
| 265 | +</script> | ||
| 266 | +<style scoped> | ||
| 267 | + | ||
| 268 | +</style> |
yudao-ui-admin/src/views/pay/app/index.vue
| @@ -213,8 +213,10 @@ | @@ -213,8 +213,10 @@ | ||
| 213 | <el-button @click="cancel">取 消</el-button> | 213 | <el-button @click="cancel">取 消</el-button> |
| 214 | </div> | 214 | </div> |
| 215 | </el-dialog> | 215 | </el-dialog> |
| 216 | - <wechat-channel-form :transferParam="channelParam"></wechat-channel-form> | ||
| 217 | - <ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form> | 216 | + |
| 217 | + <!-- 弹窗 --> | ||
| 218 | + <wechat-channel-form :transferParam="channelParam" /> | ||
| 219 | + <alipay-channel-form ref="alipayChannelFormRef" @success="getList" /> | ||
| 218 | </div> | 220 | </div> |
| 219 | </template> | 221 | </template> |
| 220 | 222 | ||
| @@ -223,13 +225,13 @@ import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage } | @@ -223,13 +225,13 @@ import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage } | ||
| 223 | import { DICT_TYPE, getDictDatas } from "@/utils/dict"; | 225 | import { DICT_TYPE, getDictDatas } from "@/utils/dict"; |
| 224 | import { PayType, PayChannelEnum, CommonStatusEnum } from "@/utils/constants"; | 226 | import { PayType, PayChannelEnum, CommonStatusEnum } from "@/utils/constants"; |
| 225 | import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm"; | 227 | import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm"; |
| 226 | -import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm"; | 228 | +import alipayChannelForm from "@/views/pay/app/components/alipayChannelForm"; |
| 227 | 229 | ||
| 228 | export default { | 230 | export default { |
| 229 | name: "PayApp", | 231 | name: "PayApp", |
| 230 | components: { | 232 | components: { |
| 231 | "wechatChannelForm": wechatChannelForm, | 233 | "wechatChannelForm": wechatChannelForm, |
| 232 | - "aliPayChannelForm": aliPayChannelForm | 234 | + "alipayChannelForm": alipayChannelForm |
| 233 | }, | 235 | }, |
| 234 | data() { | 236 | data() { |
| 235 | return { | 237 | return { |
| @@ -283,13 +285,6 @@ export default { | @@ -283,13 +285,6 @@ export default { | ||
| 283 | "appId": null, | 285 | "appId": null, |
| 284 | // 渠道编码 | 286 | // 渠道编码 |
| 285 | "payCode": null, | 287 | "payCode": null, |
| 286 | - // 商户对象 | ||
| 287 | - "payMerchant": { | ||
| 288 | - // 编号 | ||
| 289 | - "id": null, | ||
| 290 | - // 名称 | ||
| 291 | - "name": null | ||
| 292 | - }, | ||
| 293 | } | 288 | } |
| 294 | }; | 289 | }; |
| 295 | }, | 290 | }, |
| @@ -424,14 +419,12 @@ export default { | @@ -424,14 +419,12 @@ export default { | ||
| 424 | this.channelParam.aliPayOpen = false; | 419 | this.channelParam.aliPayOpen = false; |
| 425 | } | 420 | } |
| 426 | if (type === PayType.ALIPAY) { | 421 | if (type === PayType.ALIPAY) { |
| 427 | - this.channelParam.aliPayOpen = true; | ||
| 428 | - this.channelParam.wechatOpen = false; | 422 | + console.log(this.$refs['alipayChannelFormRef']) |
| 423 | + this.$refs['alipayChannelFormRef'].open(row.id, payCode); | ||
| 424 | + return; | ||
| 425 | + // this.channelParam.aliPayOpen = true; | ||
| 426 | + // this.channelParam.wechatOpen = false; | ||
| 429 | } | 427 | } |
| 430 | - this.channelParam.edit = false; | ||
| 431 | - this.channelParam.loading = false; | ||
| 432 | - this.channelParam.appId = row.id; | ||
| 433 | - this.channelParam.payCode = payCode; | ||
| 434 | - this.channelParam.payMerchant = row.payMerchant; | ||
| 435 | }, | 428 | }, |
| 436 | /** | 429 | /** |
| 437 | * 根据渠道编码判断渠道列表中是否存在 | 430 | * 根据渠道编码判断渠道列表中是否存在 |
yudao-ui-admin/src/views/pay/notify/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="app-container"> | ||
| 3 | + | ||
| 4 | + <!-- 搜索工作栏 --> | ||
| 5 | + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px"> | ||
| 6 | + <el-form-item label="应用编号" prop="appId"> | ||
| 7 | + <el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息"> | ||
| 8 | + <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" /> | ||
| 9 | + </el-select> | ||
| 10 | + </el-form-item> | ||
| 11 | + <el-form-item label="通知类型" prop="type"> | ||
| 12 | + <el-select v-model="queryParams.type" placeholder="请选择通知类型" clearable size="small"> | ||
| 13 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_NOTIFY_TYPE)" | ||
| 14 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 15 | + </el-select> | ||
| 16 | + </el-form-item> | ||
| 17 | + <el-form-item label="关联编号" prop="dataId"> | ||
| 18 | + <el-input v-model="queryParams.dataId" placeholder="请输入关联编号" clearable @keyup.enter.native="handleQuery"/> | ||
| 19 | + </el-form-item> | ||
| 20 | + <el-form-item label="通知状态" prop="status"> | ||
| 21 | + <el-select v-model="queryParams.status" placeholder="请选择通知状态" clearable size="small"> | ||
| 22 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_NOTIFY_STATUS)" | ||
| 23 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 24 | + </el-select> | ||
| 25 | + </el-form-item> | ||
| 26 | + <el-form-item label="商户订单编号" prop="merchantOrderId"> | ||
| 27 | + <el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户订单编号" clearable @keyup.enter.native="handleQuery"/> | ||
| 28 | + </el-form-item> | ||
| 29 | + <el-form-item label="创建时间" prop="createTime"> | ||
| 30 | + <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" | ||
| 31 | + range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" /> | ||
| 32 | + </el-form-item> | ||
| 33 | + <el-form-item> | ||
| 34 | + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | ||
| 35 | + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> | ||
| 36 | + </el-form-item> | ||
| 37 | + </el-form> | ||
| 38 | + | ||
| 39 | + <!-- 列表 --> | ||
| 40 | + <el-table v-loading="loading" :data="list"> | ||
| 41 | + <el-table-column label="任务编号" align="center" prop="id" /> | ||
| 42 | + <el-table-column label="应用编号" align="center" prop="appName" /> | ||
| 43 | + <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" /> | ||
| 44 | + <el-table-column label="通知类型" align="center" prop="type"> | ||
| 45 | + <template v-slot="scope"> | ||
| 46 | + <dict-tag :type="DICT_TYPE.PAY_NOTIFY_TYPE" :value="scope.row.type" /> | ||
| 47 | + </template> | ||
| 48 | + </el-table-column> | ||
| 49 | + <el-table-column label="关联编号" align="center" prop="dataId" /> | ||
| 50 | + <el-table-column label="通知状态" align="center" prop="status"> | ||
| 51 | + <template v-slot="scope"> | ||
| 52 | + <dict-tag :type="DICT_TYPE.PAY_NOTIFY_STATUS" :value="scope.row.status" /> | ||
| 53 | + </template> | ||
| 54 | + </el-table-column> | ||
| 55 | + <el-table-column label="最后通知时间" align="center" prop="lastExecuteTime" width="180"> | ||
| 56 | + <template v-slot="scope"> | ||
| 57 | + <span>{{ parseTime(scope.row.lastExecuteTime) }}</span> | ||
| 58 | + </template> | ||
| 59 | + </el-table-column> | ||
| 60 | + <el-table-column label="下次通知时间" align="center" prop="nextNotifyTime" width="180"> | ||
| 61 | + <template v-slot="scope"> | ||
| 62 | + <span>{{ parseTime(scope.row.nextNotifyTime) }}</span> | ||
| 63 | + </template> | ||
| 64 | + </el-table-column> | ||
| 65 | + <el-table-column label="通知次数" align="center" prop="notifyTimes"> | ||
| 66 | + <template v-slot="scope"> | ||
| 67 | + <el-tag size="mini" type="success"> | ||
| 68 | + {{ scope.row.notifyTimes }} / {{ scope.row.maxNotifyTimes }} | ||
| 69 | + </el-tag> | ||
| 70 | + </template> | ||
| 71 | + </el-table-column> | ||
| 72 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||
| 73 | + <template v-slot="scope"> | ||
| 74 | + <el-button size="mini" type="text" icon="el-icon-search" @click="handleDetail(scope.row)" | ||
| 75 | + v-hasPermi="['pay:notify:query']">查看详情 | ||
| 76 | + </el-button> | ||
| 77 | + </template> | ||
| 78 | + </el-table-column> | ||
| 79 | + </el-table> | ||
| 80 | + <!-- 分页组件 --> | ||
| 81 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | ||
| 82 | + @pagination="getList"/> | ||
| 83 | + | ||
| 84 | + <!-- 对话框(详情) --> | ||
| 85 | + <el-dialog title="通知详情" :visible.sync="open" width="700px" v-dialogDrag append-to-body> | ||
| 86 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 87 | + <el-descriptions-item label="商户订单编号"> | ||
| 88 | + <el-tag size="small">{{ notifyDetail.merchantOrderId }}</el-tag> | ||
| 89 | + </el-descriptions-item> | ||
| 90 | + <el-descriptions-item label="通知状态"> | ||
| 91 | + <dict-tag :type="DICT_TYPE.PAY_NOTIFY_STATUS" :value="notifyDetail.status" size="small" /> | ||
| 92 | + </el-descriptions-item> | ||
| 93 | + </el-descriptions> | ||
| 94 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 95 | + <el-descriptions-item label="应用编号">{{ notifyDetail.appId }}</el-descriptions-item> | ||
| 96 | + <el-descriptions-item label="应用名称">{{ notifyDetail.appName }}</el-descriptions-item> | ||
| 97 | + </el-descriptions> | ||
| 98 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 99 | + <el-descriptions-item label="关联编号">{{ notifyDetail.dataId }}</el-descriptions-item> | ||
| 100 | + <el-descriptions-item label="通知类型"> | ||
| 101 | + <dict-tag :type="DICT_TYPE.PAY_NOTIFY_TYPE" :value="notifyDetail.type" /> | ||
| 102 | + </el-descriptions-item> | ||
| 103 | + </el-descriptions> | ||
| 104 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 105 | + <el-descriptions-item label="通知次数">{{ notifyDetail.notifyTimes }}</el-descriptions-item> | ||
| 106 | + <el-descriptions-item label="最大通知次数">{{ notifyDetail.maxNotifyTimes }}</el-descriptions-item> | ||
| 107 | + </el-descriptions> | ||
| 108 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 109 | + <el-descriptions-item label="最后通知时间">{{ parseTime(notifyDetail.lastExecuteTime) }}</el-descriptions-item> | ||
| 110 | + <el-descriptions-item label="下次通知时间">{{ parseTime(notifyDetail.nextNotifyTime) }}</el-descriptions-item> | ||
| 111 | + </el-descriptions> | ||
| 112 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 113 | + <el-descriptions-item label="创建时间">{{ parseTime(notifyDetail.createTime) }}</el-descriptions-item> | ||
| 114 | + <el-descriptions-item label="更新时间">{{ parseTime(notifyDetail.updateTime) }}</el-descriptions-item> | ||
| 115 | + </el-descriptions> | ||
| 116 | + <!-- 分割线 --> | ||
| 117 | + <el-divider /> | ||
| 118 | + <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> | ||
| 119 | + <el-descriptions-item label="回调日志"> | ||
| 120 | + <el-table :data="notifyDetail.logs"> | ||
| 121 | + <el-table-column label="日志编号" align="center" prop="id" /> | ||
| 122 | + <el-table-column label="通知状态" align="center" prop="status"> | ||
| 123 | + <template v-slot="scope"> | ||
| 124 | + <dict-tag :type="DICT_TYPE.PAY_NOTIFY_STATUS" :value="scope.row.status" /> | ||
| 125 | + </template> | ||
| 126 | + </el-table-column> | ||
| 127 | + <el-table-column label="通知次数" align="center" prop="notifyTimes" /> | ||
| 128 | + <el-table-column label="通知时间" align="center" prop="lastExecuteTime" width="180"> | ||
| 129 | + <template v-slot="scope"> | ||
| 130 | + <span>{{ parseTime(scope.row.createTime) }}</span> | ||
| 131 | + </template> | ||
| 132 | + </el-table-column> | ||
| 133 | + <el-table-column label="响应结果" align="center" prop="response" /> | ||
| 134 | + </el-table> | ||
| 135 | + </el-descriptions-item> | ||
| 136 | + </el-descriptions> | ||
| 137 | + </el-dialog> | ||
| 138 | + </div> | ||
| 139 | +</template> | ||
| 140 | + | ||
| 141 | +<script> | ||
| 142 | +import { getNotifyTaskPage, getNotifyTaskDetail } from "@/api/pay/notify"; | ||
| 143 | +import { getAppList } from "@/api/pay/app"; | ||
| 144 | + | ||
| 145 | +export default { | ||
| 146 | + name: "PayNotify", | ||
| 147 | + data() { | ||
| 148 | + return { | ||
| 149 | + // 遮罩层 | ||
| 150 | + loading: true, | ||
| 151 | + // 导出遮罩层 | ||
| 152 | + exportLoading: false, | ||
| 153 | + // 显示搜索条件 | ||
| 154 | + showSearch: true, | ||
| 155 | + // 总条数 | ||
| 156 | + total: 0, | ||
| 157 | + // 支付通知列表 | ||
| 158 | + list: [], | ||
| 159 | + // 是否显示弹出层 | ||
| 160 | + open: false, | ||
| 161 | + // 查询参数 | ||
| 162 | + queryParams: { | ||
| 163 | + pageNo: 1, | ||
| 164 | + pageSize: 10, | ||
| 165 | + appId: null, | ||
| 166 | + type: null, | ||
| 167 | + dataId: null, | ||
| 168 | + status: null, | ||
| 169 | + merchantOrderId: null, | ||
| 170 | + createTime: [], | ||
| 171 | + }, | ||
| 172 | + | ||
| 173 | + // 支付应用列表集合 | ||
| 174 | + appList: [], | ||
| 175 | + // 通知详情 | ||
| 176 | + notifyDetail: { | ||
| 177 | + logs: [] | ||
| 178 | + }, | ||
| 179 | + }; | ||
| 180 | + }, | ||
| 181 | + created() { | ||
| 182 | + this.getList(); | ||
| 183 | + // 获得筛选项 | ||
| 184 | + getAppList().then(response => { | ||
| 185 | + this.appList = response.data; | ||
| 186 | + }) | ||
| 187 | + }, | ||
| 188 | + methods: { | ||
| 189 | + /** 查询列表 */ | ||
| 190 | + getList() { | ||
| 191 | + this.loading = true; | ||
| 192 | + // 执行查询 | ||
| 193 | + getNotifyTaskPage(this.queryParams).then(response => { | ||
| 194 | + this.list = response.data.list; | ||
| 195 | + this.total = response.data.total; | ||
| 196 | + this.loading = false; | ||
| 197 | + }); | ||
| 198 | + }, | ||
| 199 | + /** 搜索按钮操作 */ | ||
| 200 | + handleQuery() { | ||
| 201 | + this.queryParams.pageNo = 1; | ||
| 202 | + this.getList(); | ||
| 203 | + }, | ||
| 204 | + /** 重置按钮操作 */ | ||
| 205 | + resetQuery() { | ||
| 206 | + this.resetForm("queryForm"); | ||
| 207 | + this.handleQuery(); | ||
| 208 | + }, | ||
| 209 | + /** 详情按钮操作 */ | ||
| 210 | + handleDetail(row) { | ||
| 211 | + this.notifyDetail = {}; | ||
| 212 | + getNotifyTaskDetail(row.id).then(response => { | ||
| 213 | + // 设置值 | ||
| 214 | + this.notifyDetail = response.data; | ||
| 215 | + // 弹窗打开 | ||
| 216 | + this.open = true; | ||
| 217 | + }); | ||
| 218 | + }, | ||
| 219 | + } | ||
| 220 | +}; | ||
| 221 | +</script> |
yudao-ui-admin/src/views/pay/order/index.vue
| @@ -8,35 +8,26 @@ | @@ -8,35 +8,26 @@ | ||
| 8 | <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" /> | 8 | <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" /> |
| 9 | </el-select> | 9 | </el-select> |
| 10 | </el-form-item> | 10 | </el-form-item> |
| 11 | - <el-form-item label="渠道编码" prop="channelCode"> | ||
| 12 | - <el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable | ||
| 13 | - @clear="()=>{queryParams.channelCode = null}"> | ||
| 14 | - <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/> | 11 | + <el-form-item label="支付渠道" prop="channelCode"> |
| 12 | + <el-select v-model="queryParams.channelCode" placeholder="请选择支付渠道" clearable> | ||
| 13 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE)" :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 15 | </el-select> | 14 | </el-select> |
| 16 | </el-form-item> | 15 | </el-form-item> |
| 17 | - <el-form-item label="商户订单编号" prop="merchantOrderId"> | ||
| 18 | - <el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户订单编号" clearable | 16 | + <el-form-item label="商户单号" prop="merchantOrderId"> |
| 17 | + <el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户单号" clearable | ||
| 19 | @keyup.enter.native="handleQuery"/> | 18 | @keyup.enter.native="handleQuery"/> |
| 20 | </el-form-item> | 19 | </el-form-item> |
| 21 | - <el-form-item label="渠道订单号" prop="channelOrderNo"> | ||
| 22 | - <el-input v-model="queryParams.channelOrderNo" placeholder="请输入渠道订单号" clearable | 20 | + <el-form-item label="支付单号" prop="no"> |
| 21 | + <el-input v-model="queryParams.no" placeholder="请输入支付单号" clearable | ||
| 22 | + @keyup.enter.native="handleQuery"/> | ||
| 23 | + </el-form-item> | ||
| 24 | + <el-form-item label="渠道单号" prop="channelOrderNo"> | ||
| 25 | + <el-input v-model="queryParams.channelOrderNo" placeholder="请输入渠道单号" clearable | ||
| 23 | @keyup.enter.native="handleQuery"/> | 26 | @keyup.enter.native="handleQuery"/> |
| 24 | </el-form-item> | 27 | </el-form-item> |
| 25 | <el-form-item label="支付状态" prop="status"> | 28 | <el-form-item label="支付状态" prop="status"> |
| 26 | <el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small"> | 29 | <el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small"> |
| 27 | - <el-option v-for="dict in payOrderDictDatum" :key="parseInt(dict.value)" | ||
| 28 | - :label="dict.label" :value="parseInt(dict.value)"/> | ||
| 29 | - </el-select> | ||
| 30 | - </el-form-item> | ||
| 31 | - <el-form-item label="退款状态" prop="refundStatus"> | ||
| 32 | - <el-select v-model="queryParams.refundStatus" placeholder="请选择退款状态" clearable> | ||
| 33 | - <el-option v-for="dict in payOrderRefundDictDatum" :key="parseInt(dict.value)" | ||
| 34 | - :label="dict.label" :value="parseInt(dict.value)"/> | ||
| 35 | - </el-select> | ||
| 36 | - </el-form-item> | ||
| 37 | - <el-form-item label="回调商户状态" prop="notifyStatus"> | ||
| 38 | - <el-select v-model="queryParams.notifyStatus" placeholder="请选择订单回调商户状态" clearable> | ||
| 39 | - <el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)" | 30 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_ORDER_STATUS)" :key="parseInt(dict.value)" |
| 40 | :label="dict.label" :value="parseInt(dict.value)"/> | 31 | :label="dict.label" :value="parseInt(dict.value)"/> |
| 41 | </el-select> | 32 | </el-select> |
| 42 | </el-form-item> | 33 | </el-form-item> |
| @@ -62,69 +53,64 @@ | @@ -62,69 +53,64 @@ | ||
| 62 | 53 | ||
| 63 | <!-- 列表 --> | 54 | <!-- 列表 --> |
| 64 | <el-table v-loading="loading" :data="list"> | 55 | <el-table v-loading="loading" :data="list"> |
| 65 | - <el-table-column label="订单编号" align="center" prop="id" width="80"/> | ||
| 66 | - <el-table-column label="支付渠道" align="center" width="130"> | 56 | + <el-table-column label="编号" align="center" prop="id" width="80"/> |
| 57 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | ||
| 67 | <template v-slot="scope"> | 58 | <template v-slot="scope"> |
| 68 | - <el-popover trigger="hover" placement="top"> | ||
| 69 | - <p>应用名称: {{ scope.row.appName }}</p> | ||
| 70 | - <p>渠道名称: {{ scope.row.channelCodeName }}</p> | ||
| 71 | - <div slot="reference" class="name-wrapper"> | ||
| 72 | - {{ scope.row.channelCodeName }} | ||
| 73 | - </div> | ||
| 74 | - </el-popover> | 59 | + <span>{{ parseTime(scope.row.createTime) }}</span> |
| 75 | </template> | 60 | </template> |
| 76 | </el-table-column> | 61 | </el-table-column> |
| 77 | - <el-table-column label="支付订单" align="left" width="280"> | 62 | + <el-table-column label="支付金额" align="center" prop="price" width="100"> |
| 78 | <template v-slot="scope"> | 63 | <template v-slot="scope"> |
| 79 | - <p class="order-font"><el-tag size="mini">商户单号</el-tag> {{scope.row.merchantOrderId}}</p> | ||
| 80 | - <p class="order-font"><el-tag size="mini" type="warning">支付单号</el-tag> {{scope.row.channelOrderNo}}</p> | 64 | + ¥{{ (scope.row.price / 100.0).toFixed(2) }} |
| 81 | </template> | 65 | </template> |
| 82 | </el-table-column> | 66 | </el-table-column> |
| 83 | - <el-table-column label="商品标题" align="center" prop="subject" width="180" :show-overflow-tooltip="true"/> | ||
| 84 | - <el-table-column label="支付金额" align="center" prop="price" width="100"> | 67 | + <el-table-column label="退款金额" align="center" prop="refundPrice" width="100"> |
| 85 | <template v-slot="scope"> | 68 | <template v-slot="scope"> |
| 86 | - ¥{{ parseFloat(scope.row.price / 100).toFixed(2) }} | 69 | + ¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }} |
| 87 | </template> | 70 | </template> |
| 88 | </el-table-column> | 71 | </el-table-column> |
| 89 | <el-table-column label="手续金额" align="center" prop="channelFeePrice" width="100"> | 72 | <el-table-column label="手续金额" align="center" prop="channelFeePrice" width="100"> |
| 90 | <template v-slot="scope"> | 73 | <template v-slot="scope"> |
| 91 | - ¥{{ parseFloat(scope.row.channelFeePrice / 100).toFixed(2) }} | 74 | + ¥{{ (scope.row.channelFeePrice / 100.0).toFixed(2) }} |
| 92 | </template> | 75 | </template> |
| 93 | </el-table-column> | 76 | </el-table-column> |
| 94 | - <el-table-column label="退款金额" align="center" prop="refundPrice" width="100"> | 77 | + <el-table-column label="订单号" align="left" width="300"> |
| 95 | <template v-slot="scope"> | 78 | <template v-slot="scope"> |
| 96 | - ¥{{ parseFloat(scope.row.refundPrice / 100).toFixed(2) }} | 79 | + <p class="order-font"><el-tag size="mini"> |
| 80 | + 商户</el-tag> {{scope.row.merchantOrderId}} | ||
| 81 | + </p> | ||
| 82 | + <p class="order-font" v-if="scope.row.no"> | ||
| 83 | + <el-tag size="mini" type="warning">支付</el-tag> {{scope.row.no}} | ||
| 84 | + </p> | ||
| 85 | + <p class="order-font" v-if="scope.row.channelOrderNo"> | ||
| 86 | + <el-tag size="mini" type="success">渠道</el-tag> {{scope.row.channelOrderNo}} | ||
| 87 | + </p> | ||
| 97 | </template> | 88 | </template> |
| 98 | </el-table-column> | 89 | </el-table-column> |
| 99 | <el-table-column label="支付状态" align="center" prop="status"> | 90 | <el-table-column label="支付状态" align="center" prop="status"> |
| 100 | <template v-slot="scope"> | 91 | <template v-slot="scope"> |
| 101 | <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="scope.row.status" /> | 92 | <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="scope.row.status" /> |
| 102 | </template> | 93 | </template> |
| 103 | - | ||
| 104 | </el-table-column> | 94 | </el-table-column> |
| 105 | -<!-- <el-table-column label="退款状态" align="center" prop="refundStatus">--> | ||
| 106 | -<!-- <template v-slot="scope">--> | ||
| 107 | -<!-- <span>{{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, scope.row.refundStatus) }}</span>--> | ||
| 108 | -<!-- </template>--> | ||
| 109 | -<!-- </el-table-column>--> | ||
| 110 | - <el-table-column label="回调状态" align="center" prop="notifyStatus" width="100"> | 95 | + <el-table-column label="支付渠道" align="center" width="140"> |
| 111 | <template v-slot="scope"> | 96 | <template v-slot="scope"> |
| 112 | - <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" /> | 97 | + <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE" :value="scope.row.channelCode" /> |
| 113 | </template> | 98 | </template> |
| 114 | </el-table-column> | 99 | </el-table-column> |
| 115 | - <el-table-column label="创建时间" align="center" prop="createTime" width="100"> | 100 | + <el-table-column label="支付时间" align="center" prop="successTime" width="180"> |
| 116 | <template v-slot="scope"> | 101 | <template v-slot="scope"> |
| 117 | - <span>{{ parseTime(scope.row.createTime) }}</span> | 102 | + <span>{{ parseTime(scope.row.successTime) }}</span> |
| 118 | </template> | 103 | </template> |
| 119 | </el-table-column> | 104 | </el-table-column> |
| 120 | - <el-table-column label="支付时间" align="center" prop="successTime" width="100"> | 105 | + <el-table-column label="支付应用" align="center" prop="successTime" width="100"> |
| 121 | <template v-slot="scope"> | 106 | <template v-slot="scope"> |
| 122 | - <span>{{ parseTime(scope.row.successTime) }}</span> | 107 | + <span>{{ scope.row.appName }}</span> |
| 123 | </template> | 108 | </template> |
| 124 | </el-table-column> | 109 | </el-table-column> |
| 110 | + <el-table-column label="商品标题" align="center" prop="subject" width="180" :show-overflow-tooltip="true"/> | ||
| 125 | <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> | 111 | <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> |
| 126 | <template v-slot="scope"> | 112 | <template v-slot="scope"> |
| 127 | - <el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)" | 113 | + <el-button size="mini" type="text" icon="el-icon-search" @click="handleDetail(scope.row)" |
| 128 | v-hasPermi="['pay:order:query']">查看详情 | 114 | v-hasPermi="['pay:order:query']">查看详情 |
| 129 | </el-button> | 115 | </el-button> |
| 130 | </template> | 116 | </template> |
| @@ -134,67 +120,71 @@ | @@ -134,67 +120,71 @@ | ||
| 134 | <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 120 | <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 135 | @pagination="getList"/> | 121 | @pagination="getList"/> |
| 136 | 122 | ||
| 137 | - <!-- 对话框(添加 / 修改) --> | ||
| 138 | - <el-dialog title="订单详情" :visible.sync="open" width="50%"> | ||
| 139 | - <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 140 | - <el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item> | ||
| 141 | - <el-descriptions-item label="商品名称">{{ orderDetail.subject }}</el-descriptions-item> | ||
| 142 | - </el-descriptions> | ||
| 143 | - <el-divider></el-divider> | 123 | + <!-- 对话框(详情) --> |
| 124 | + <el-dialog title="订单详情" :visible.sync="open" width="700px" v-dialogDrag append-to-body> | ||
| 144 | <el-descriptions :column="2" label-class-name="desc-label"> | 125 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 145 | - <el-descriptions-item label="商户订单号"> | 126 | + <el-descriptions-item label="商户单号"> |
| 146 | <el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag> | 127 | <el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag> |
| 147 | </el-descriptions-item> | 128 | </el-descriptions-item> |
| 148 | - <el-descriptions-item label="渠道订单号"> | ||
| 149 | - <el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag> | 129 | + <el-descriptions-item label="支付单号"> |
| 130 | + <el-tag type="warning" size="small" v-if="orderDetail.no">{{ orderDetail.no }}</el-tag> | ||
| 150 | </el-descriptions-item> | 131 | </el-descriptions-item> |
| 151 | - <el-descriptions-item label="支付订单号"> | ||
| 152 | - <el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small"> | ||
| 153 | - {{ orderDetail.payOrderExtension.no }} | ||
| 154 | - </el-tag> | 132 | + </el-descriptions> |
| 133 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 134 | + <el-descriptions-item label="应用编号">{{ orderDetail.appId }}</el-descriptions-item> | ||
| 135 | + <el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item> | ||
| 136 | + </el-descriptions> | ||
| 137 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 138 | + <el-descriptions-item label="支付状态"> | ||
| 139 | + <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" size="small" /> | ||
| 155 | </el-descriptions-item> | 140 | </el-descriptions-item> |
| 156 | - <el-descriptions-item label="金额"> | ||
| 157 | - <el-tag type="success" size="small">{{ parseFloat(orderDetail.price / 100, 2) }}</el-tag> | 141 | + <el-descriptions-item label="支付金额"> |
| 142 | + <el-tag type="success" size="small">¥{{ (orderDetail.price / 100.0).toFixed(2) }}</el-tag> | ||
| 158 | </el-descriptions-item> | 143 | </el-descriptions-item> |
| 144 | + </el-descriptions> | ||
| 145 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 159 | <el-descriptions-item label="手续费"> | 146 | <el-descriptions-item label="手续费"> |
| 160 | - <el-tag type="warning" size="small">{{ parseFloat(orderDetail.channelFeePrice / 100, 2) }}</el-tag> | ||
| 161 | - </el-descriptions-item> | ||
| 162 | - <el-descriptions-item label="手续费比例"> | ||
| 163 | - {{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}% | ||
| 164 | - </el-descriptions-item> | ||
| 165 | - <el-descriptions-item label="支付状态"> | ||
| 166 | - <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" /> | 147 | + <el-tag type="warning" size="small">¥{{ (orderDetail.channelFeePrice / 100.0).toFixed(2) }}</el-tag> |
| 167 | </el-descriptions-item> | 148 | </el-descriptions-item> |
| 168 | - <el-descriptions-item label="回调状态"> | ||
| 169 | - <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="orderDetail.notifyStatus" /> | ||
| 170 | - </el-descriptions-item> | ||
| 171 | - <el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item> | ||
| 172 | - <el-descriptions-item label="创建时间">{{ parseTime(orderDetail.createTime) }}</el-descriptions-item> | 149 | + <el-descriptions-item label="手续费比例">{{ (orderDetail.channelFeeRate / 100.0).toFixed(2) }}%</el-descriptions-item> |
| 150 | + </el-descriptions> | ||
| 151 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 173 | <el-descriptions-item label="支付时间">{{ parseTime(orderDetail.successTime) }}</el-descriptions-item> | 152 | <el-descriptions-item label="支付时间">{{ parseTime(orderDetail.successTime) }}</el-descriptions-item> |
| 174 | <el-descriptions-item label="失效时间">{{ parseTime(orderDetail.expireTime) }}</el-descriptions-item> | 153 | <el-descriptions-item label="失效时间">{{ parseTime(orderDetail.expireTime) }}</el-descriptions-item> |
| 175 | - <el-descriptions-item label="通知时间">{{ parseTime(orderDetail.notifyTime) }}</el-descriptions-item> | ||
| 176 | </el-descriptions> | 154 | </el-descriptions> |
| 177 | - <el-divider></el-divider> | ||
| 178 | <el-descriptions :column="2" label-class-name="desc-label"> | 155 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 179 | - <el-descriptions-item label="支付渠道">{{ orderDetail.channelCodeName }}</el-descriptions-item> | ||
| 180 | - <el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item> | ||
| 181 | - <el-descriptions-item label="退款状态"> | ||
| 182 | - <dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="orderDetail.refundStatus" /> | 156 | + <el-descriptions-item label="创建时间">{{ parseTime(orderDetail.createTime) }}</el-descriptions-item> |
| 157 | + <el-descriptions-item label="更新时间">{{ parseTime(orderDetail.updateTime) }}</el-descriptions-item> | ||
| 158 | + </el-descriptions> | ||
| 159 | + <!-- 分割线 --> | ||
| 160 | + <el-divider/> | ||
| 161 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 162 | + <el-descriptions-item label="商品标题">{{ orderDetail.subject }}</el-descriptions-item> | ||
| 163 | + <el-descriptions-item label="商品描述">{{ orderDetail.body }}</el-descriptions-item> | ||
| 164 | + </el-descriptions> | ||
| 165 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 166 | + <el-descriptions-item label="支付渠道"> | ||
| 167 | + <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE" :value="orderDetail.channelCode" /> | ||
| 183 | </el-descriptions-item> | 168 | </el-descriptions-item> |
| 184 | - <el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item> | 169 | + <el-descriptions-item label="支付 IP">{{ orderDetail.userIp }}</el-descriptions-item> |
| 170 | + </el-descriptions> | ||
| 171 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 172 | + <el-descriptions-item label="渠道单号"> | ||
| 173 | + <el-tag size="mini" type="success" v-if="orderDetail.channelOrderNo">{{ orderDetail.channelOrderNo }}</el-tag> | ||
| 174 | + </el-descriptions-item> | ||
| 175 | + <el-descriptions-item label="渠道用户">{{ orderDetail.channelUserId }}</el-descriptions-item> | ||
| 176 | + </el-descriptions> | ||
| 177 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 185 | <el-descriptions-item label="退款金额"> | 178 | <el-descriptions-item label="退款金额"> |
| 186 | - <el-tag type="warning"> | ||
| 187 | - {{ parseFloat(orderDetail.refundPrice / 100, 2) }} | ||
| 188 | - </el-tag> | 179 | + <el-tag size="mini" type="danger">¥{{ (orderDetail.refundPrice / 100.0).toFixed(2) }}</el-tag> |
| 189 | </el-descriptions-item> | 180 | </el-descriptions-item> |
| 181 | + <el-descriptions-item label="通知 URL">{{ orderDetail.notifyUrl }}</el-descriptions-item> | ||
| 190 | </el-descriptions> | 182 | </el-descriptions> |
| 191 | - <el-divider></el-divider> | 183 | + <!-- 分割线 --> |
| 184 | + <el-divider /> | ||
| 192 | <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> | 185 | <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> |
| 193 | - <el-descriptions-item label="商品描述"> | ||
| 194 | - {{ orderDetail.body }} | ||
| 195 | - </el-descriptions-item> | ||
| 196 | <el-descriptions-item label="支付通道异步回调内容"> | 186 | <el-descriptions-item label="支付通道异步回调内容"> |
| 197 | - {{ orderDetail.payOrderExtension.channelNotifyData }} | 187 | + {{ orderDetail.extension.channelNotifyData }} |
| 198 | </el-descriptions-item> | 188 | </el-descriptions-item> |
| 199 | </el-descriptions> | 189 | </el-descriptions> |
| 200 | </el-dialog> | 190 | </el-dialog> |
| @@ -203,35 +193,7 @@ | @@ -203,35 +193,7 @@ | ||
| 203 | 193 | ||
| 204 | <script> | 194 | <script> |
| 205 | import { getOrderDetail, getOrderPage, exportOrderExcel } from "@/api/pay/order"; | 195 | import { getOrderDetail, getOrderPage, exportOrderExcel } from "@/api/pay/order"; |
| 206 | -import { DICT_TYPE, getDictDatas } from "@/utils/dict"; | ||
| 207 | -import { getNowDateTime} from "@/utils/ruoyi"; | ||
| 208 | - | ||
| 209 | -const defaultOrderDetail = { | ||
| 210 | - appName: '', | ||
| 211 | - channelCodeName: '', | ||
| 212 | - subject: '', | ||
| 213 | - merchantOrderId: null, | ||
| 214 | - channelOrderNo: '', | ||
| 215 | - body: '', | ||
| 216 | - price: null, | ||
| 217 | - channelFeeRate: null, | ||
| 218 | - channelFeePrice: null, | ||
| 219 | - userIp: '', | ||
| 220 | - status: null, | ||
| 221 | - notifyUrl: '', | ||
| 222 | - notifyStatus: null, | ||
| 223 | - refundStatus: null, | ||
| 224 | - refundTimes: '', | ||
| 225 | - refundPrice: null, | ||
| 226 | - createTime: '', | ||
| 227 | - successTime: '', | ||
| 228 | - notifyTime: '', | ||
| 229 | - expireTime: '', | ||
| 230 | - payOrderExtension: { | ||
| 231 | - channelNotifyData: '', | ||
| 232 | - no: '' | ||
| 233 | - } | ||
| 234 | -}; | 196 | +import { getAppList } from "@/api/pay/app"; |
| 235 | 197 | ||
| 236 | export default { | 198 | export default { |
| 237 | name: "PayOrder", | 199 | name: "PayOrder", |
| @@ -250,75 +212,37 @@ export default { | @@ -250,75 +212,37 @@ export default { | ||
| 250 | title: "", | 212 | title: "", |
| 251 | // 是否显示弹出层 | 213 | // 是否显示弹出层 |
| 252 | open: false, | 214 | open: false, |
| 253 | - // 查询参数 TODO 芋艿:多余字段的清理 | 215 | + // 查询参数 |
| 254 | queryParams: { | 216 | queryParams: { |
| 255 | pageNo: 1, | 217 | pageNo: 1, |
| 256 | pageSize: 10, | 218 | pageSize: 10, |
| 257 | appId: null, | 219 | appId: null, |
| 258 | - channelId: null, | ||
| 259 | channelCode: null, | 220 | channelCode: null, |
| 260 | merchantOrderId: null, | 221 | merchantOrderId: null, |
| 261 | - subject: null, | ||
| 262 | - body: null, | ||
| 263 | - notifyUrl: null, | ||
| 264 | - notifyStatus: null, | ||
| 265 | - price: null, | ||
| 266 | - channelFeeRate: null, | ||
| 267 | - channelFeePrice: null, | ||
| 268 | - status: null, | ||
| 269 | - userIp: null, | ||
| 270 | - successExtensionId: null, | ||
| 271 | - refundStatus: null, | ||
| 272 | - refundTimes: null, | ||
| 273 | - refundPrice: null, | ||
| 274 | - channelUserId: null, | ||
| 275 | channelOrderNo: null, | 222 | channelOrderNo: null, |
| 276 | - expireTime: [], | ||
| 277 | - successTime: [], | ||
| 278 | - notifyTime: [], | ||
| 279 | - createTime: [] | 223 | + no: null, |
| 224 | + status: null, | ||
| 225 | + createTime: [], | ||
| 280 | }, | 226 | }, |
| 281 | - // 商户加载遮罩层 | ||
| 282 | - merchantLoading: false, | ||
| 283 | - // 商户列表集合 | ||
| 284 | - merchantList: null, | 227 | + |
| 285 | // 支付应用列表集合 | 228 | // 支付应用列表集合 |
| 286 | - appList: null, | ||
| 287 | - // 支付渠道编码字典数据集合 | ||
| 288 | - payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE), | ||
| 289 | - // 订单回调商户状态字典数据集合 | ||
| 290 | - payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS), | ||
| 291 | - // 订单状态字典数据集合 | ||
| 292 | - payOrderDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_STATUS), | ||
| 293 | - // 订单退款状态字典数据集合 | ||
| 294 | - payOrderRefundDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_REFUND_STATUS), | ||
| 295 | - orderDetail: JSON.parse(JSON.stringify(defaultOrderDetail)), | 229 | + appList: [], |
| 230 | + // 订单详情 | ||
| 231 | + orderDetail: { | ||
| 232 | + extension: {} | ||
| 233 | + }, | ||
| 296 | }; | 234 | }; |
| 297 | }, | 235 | }, |
| 298 | created() { | 236 | created() { |
| 299 | - // 初始化默认时间 | ||
| 300 | - this.initTime(); | ||
| 301 | this.getList(); | 237 | this.getList(); |
| 302 | - this.handleGetMerchantListByName(null); | 238 | + // 获得筛选项 |
| 239 | + getAppList().then(response => { | ||
| 240 | + this.appList = response.data; | ||
| 241 | + }) | ||
| 303 | }, | 242 | }, |
| 304 | methods: { | 243 | methods: { |
| 305 | - initTime(){ | ||
| 306 | - this.queryParams.createTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")]; | ||
| 307 | - }, | ||
| 308 | /** 查询列表 */ | 244 | /** 查询列表 */ |
| 309 | getList() { | 245 | getList() { |
| 310 | - // 判断选择的日期是否超过了一个月 | ||
| 311 | - let oneMonthTime = 31 * 24 * 3600 * 1000; | ||
| 312 | - if (this.queryParams.createTime == null){ | ||
| 313 | - this.initTime(); | ||
| 314 | - } else { | ||
| 315 | - let minDateTime = new Date(this.queryParams.createTime[0]).getTime(); | ||
| 316 | - let maxDateTime = new Date(this.queryParams.createTime[1]).getTime() | ||
| 317 | - if (maxDateTime - minDateTime > oneMonthTime) { | ||
| 318 | - this.$message.error('时间范围最大为 31 天!'); | ||
| 319 | - return false; | ||
| 320 | - } | ||
| 321 | - } | ||
| 322 | this.loading = true; | 246 | this.loading = true; |
| 323 | // 执行查询 | 247 | // 执行查询 |
| 324 | getOrderPage(this.queryParams).then(response => { | 248 | getOrderPage(this.queryParams).then(response => { |
| @@ -339,22 +263,20 @@ export default { | @@ -339,22 +263,20 @@ export default { | ||
| 339 | /** 重置按钮操作 */ | 263 | /** 重置按钮操作 */ |
| 340 | resetQuery() { | 264 | resetQuery() { |
| 341 | this.resetForm("queryForm"); | 265 | this.resetForm("queryForm"); |
| 342 | - this.initTime(); | ||
| 343 | this.handleQuery(); | 266 | this.handleQuery(); |
| 344 | }, | 267 | }, |
| 345 | - /** | ||
| 346 | - * 查看订单详情 | ||
| 347 | - */ | ||
| 348 | - handleQueryDetails(row) { | ||
| 349 | - this.orderDetail = JSON.parse(JSON.stringify(defaultOrderDetail)); | 268 | + /** 详情按钮操作 */ |
| 269 | + handleDetail(row) { | ||
| 270 | + this.orderDetail = {}; | ||
| 350 | getOrderDetail(row.id).then(response => { | 271 | getOrderDetail(row.id).then(response => { |
| 272 | + // 设置值 | ||
| 351 | this.orderDetail = response.data; | 273 | this.orderDetail = response.data; |
| 352 | - if (response.data.payOrderExtension === null) { | ||
| 353 | - this.orderDetail.payOrderExtension = Object.assign(defaultOrderDetail.payOrderExtension, {}); | 274 | + if (!this.orderDetail.extension) { |
| 275 | + this.orderDetail.extension = {} | ||
| 354 | } | 276 | } |
| 277 | + // 弹窗打开 | ||
| 355 | this.open = true; | 278 | this.open = true; |
| 356 | }); | 279 | }); |
| 357 | - | ||
| 358 | }, | 280 | }, |
| 359 | /** 导出按钮操作 */ | 281 | /** 导出按钮操作 */ |
| 360 | handleExport() { | 282 | handleExport() { |
yudao-ui-admin/src/views/pay/refund/index.vue
| @@ -7,31 +7,30 @@ | @@ -7,31 +7,30 @@ | ||
| 7 | <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" /> | 7 | <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" /> |
| 8 | </el-select> | 8 | </el-select> |
| 9 | </el-form-item> | 9 | </el-form-item> |
| 10 | - <el-form-item label="渠道编码" prop="channelCode"> | ||
| 11 | - <el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable | ||
| 12 | - @clear="()=>{queryParams.channelCode = null}"> | ||
| 13 | - <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/> | 10 | + <el-form-item label="退款渠道" prop="channelCode"> |
| 11 | + <el-select v-model="queryParams.channelCode" placeholder="请选择退款渠道" clearable> | ||
| 12 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE)" :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 14 | </el-select> | 13 | </el-select> |
| 15 | </el-form-item> | 14 | </el-form-item> |
| 16 | - <el-form-item label="退款类型" prop="type"> | ||
| 17 | - <el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable> | ||
| 18 | - <el-option v-for="dict in payRefundOrderTypeDictDatum" :key="parseInt(dict.value)" | ||
| 19 | - :label="dict.label" :value="parseInt(dict.value)"/> | ||
| 20 | - </el-select> | 15 | + <el-form-item label="商户支付单号" prop="merchantOrderId"> |
| 16 | + <el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户支付单号" clearable | ||
| 17 | + @keyup.enter.native="handleQuery"/> | ||
| 18 | + </el-form-item> | ||
| 19 | + <el-form-item label="商户退款单号" prop="merchantRefundId"> | ||
| 20 | + <el-input v-model="queryParams.merchantRefundId" placeholder="请输入商户退款单号" clearable | ||
| 21 | + @keyup.enter.native="handleQuery"/> | ||
| 22 | + </el-form-item> | ||
| 23 | + <el-form-item label="渠道支付单号" prop="channelOrderNo"> | ||
| 24 | + <el-input v-model="queryParams.channelOrderNo" placeholder="请输入渠道支付单号" clearable | ||
| 25 | + @keyup.enter.native="handleQuery"/> | ||
| 21 | </el-form-item> | 26 | </el-form-item> |
| 22 | - <el-form-item label="商户退款订单号" prop="merchantRefundNo"> | ||
| 23 | - <el-input v-model="queryParams.merchantRefundNo" placeholder="请输入商户退款订单号" clearable | 27 | + <el-form-item label="渠道退款单号" prop="channelRefundNo"> |
| 28 | + <el-input v-model="queryParams.channelRefundNo" placeholder="请输入渠道退款单号" clearable | ||
| 24 | @keyup.enter.native="handleQuery"/> | 29 | @keyup.enter.native="handleQuery"/> |
| 25 | </el-form-item> | 30 | </el-form-item> |
| 26 | <el-form-item label="退款状态" prop="status"> | 31 | <el-form-item label="退款状态" prop="status"> |
| 27 | <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable> | 32 | <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable> |
| 28 | - <el-option v-for="dict in payRefundOrderDictDatum" :key="parseInt(dict.value)" | ||
| 29 | - :label="dict.label" :value="parseInt(dict.value)"/> | ||
| 30 | - </el-select> | ||
| 31 | - </el-form-item> | ||
| 32 | - <el-form-item label="退款回调状态" prop="notifyStatus"> | ||
| 33 | - <el-select v-model="queryParams.notifyStatus" placeholder="请选择通知商户退款结果的回调状态" clearable> | ||
| 34 | - <el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)" | 33 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_REFUND_STATUS)" :key="parseInt(dict.value)" |
| 35 | :label="dict.label" :value="parseInt(dict.value)"/> | 34 | :label="dict.label" :value="parseInt(dict.value)"/> |
| 36 | </el-select> | 35 | </el-select> |
| 37 | </el-form-item> | 36 | </el-form-item> |
| @@ -58,77 +57,62 @@ | @@ -58,77 +57,62 @@ | ||
| 58 | <!-- 列表 --> | 57 | <!-- 列表 --> |
| 59 | <el-table v-loading="loading" :data="list"> | 58 | <el-table v-loading="loading" :data="list"> |
| 60 | <el-table-column label="编号" align="center" prop="id"/> | 59 | <el-table-column label="编号" align="center" prop="id"/> |
| 61 | - <el-table-column label="支付渠道" align="center" width="130"> | 60 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| 62 | <template v-slot="scope"> | 61 | <template v-slot="scope"> |
| 63 | - <el-popover trigger="hover" placement="top"> | ||
| 64 | - <p>应用名称: {{ scope.row.appName }}</p> | ||
| 65 | - <p>渠道名称: {{ scope.row.channelCodeName }}</p> | ||
| 66 | - <div slot="reference" class="name-wrapper"> | ||
| 67 | - {{ scope.row.channelCodeName }} | ||
| 68 | - </div> | ||
| 69 | - </el-popover> | 62 | + <span>{{ parseTime(scope.row.createTime) }}</span> |
| 63 | + </template> | ||
| 64 | + </el-table-column> | ||
| 65 | + <el-table-column label="支付金额" align="center" prop="payPrice" width="100"> | ||
| 66 | + <template v-slot="scope" class=""> | ||
| 67 | + ¥{{ (scope.row.payPrice / 100.0).toFixed(2) }} | ||
| 70 | </template> | 68 | </template> |
| 71 | </el-table-column> | 69 | </el-table-column> |
| 72 | - <!-- <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140"/>--> | ||
| 73 | - <!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>--> | ||
| 74 | - <el-table-column label="商户订单号" align="left" width="230"> | 70 | + <el-table-column label="退款金额" align="center" prop="refundPrice" width="100"> |
| 71 | + <template v-slot="scope"> | ||
| 72 | + ¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }} | ||
| 73 | + </template> | ||
| 74 | + </el-table-column> | ||
| 75 | + <el-table-column label="退款订单号" align="left" width="300"> | ||
| 75 | <template v-slot="scope"> | 76 | <template v-slot="scope"> |
| 76 | <p class="order-font"> | 77 | <p class="order-font"> |
| 77 | - <el-tag size="mini">退款</el-tag> | ||
| 78 | - {{ scope.row.merchantRefundNo }} | 78 | + <el-tag size="mini">商户</el-tag> {{scope.row.merchantRefundId}} |
| 79 | </p> | 79 | </p> |
| 80 | <p class="order-font"> | 80 | <p class="order-font"> |
| 81 | - <el-tag type="success">交易</el-tag> | ||
| 82 | - {{ scope.row.merchantOrderId }} | 81 | + <el-tag size="mini" type="warning">退款</el-tag> {{scope.row.no}} |
| 82 | + </p> | ||
| 83 | + <p class="order-font" v-if="scope.row.channelRefundNo"> | ||
| 84 | + <el-tag size="mini" type="success">渠道</el-tag> {{scope.row.channelRefundNo}} | ||
| 83 | </p> | 85 | </p> |
| 84 | </template> | 86 | </template> |
| 85 | </el-table-column> | 87 | </el-table-column> |
| 86 | - <el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250"> | 88 | + <el-table-column label="支付订单号" align="left" width="300"> |
| 87 | <template v-slot="scope"> | 89 | <template v-slot="scope"> |
| 88 | <p class="order-font"> | 90 | <p class="order-font"> |
| 89 | - <el-tag size="mini">交易</el-tag> | ||
| 90 | - {{ scope.row.tradeNo }} | 91 | + <el-tag size="mini">商户</el-tag> {{scope.row.merchantOrderId}} |
| 91 | </p> | 92 | </p> |
| 92 | <p class="order-font"> | 93 | <p class="order-font"> |
| 93 | - <el-tag size="mini" type="warning">渠道</el-tag> | ||
| 94 | - {{ scope.row.channelOrderNo }} | 94 | + <el-tag size="mini" type="success">渠道</el-tag> {{scope.row.channelOrderNo}} |
| 95 | </p> | 95 | </p> |
| 96 | </template> | 96 | </template> |
| 97 | </el-table-column> | 97 | </el-table-column> |
| 98 | - <el-table-column label="支付金额(元)" align="center" prop="payPrice" width="100"> | ||
| 99 | - <template v-slot="scope" class=""> | ||
| 100 | - ¥{{ parseFloat(scope.row.payPrice / 100).toFixed(2) }} | ||
| 101 | - </template> | ||
| 102 | - </el-table-column> | ||
| 103 | - <el-table-column label="退款金额(元)" align="center" prop="refundPrice" width="100"> | ||
| 104 | - <template v-slot="scope"> | ||
| 105 | - ¥{{ parseFloat(scope.row.refundPrice / 100).toFixed(2) }} | ||
| 106 | - </template> | ||
| 107 | - </el-table-column> | ||
| 108 | - <el-table-column label="退款类型" align="center" prop="type" width="80"> | ||
| 109 | - <template v-slot="scope"> | ||
| 110 | - <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="scope.row.type" /> | ||
| 111 | - </template> | ||
| 112 | - </el-table-column> | ||
| 113 | <el-table-column label="退款状态" align="center" prop="status"> | 98 | <el-table-column label="退款状态" align="center" prop="status"> |
| 114 | <template v-slot="scope"> | 99 | <template v-slot="scope"> |
| 115 | - <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="scope.row.status" /> | 100 | + <dict-tag :type="DICT_TYPE.PAY_REFUND_STATUS" :value="scope.row.status" /> |
| 116 | </template> | 101 | </template> |
| 117 | </el-table-column> | 102 | </el-table-column> |
| 118 | - <el-table-column label="回调状态" align="center" prop="notifyStatus"> | 103 | + <el-table-column label="退款渠道" align="center" width="140"> |
| 119 | <template v-slot="scope"> | 104 | <template v-slot="scope"> |
| 120 | - <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" /> | 105 | + <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE" :value="scope.row.channelCode" /> |
| 121 | </template> | 106 | </template> |
| 122 | </el-table-column> | 107 | </el-table-column> |
| 123 | - <el-table-column label="退款原因" align="center" prop="reason" width="140" :show-overflow-tooltip="true"/> | ||
| 124 | - <el-table-column label="创建时间" align="center" prop="createTime" width="100"> | 108 | + <el-table-column label="成功时间" align="center" prop="successTime" width="180"> |
| 125 | <template v-slot="scope"> | 109 | <template v-slot="scope"> |
| 126 | - <span>{{ parseTime(scope.row.createTime) }}</span> | 110 | + <span>{{ parseTime(scope.row.successTime) }}</span> |
| 127 | </template> | 111 | </template> |
| 128 | </el-table-column> | 112 | </el-table-column> |
| 129 | - <el-table-column label="退款成功时间" align="center" prop="successTime" width="100"> | 113 | + <el-table-column label="支付应用" align="center" prop="successTime" width="100"> |
| 130 | <template v-slot="scope"> | 114 | <template v-slot="scope"> |
| 131 | - <span>{{ parseTime(scope.row.successTime) }}</span> | 115 | + <span>{{ scope.row.appName }}</span> |
| 132 | </template> | 116 | </template> |
| 133 | </el-table-column> | 117 | </el-table-column> |
| 134 | <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> | 118 | <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> |
| @@ -143,107 +127,76 @@ | @@ -143,107 +127,76 @@ | ||
| 143 | <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 127 | <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 144 | @pagination="getList"/> | 128 | @pagination="getList"/> |
| 145 | 129 | ||
| 146 | - <!-- 对话框(添加 / 修改) --> | ||
| 147 | - <el-dialog title="退款订单详情" :visible.sync="open" width="700px" append-to-body> | 130 | + <!-- 对话框(详情) --> |
| 131 | + <el-dialog title="退款订单详情" :visible.sync="open" width="700px" v-dialogDrag append-to-body> | ||
| 148 | <el-descriptions :column="2" label-class-name="desc-label"> | 132 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 149 | - <el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item> | ||
| 150 | - <el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item> | 133 | + <el-descriptions-item label="商户退款单号"> |
| 134 | + <el-tag size="small">{{ refundDetail.merchantRefundId }}</el-tag> | ||
| 135 | + </el-descriptions-item> | ||
| 136 | + <el-descriptions-item label="渠道退款单号"> | ||
| 137 | + <el-tag type="success" size="small" v-if="refundDetail.channelRefundNo">{{ refundDetail.channelRefundNo }}</el-tag> | ||
| 138 | + </el-descriptions-item> | ||
| 151 | </el-descriptions> | 139 | </el-descriptions> |
| 152 | - <el-divider></el-divider> | ||
| 153 | <el-descriptions :column="2" label-class-name="desc-label"> | 140 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 154 | - <el-descriptions-item label="商户退款单号"> | ||
| 155 | - <el-tag size="mini">{{ refundDetail.merchantRefundNo }}</el-tag> | 141 | + <el-descriptions-item label="商户支付单号"> |
| 142 | + <el-tag size="small">{{ refundDetail.merchantOrderId }}</el-tag> | ||
| 156 | </el-descriptions-item> | 143 | </el-descriptions-item> |
| 157 | - <el-descriptions-item label="商户订单号">{{ refundDetail.merchantOrderId }}</el-descriptions-item> | ||
| 158 | - <el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item> | 144 | + <el-descriptions-item label="渠道支付单号"> |
| 145 | + <el-tag type="success" size="small">{{ refundDetail.channelOrderNo }}</el-tag> | ||
| 146 | + </el-descriptions-item> | ||
| 147 | + </el-descriptions> | ||
| 148 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 149 | + <el-descriptions-item label="应用编号">{{ refundDetail.appId }}</el-descriptions-item> | ||
| 150 | + <el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item> | ||
| 159 | </el-descriptions> | 151 | </el-descriptions> |
| 160 | - <el-divider></el-divider> | ||
| 161 | <el-descriptions :column="2" label-class-name="desc-label"> | 152 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 162 | <el-descriptions-item label="支付金额"> | 153 | <el-descriptions-item label="支付金额"> |
| 163 | - {{ parseFloat(refundDetail.payPrice / 100).toFixed(2) }} | 154 | + <el-tag type="success" size="small">¥{{ (refundDetail.payPrice / 100.0).toFixed(2) }}</el-tag> |
| 164 | </el-descriptions-item> | 155 | </el-descriptions-item> |
| 165 | - <el-descriptions-item label="退款金额" size="mini"> | ||
| 166 | - <el-tag class="tag-purple" size="mini">{{ parseFloat(refundDetail.refundPrice / 100).toFixed(2) }}</el-tag> | ||
| 167 | - </el-descriptions-item> | ||
| 168 | - <el-descriptions-item label="退款类型"> | ||
| 169 | - <template v-slot="scope"> | ||
| 170 | - <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="refundDetail.type" /> | ||
| 171 | - </template> | 156 | + <el-descriptions-item label="退款金额"> |
| 157 | + <el-tag size="mini" type="danger">¥{{ (refundDetail.refundPrice / 100.0).toFixed(2) }}</el-tag> | ||
| 172 | </el-descriptions-item> | 158 | </el-descriptions-item> |
| 159 | + </el-descriptions> | ||
| 160 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 173 | <el-descriptions-item label="退款状态"> | 161 | <el-descriptions-item label="退款状态"> |
| 174 | - <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="refundDetail.status" /> | 162 | + <dict-tag :type="DICT_TYPE.PAY_REFUND_STATUS" :value="refundDetail.status" /> |
| 175 | </el-descriptions-item> | 163 | </el-descriptions-item> |
| 164 | + <el-descriptions-item label="退款时间">{{ parseTime(refundDetail.successTime) }}</el-descriptions-item> | ||
| 165 | + </el-descriptions> | ||
| 166 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 176 | <el-descriptions-item label="创建时间">{{ parseTime(refundDetail.createTime) }}</el-descriptions-item> | 167 | <el-descriptions-item label="创建时间">{{ parseTime(refundDetail.createTime) }}</el-descriptions-item> |
| 177 | - <el-descriptions-item label="退款成功时间">{{ parseTime(refundDetail.successTime) }}</el-descriptions-item> | ||
| 178 | - <el-descriptions-item label="退款失效时间">{{ parseTime(refundDetail.expireTime) }}</el-descriptions-item> | ||
| 179 | <el-descriptions-item label="更新时间">{{ parseTime(refundDetail.updateTime) }}</el-descriptions-item> | 168 | <el-descriptions-item label="更新时间">{{ parseTime(refundDetail.updateTime) }}</el-descriptions-item> |
| 180 | </el-descriptions> | 169 | </el-descriptions> |
| 181 | - <el-divider></el-divider> | 170 | + <!-- 分割线 --> |
| 171 | + <el-divider /> | ||
| 182 | <el-descriptions :column="2" label-class-name="desc-label"> | 172 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 183 | - <el-descriptions-item label="支付渠道"> | ||
| 184 | - {{ refundDetail.channelCodeName }} | ||
| 185 | - </el-descriptions-item> | ||
| 186 | - <el-descriptions-item label="支付IP" size="mini"> | ||
| 187 | - {{refundDetail.userIp}} | ||
| 188 | - </el-descriptions-item> | ||
| 189 | - <el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item> | ||
| 190 | - <el-descriptions-item label="回调状态"> | ||
| 191 | - <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="refundDetail.notifyStatus" /> | 173 | + <el-descriptions-item label="退款渠道"> |
| 174 | + <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE" :value="refundDetail.channelCode" /> | ||
| 192 | </el-descriptions-item> | 175 | </el-descriptions-item> |
| 193 | - <el-descriptions-item label="回调时间">{{ parseTime(refundDetail.notifyTime) }}</el-descriptions-item> | 176 | + <el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item> |
| 177 | + </el-descriptions> | ||
| 178 | + <el-descriptions :column="2" label-class-name="desc-label"> | ||
| 179 | + <el-descriptions-item label="退款 IP">{{ refundDetail.userIp }}</el-descriptions-item> | ||
| 180 | + <el-descriptions-item label="通知 URL">{{ refundDetail.notifyUrl }}</el-descriptions-item> | ||
| 194 | </el-descriptions> | 181 | </el-descriptions> |
| 195 | - <el-divider></el-divider> | 182 | + <!-- 分割线 --> |
| 183 | + <el-divider /> | ||
| 196 | <el-descriptions :column="2" label-class-name="desc-label"> | 184 | <el-descriptions :column="2" label-class-name="desc-label"> |
| 197 | - <el-descriptions-item label="渠道订单号">{{ refundDetail.channelOrderNo }}</el-descriptions-item> | ||
| 198 | - <el-descriptions-item label="渠道退款单号">{{ refundDetail.channelRefundNo }}</el-descriptions-item> | ||
| 199 | <el-descriptions-item label="渠道错误码">{{refundDetail.channelErrorCode}}</el-descriptions-item> | 185 | <el-descriptions-item label="渠道错误码">{{refundDetail.channelErrorCode}}</el-descriptions-item> |
| 200 | <el-descriptions-item label="渠道错误码描述">{{refundDetail.channelErrorMsg}}</el-descriptions-item> | 186 | <el-descriptions-item label="渠道错误码描述">{{refundDetail.channelErrorMsg}}</el-descriptions-item> |
| 201 | </el-descriptions> | 187 | </el-descriptions> |
| 202 | - <br> | ||
| 203 | <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> | 188 | <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> |
| 204 | - <el-descriptions-item label="渠道额外参数">{{ refundDetail.channelExtras }}</el-descriptions-item> | ||
| 205 | - <el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item> | 189 | + <el-descriptions-item label="支付通道异步回调内容"> |
| 190 | + {{ refundDetail.channelNotifyData }} | ||
| 191 | + </el-descriptions-item> | ||
| 206 | </el-descriptions> | 192 | </el-descriptions> |
| 207 | </el-dialog> | 193 | </el-dialog> |
| 208 | </div> | 194 | </div> |
| 209 | </template> | 195 | </template> |
| 210 | 196 | ||
| 211 | <script> | 197 | <script> |
| 212 | -import {getRefundPage, exportRefundExcel, getRefund} from "@/api/pay/refund"; | ||
| 213 | -import { DICT_TYPE, getDictDatas } from "@/utils/dict"; | ||
| 214 | -import { PayOrderRefundStatusEnum, PayRefundStatusEnum } from "@/utils/constants"; | ||
| 215 | -import { getNowDateTime } from "@/utils/ruoyi"; | ||
| 216 | - | ||
| 217 | -const defaultRefundDetail = { | ||
| 218 | - id: null, | ||
| 219 | - appId: null, | ||
| 220 | - appName: '', | ||
| 221 | - channelCode: '', | ||
| 222 | - channelCodeName: '', | ||
| 223 | - channelErrorCode: '', | ||
| 224 | - channelErrorMsg: '', | ||
| 225 | - channelExtras: '', | ||
| 226 | - channelId: null, | ||
| 227 | - channelOrderNo: '', | ||
| 228 | - channelRefundNo: '', | ||
| 229 | - createTime: null, | ||
| 230 | - expireTime: null, | ||
| 231 | - merchantOrderId: '', | ||
| 232 | - merchantRefundNo: '', | ||
| 233 | - notifyStatus: null, | ||
| 234 | - notifyTime: null, | ||
| 235 | - notifyUrl: '', | ||
| 236 | - orderId: null, | ||
| 237 | - payPrice: null, | ||
| 238 | - reason: '', | ||
| 239 | - refundPrice: null, | ||
| 240 | - status: null, | ||
| 241 | - subject: '', | ||
| 242 | - successTime: null, | ||
| 243 | - tradeNo: '', | ||
| 244 | - type: null, | ||
| 245 | - userIp: '' | ||
| 246 | -} | 198 | +import { getRefundPage, exportRefundExcel, getRefund } from "@/api/pay/refund"; |
| 199 | +import { getAppList } from "@/api/pay/app"; | ||
| 247 | 200 | ||
| 248 | export default { | 201 | export default { |
| 249 | name: "PayRefund", | 202 | name: "PayRefund", |
| @@ -267,73 +220,30 @@ export default { | @@ -267,73 +220,30 @@ export default { | ||
| 267 | pageNo: 1, | 220 | pageNo: 1, |
| 268 | pageSize: 10, | 221 | pageSize: 10, |
| 269 | appId: null, | 222 | appId: null, |
| 270 | - channelId: null, | ||
| 271 | channelCode: null, | 223 | channelCode: null, |
| 272 | - orderId: null, | ||
| 273 | - tradeNo: null, | ||
| 274 | merchantOrderId: null, | 224 | merchantOrderId: null, |
| 275 | - merchantRefundNo: null, | ||
| 276 | - notifyUrl: null, | ||
| 277 | - notifyStatus: null, | ||
| 278 | - status: null, | ||
| 279 | - type: null, | ||
| 280 | - payPrice: null, | ||
| 281 | - refundPrice: null, | ||
| 282 | - reason: null, | ||
| 283 | - userIp: null, | 225 | + merchantRefundId: null, |
| 284 | channelOrderNo: null, | 226 | channelOrderNo: null, |
| 285 | channelRefundNo: null, | 227 | channelRefundNo: null, |
| 286 | - channelErrorCode: null, | ||
| 287 | - channelErrorMsg: null, | ||
| 288 | - channelExtras: null, | ||
| 289 | - expireTime: [], | ||
| 290 | - successTime: [], | ||
| 291 | - notifyTime: [], | 228 | + status: null, |
| 292 | createTime: [] | 229 | createTime: [] |
| 293 | }, | 230 | }, |
| 294 | - // 商户加载遮罩层 | ||
| 295 | - merchantLoading: false, | ||
| 296 | - // 商户列表集合 | ||
| 297 | - merchantList: null, | ||
| 298 | // 支付应用列表集合 | 231 | // 支付应用列表集合 |
| 299 | - appList: null, | ||
| 300 | - // 支付渠道编码字典数据集合 | ||
| 301 | - payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE), | ||
| 302 | - // 订单退款状态字典数据集合 | ||
| 303 | - payRefundOrderDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_STATUS), | ||
| 304 | - // 退款订单类别字典数据集合 | ||
| 305 | - payRefundOrderTypeDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_TYPE), | ||
| 306 | - // 订单回调商户状态字典数据集合 | ||
| 307 | - payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS), | ||
| 308 | - // el-tag订单退款状态type值 | ||
| 309 | - refundStatusType: '', | 232 | + appList: [], |
| 310 | // 退款订单详情 | 233 | // 退款订单详情 |
| 311 | - refundDetail: JSON.parse(JSON.stringify(defaultRefundDetail)), | 234 | + refundDetail: {}, |
| 312 | }; | 235 | }; |
| 313 | }, | 236 | }, |
| 314 | created() { | 237 | created() { |
| 315 | - this.initTime(); | ||
| 316 | this.getList(); | 238 | this.getList(); |
| 317 | - this.handleGetMerchantListByName(null); | 239 | + // 获得筛选项 |
| 240 | + getAppList().then(response => { | ||
| 241 | + this.appList = response.data; | ||
| 242 | + }) | ||
| 318 | }, | 243 | }, |
| 319 | methods: { | 244 | methods: { |
| 320 | - initTime(){ | ||
| 321 | - this.queryParams.createTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")]; | ||
| 322 | - }, | ||
| 323 | /** 查询列表 */ | 245 | /** 查询列表 */ |
| 324 | getList() { | 246 | getList() { |
| 325 | - // 判断选择的日期是否超过了一个月 | ||
| 326 | - let oneMonthTime = 31 * 24 * 3600 * 1000; | ||
| 327 | - if (this.queryParams.createTime == null){ | ||
| 328 | - this.initTime(); | ||
| 329 | - } else { | ||
| 330 | - let minDateTime = new Date(this.queryParams.createTime[0]).getTime(); | ||
| 331 | - let maxDateTime = new Date(this.queryParams.createTime[1]).getTime() | ||
| 332 | - if (maxDateTime - minDateTime > oneMonthTime) { | ||
| 333 | - this.$message.error('时间范围最大为 31 天!'); | ||
| 334 | - return false; | ||
| 335 | - } | ||
| 336 | - } | ||
| 337 | this.loading = true; | 247 | this.loading = true; |
| 338 | // 执行查询 | 248 | // 执行查询 |
| 339 | getRefundPage(this.queryParams).then(response => { | 249 | getRefundPage(this.queryParams).then(response => { |
| @@ -369,60 +279,13 @@ export default { | @@ -369,60 +279,13 @@ export default { | ||
| 369 | this.$download.excel(response, '退款订单.xls'); | 279 | this.$download.excel(response, '退款订单.xls'); |
| 370 | }).catch(() => {}); | 280 | }).catch(() => {}); |
| 371 | }, | 281 | }, |
| 372 | - /** | ||
| 373 | - * 根据商户名称模糊匹配商户信息 | ||
| 374 | - * @param name 商户名称 | ||
| 375 | - */ | ||
| 376 | - handleGetMerchantListByName(name) { | ||
| 377 | - getMerchantListByName(name).then(response => { | ||
| 378 | - this.merchantList = response.data; | ||
| 379 | - this.merchantLoading = false; | ||
| 380 | - }); | ||
| 381 | - }, | ||
| 382 | - /** | ||
| 383 | - * 根据退款类别得到样式名称 | ||
| 384 | - * @param refundType 退款类别 | ||
| 385 | - */ | ||
| 386 | - findByRefundTypeGetStyle(refundType) { | ||
| 387 | - switch (refundType) { | ||
| 388 | - case PayOrderRefundStatusEnum.NO.status: | ||
| 389 | - return "success"; | ||
| 390 | - case PayOrderRefundStatusEnum.SOME.status: | ||
| 391 | - return "warning"; | ||
| 392 | - case PayOrderRefundStatusEnum.ALL.status: | ||
| 393 | - return "danger"; | ||
| 394 | - } | ||
| 395 | - }, | ||
| 396 | - /** | ||
| 397 | - * 根据退款状态得到样式名称 | ||
| 398 | - * @param refundStatus 退款状态 | ||
| 399 | - */ | ||
| 400 | - findByRefundStatusGetStyle(refundStatus) { | ||
| 401 | - switch (refundStatus) { | ||
| 402 | - case PayRefundStatusEnum.CREATE.status: | ||
| 403 | - return "info"; | ||
| 404 | - case PayRefundStatusEnum.SUCCESS.status: | ||
| 405 | - return "success"; | ||
| 406 | - case PayRefundStatusEnum.FAILURE.status: | ||
| 407 | - case PayRefundStatusEnum.CLOSE.status: | ||
| 408 | - return "danger"; | ||
| 409 | - case PayRefundStatusEnum.PROCESSING_NOTIFY.status: | ||
| 410 | - case PayRefundStatusEnum.PROCESSING_QUERY.status: | ||
| 411 | - case PayRefundStatusEnum.UNKNOWN_RETRY.status: | ||
| 412 | - case PayRefundStatusEnum.UNKNOWN_QUERY.status: | ||
| 413 | - return "warning"; | ||
| 414 | - } | ||
| 415 | - }, | ||
| 416 | - /** | ||
| 417 | - * 查看订单详情 | ||
| 418 | - */ | 282 | + /** 详情按钮操作 */ |
| 419 | handleQueryDetails(row) { | 283 | handleQueryDetails(row) { |
| 420 | - this.refundDetail = JSON.parse(JSON.stringify(defaultRefundDetail)); | 284 | + this.refundDetail = {}; |
| 421 | getRefund(row.id).then(response => { | 285 | getRefund(row.id).then(response => { |
| 422 | this.refundDetail = response.data; | 286 | this.refundDetail = response.data; |
| 423 | this.open = true; | 287 | this.open = true; |
| 424 | }); | 288 | }); |
| 425 | - | ||
| 426 | }, | 289 | }, |
| 427 | } | 290 | } |
| 428 | }; | 291 | }; |