Commit 6f475f8c85cdad39c733579872b402b700139bb8
1 parent
7cf4c541
mall + pay:
1. 优化 PayClient 支付逻辑,返回业务失败 errorCode + errorMsg 错误码
Showing
29 changed files
with
361 additions
and
292 deletions
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 5 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| 7 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |
| 8 | 7 | ||
| @@ -30,7 +29,7 @@ public interface PayClient { | @@ -30,7 +29,7 @@ public interface PayClient { | ||
| 30 | * @param reqDTO 下单信息 | 29 | * @param reqDTO 下单信息 |
| 31 | * @return 各支付渠道的返回结果 | 30 | * @return 各支付渠道的返回结果 |
| 32 | */ | 31 | */ |
| 33 | - PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO); | 32 | + PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO); |
| 34 | 33 | ||
| 35 | /** | 34 | /** |
| 36 | * 解析 order 回调数据 | 35 | * 解析 order 回调数据 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/order/PayOrderRespDTO.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.dto.order; | 1 | package cn.iocoder.yudao.framework.pay.core.client.dto.order; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.exception.PayException; | ||
| 4 | +import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; | 5 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; |
| 4 | -import lombok.AllArgsConstructor; | ||
| 5 | -import lombok.Builder; | ||
| 6 | import lombok.Data; | 6 | import lombok.Data; |
| 7 | -import lombok.NoArgsConstructor; | ||
| 8 | 7 | ||
| 9 | import java.time.LocalDateTime; | 8 | import java.time.LocalDateTime; |
| 10 | 9 | ||
| @@ -14,9 +13,6 @@ import java.time.LocalDateTime; | @@ -14,9 +13,6 @@ import java.time.LocalDateTime; | ||
| 14 | * @author 芋道源码 | 13 | * @author 芋道源码 |
| 15 | */ | 14 | */ |
| 16 | @Data | 15 | @Data |
| 17 | -@Builder | ||
| 18 | -@NoArgsConstructor | ||
| 19 | -@AllArgsConstructor | ||
| 20 | public class PayOrderRespDTO { | 16 | public class PayOrderRespDTO { |
| 21 | 17 | ||
| 22 | /** | 18 | /** |
| @@ -48,8 +44,94 @@ public class PayOrderRespDTO { | @@ -48,8 +44,94 @@ public class PayOrderRespDTO { | ||
| 48 | private LocalDateTime successTime; | 44 | private LocalDateTime successTime; |
| 49 | 45 | ||
| 50 | /** | 46 | /** |
| 51 | - * 原始的异步通知结果 | 47 | + * 原始的同步/异步通知结果 |
| 52 | */ | 48 | */ |
| 53 | private Object rawData; | 49 | private Object rawData; |
| 54 | 50 | ||
| 51 | + // ========== 主动发起支付时,会返回的字段 ========== | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * 展示模式 | ||
| 55 | + * | ||
| 56 | + * 枚举 {@link PayOrderDisplayModeEnum} 类 | ||
| 57 | + */ | ||
| 58 | + private String displayMode; | ||
| 59 | + /** | ||
| 60 | + * 展示内容 | ||
| 61 | + */ | ||
| 62 | + private String displayContent; | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 调用渠道的错误码 | ||
| 66 | + * | ||
| 67 | + * 注意:这里返回的是业务异常,而是不系统异常。 | ||
| 68 | + * 如果是系统异常,则会抛出 {@link PayException} | ||
| 69 | + */ | ||
| 70 | + private String channelErrorCode; | ||
| 71 | + /** | ||
| 72 | + * 调用渠道报错时,错误信息 | ||
| 73 | + */ | ||
| 74 | + private String channelErrorMsg; | ||
| 75 | + | ||
| 76 | + public PayOrderRespDTO() { | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 创建【WAITING】状态的订单返回 | ||
| 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; | ||
| 87 | + // 相对通用的字段 | ||
| 88 | + this.outTradeNo = outTradeNo; | ||
| 89 | + this.rawData = rawData; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * 创建【SUCCESS】状态的订单返回 | ||
| 94 | + */ | ||
| 95 | + public PayOrderRespDTO(String channelOrderNo, String channelUserId, LocalDateTime successTime, | ||
| 96 | + String outTradeNo, Object rawData) { | ||
| 97 | + this.status = PayOrderStatusRespEnum.SUCCESS.getStatus(); | ||
| 98 | + this.channelOrderNo = channelOrderNo; | ||
| 99 | + this.channelUserId = channelUserId; | ||
| 100 | + this.successTime = successTime; | ||
| 101 | + // 相对通用的字段 | ||
| 102 | + this.outTradeNo = outTradeNo; | ||
| 103 | + this.rawData = rawData; | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 创建【SUCCESS】或【CLOSED】状态的订单返回,适合支付渠道回调时 | ||
| 108 | + */ | ||
| 109 | + public PayOrderRespDTO(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime, | ||
| 110 | + String outTradeNo, Object rawData) { | ||
| 111 | + this.status = status; | ||
| 112 | + this.channelOrderNo = channelOrderNo; | ||
| 113 | + this.channelUserId = channelUserId; | ||
| 114 | + this.successTime = successTime; | ||
| 115 | + // 相对通用的字段 | ||
| 116 | + this.outTradeNo = outTradeNo; | ||
| 117 | + this.rawData = rawData; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * 创建【CLOSED】状态的订单返回,适合调用支付渠道失败时 | ||
| 122 | + * | ||
| 123 | + * 参数和 {@link #PayOrderRespDTO(String, String, String, Object)} 冲突,所以独立个方法出来 | ||
| 124 | + */ | ||
| 125 | + public static PayOrderRespDTO build(String channelErrorCode, String channelErrorMsg, | ||
| 126 | + String outTradeNo, Object rawData) { | ||
| 127 | + PayOrderRespDTO respDTO = new PayOrderRespDTO(); | ||
| 128 | + respDTO.status = PayOrderStatusRespEnum.CLOSED.getStatus(); | ||
| 129 | + respDTO.channelErrorCode = channelErrorCode; | ||
| 130 | + respDTO.channelErrorMsg = channelErrorMsg; | ||
| 131 | + // 相对通用的字段 | ||
| 132 | + respDTO.outTradeNo = outTradeNo; | ||
| 133 | + respDTO.rawData = rawData; | ||
| 134 | + return respDTO; | ||
| 135 | + } | ||
| 136 | + | ||
| 55 | } | 137 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/order/PayOrderUnifiedReqDTO.java
| @@ -43,7 +43,6 @@ public class PayOrderUnifiedReqDTO { | @@ -43,7 +43,6 @@ public class PayOrderUnifiedReqDTO { | ||
| 43 | /** | 43 | /** |
| 44 | * 商品描述信息 | 44 | * 商品描述信息 |
| 45 | */ | 45 | */ |
| 46 | - @NotEmpty(message = "商品描述信息不能为空") | ||
| 47 | @Length(max = 128, message = "商品描述信息长度不能超过128") | 46 | @Length(max = 128, message = "商品描述信息长度不能超过128") |
| 48 | private String body; | 47 | private String body; |
| 49 | /** | 48 | /** |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/order/PayOrderUnifiedRespDTO.java deleted
| 1 | -package cn.iocoder.yudao.framework.pay.core.client.dto.order; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | ||
| 4 | -import lombok.Data; | ||
| 5 | - | ||
| 6 | -/** | ||
| 7 | - * 统一下单 Response DTO | ||
| 8 | - * | ||
| 9 | - * @author 芋道源码 | ||
| 10 | - */ | ||
| 11 | -@Data | ||
| 12 | -public class PayOrderUnifiedRespDTO { | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * 展示模式 | ||
| 16 | - * | ||
| 17 | - * 枚举 {@link PayOrderDisplayModeEnum} 类 | ||
| 18 | - */ | ||
| 19 | - private String displayMode; | ||
| 20 | - /** | ||
| 21 | - * 展示内容 | ||
| 22 | - */ | ||
| 23 | - private String displayContent; | ||
| 24 | - | ||
| 25 | - /** | ||
| 26 | - * 渠道支付订单 | ||
| 27 | - * | ||
| 28 | - * 只有在订单直接支付成功时,才会进行返回。 | ||
| 29 | - * 目前只有 bar 条码支付才会出现,它是支付发起时,直接返回是否支付成功的,而其它支付还是异步通知 | ||
| 30 | - */ | ||
| 31 | - private PayOrderRespDTO order; | ||
| 32 | - | ||
| 33 | - public PayOrderUnifiedRespDTO(String displayMode, String displayContent) { | ||
| 34 | - this.displayMode = displayMode; | ||
| 35 | - this.displayContent = displayContent; | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | -} |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 3 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 4 | +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; | ||
| 4 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; | 5 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 5 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; | 6 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 7 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 7 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |
| 10 | import cn.iocoder.yudao.framework.pay.core.client.exception.PayException; | 11 | import cn.iocoder.yudao.framework.pay.core.client.exception.PayException; |
| 11 | import lombok.extern.slf4j.Slf4j; | 12 | import lombok.extern.slf4j.Slf4j; |
| 12 | 13 | ||
| 13 | -import javax.validation.Validation; | 14 | +import java.util.Map; |
| 14 | 15 | ||
| 15 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 16 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 16 | 17 | ||
| @@ -29,6 +30,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -29,6 +30,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 29 | /** | 30 | /** |
| 30 | * 渠道编码 | 31 | * 渠道编码 |
| 31 | */ | 32 | */ |
| 33 | + @SuppressWarnings("FieldCanBeLocal") | ||
| 32 | private final String channelCode; | 34 | private final String channelCode; |
| 33 | /** | 35 | /** |
| 34 | * 支付配置 | 36 | * 支付配置 |
| @@ -73,31 +75,42 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -73,31 +75,42 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 73 | // ============ 支付相关 ========== | 75 | // ============ 支付相关 ========== |
| 74 | 76 | ||
| 75 | @Override | 77 | @Override |
| 76 | - public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { | ||
| 77 | - Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); | 78 | + public final PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 79 | + ValidationUtils.validate(reqDTO); | ||
| 78 | // 执行统一下单 | 80 | // 执行统一下单 |
| 79 | - PayOrderUnifiedRespDTO resp; | 81 | + PayOrderRespDTO resp; |
| 80 | try { | 82 | try { |
| 81 | resp = doUnifiedOrder(reqDTO); | 83 | resp = doUnifiedOrder(reqDTO); |
| 82 | - } catch (ServiceException ex) { | ||
| 83 | - // 业务异常,都是实现类已经翻译,所以直接抛出即可 | ||
| 84 | - throw ex; | ||
| 85 | } catch (Throwable ex) { | 84 | } catch (Throwable ex) { |
| 86 | // 系统异常,则包装成 PayException 异常抛出 | 85 | // 系统异常,则包装成 PayException 异常抛出 |
| 87 | - log.error("[unifiedRefund][request({}) 发起支付异常]", toJsonString(reqDTO), ex); | ||
| 88 | - throw buildException(ex); | 86 | + log.error("[unifiedRefund][客户端({}) request({}) 发起支付异常]", |
| 87 | + getId(), toJsonString(reqDTO), ex); | ||
| 88 | + throw buildPayException(ex); | ||
| 89 | } | 89 | } |
| 90 | return resp; | 90 | return resp; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | - protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) | 93 | + protected abstract PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) |
| 94 | + throws Throwable; | ||
| 95 | + | ||
| 96 | + @Override | ||
| 97 | + public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) { | ||
| 98 | + try { | ||
| 99 | + return doParseOrderNotify(params, body); | ||
| 100 | + } catch (Throwable ex) { | ||
| 101 | + log.error("[parseOrderNotify][params({}) body({}) 解析失败]", params, body, ex); | ||
| 102 | + throw buildPayException(ex); | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + protected abstract PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) | ||
| 94 | throws Throwable; | 107 | throws Throwable; |
| 95 | 108 | ||
| 96 | // ============ 退款相关 ========== | 109 | // ============ 退款相关 ========== |
| 97 | 110 | ||
| 98 | @Override | 111 | @Override |
| 99 | public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) { | 112 | public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) { |
| 100 | - Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); | 113 | + ValidationUtils.validate(reqDTO); |
| 101 | // 执行统一退款 | 114 | // 执行统一退款 |
| 102 | PayRefundRespDTO resp; | 115 | PayRefundRespDTO resp; |
| 103 | try { | 116 | try { |
| @@ -107,8 +120,9 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -107,8 +120,9 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 107 | throw ex; | 120 | throw ex; |
| 108 | } catch (Throwable ex) { | 121 | } catch (Throwable ex) { |
| 109 | // 系统异常,则包装成 PayException 异常抛出 | 122 | // 系统异常,则包装成 PayException 异常抛出 |
| 110 | - log.error("[unifiedRefund][request({}) 发起退款异常]", toJsonString(reqDTO), ex); | ||
| 111 | - throw buildException(ex); | 123 | + log.error("[unifiedRefund][客户端({}) request({}) 发起退款异常]", |
| 124 | + getId(), toJsonString(reqDTO), ex); | ||
| 125 | + throw buildPayException(ex); | ||
| 112 | } | 126 | } |
| 113 | return resp; | 127 | return resp; |
| 114 | } | 128 | } |
| @@ -117,7 +131,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -117,7 +131,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 117 | 131 | ||
| 118 | // ========== 各种工具方法 ========== | 132 | // ========== 各种工具方法 ========== |
| 119 | 133 | ||
| 120 | - private PayException buildException(Throwable ex) { | 134 | + private PayException buildPayException(Throwable ex) { |
| 121 | if (ex instanceof PayException) { | 135 | if (ex instanceof PayException) { |
| 122 | return (PayException) ex; | 136 | return (PayException) ex; |
| 123 | } | 137 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
| @@ -5,8 +5,8 @@ import cn.hutool.core.date.LocalDateTimeUtil; | @@ -5,8 +5,8 @@ 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.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 7 | import cn.hutool.http.HttpUtil; | 7 | import cn.hutool.http.HttpUtil; |
| 8 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 9 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | ||
| 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| 11 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | 11 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |
| 12 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; | 12 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |
| @@ -29,9 +29,7 @@ import java.util.Objects; | @@ -29,9 +29,7 @@ import java.util.Objects; | ||
| 29 | import java.util.function.Supplier; | 29 | import java.util.function.Supplier; |
| 30 | 30 | ||
| 31 | import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; | 31 | import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; |
| 32 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; | ||
| 33 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 32 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 34 | -import static cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants.ORDER_UNIFIED_ERROR; | ||
| 35 | 33 | ||
| 36 | /** | 34 | /** |
| 37 | * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款) | 35 | * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款) |
| @@ -55,6 +53,40 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -55,6 +53,40 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 55 | this.client = new DefaultAlipayClient(alipayConfig); | 53 | this.client = new DefaultAlipayClient(alipayConfig); |
| 56 | } | 54 | } |
| 57 | 55 | ||
| 56 | + // ============ 支付相关 ========== | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 构造支付关闭的 {@link PayOrderRespDTO} 对象 | ||
| 60 | + * | ||
| 61 | + * @return 支付关闭的 {@link PayOrderRespDTO} 对象 | ||
| 62 | + */ | ||
| 63 | + protected PayOrderRespDTO buildClosedPayOrderRespDTO(PayOrderUnifiedReqDTO reqDTO, AlipayResponse response) { | ||
| 64 | + Assert.isFalse(response.isSuccess()); | ||
| 65 | + return PayOrderRespDTO.build(response.getSubCode(), response.getSubMsg(), | ||
| 66 | + reqDTO.getOutTradeNo(), response); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws Throwable { | ||
| 71 | + // 1. 校验回调数据 | ||
| 72 | + Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8); | ||
| 73 | + AlipaySignature.rsaCheckV1(bodyObj, config.getAlipayPublicKey(), | ||
| 74 | + StandardCharsets.UTF_8.name(), config.getSignType()); | ||
| 75 | + | ||
| 76 | + // 2. 解析订单的状态 | ||
| 77 | + String tradeStatus = bodyObj.get("trade_status"); | ||
| 78 | + Integer status = Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus() | ||
| 79 | + : Objects.equals("TRADE_SUCCESS", tradeStatus) ? PayOrderStatusRespEnum.SUCCESS.getStatus() | ||
| 80 | + : Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null; | ||
| 81 | + Assert.notNull(status, (Supplier<Throwable>) () -> { | ||
| 82 | + throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body)); | ||
| 83 | + }); | ||
| 84 | + return new PayOrderRespDTO(status, bodyObj.get("trade_no"), bodyObj.get("seller_id"), parseTime(params.get("gmt_payment")), | ||
| 85 | + bodyObj.get("out_trade_no"), body); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + // ============ 退款相关 ========== | ||
| 89 | + | ||
| 58 | /** | 90 | /** |
| 59 | * 支付宝统一的退款接口 alipay.trade.refund | 91 | * 支付宝统一的退款接口 alipay.trade.refund |
| 60 | * | 92 | * |
| @@ -96,32 +128,6 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -96,32 +128,6 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 96 | } | 128 | } |
| 97 | 129 | ||
| 98 | @Override | 130 | @Override |
| 99 | - @SneakyThrows | ||
| 100 | - public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) { | ||
| 101 | - // 1. 校验回调数据 | ||
| 102 | - Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8); | ||
| 103 | - AlipaySignature.rsaCheckV1(bodyObj, config.getAlipayPublicKey(), | ||
| 104 | - StandardCharsets.UTF_8.name(), config.getSignType()); | ||
| 105 | - | ||
| 106 | - // 2. 解析订单的状态 | ||
| 107 | - String tradeStatus = bodyObj.get("trade_status"); | ||
| 108 | - PayOrderStatusRespEnum status = Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING | ||
| 109 | - : Objects.equals("TRADE_SUCCESS", tradeStatus) ? PayOrderStatusRespEnum.SUCCESS | ||
| 110 | - : Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED : null; | ||
| 111 | - Assert.notNull(status, (Supplier<Throwable>) () -> { | ||
| 112 | - throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body)); | ||
| 113 | - }); | ||
| 114 | - return PayOrderRespDTO.builder() | ||
| 115 | - .status(Objects.requireNonNull(status).getStatus()) | ||
| 116 | - .outTradeNo(bodyObj.get("out_trade_no")) | ||
| 117 | - .channelOrderNo(bodyObj.get("trade_no")) | ||
| 118 | - .channelUserId(bodyObj.get("seller_id")) | ||
| 119 | - .successTime(parseTime(params.get("gmt_payment"))) | ||
| 120 | - .rawData(body) | ||
| 121 | - .build(); | ||
| 122 | - } | ||
| 123 | - | ||
| 124 | - @Override | ||
| 125 | public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) { | 131 | public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) { |
| 126 | // 补充说明:支付宝退款时,没有回调,这点和微信支付是不同的。并且,退款分成部分退款、和全部退款。 | 132 | // 补充说明:支付宝退款时,没有回调,这点和微信支付是不同的。并且,退款分成部分退款、和全部退款。 |
| 127 | // ① 部分退款:是会有回调,但是它回调的是订单状态的同步回调,不是退款订单的回调 | 133 | // ① 部分退款:是会有回调,但是它回调的是订单状态的同步回调,不是退款订单的回调 |
| @@ -145,21 +151,4 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -145,21 +151,4 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 145 | return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER); | 151 | return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER); |
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | - /** | ||
| 149 | - * 校验支付宝统一下单的响应 | ||
| 150 | - * | ||
| 151 | - * 如果校验不通过,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 异常 | ||
| 152 | - * | ||
| 153 | - * @param request 请求 | ||
| 154 | - * @param response 响应 | ||
| 155 | - */ | ||
| 156 | - protected void validateUnifiedOrderResponse(Object request, AlipayResponse response) { | ||
| 157 | - if (response.isSuccess()) { | ||
| 158 | - return; | ||
| 159 | - } | ||
| 160 | - log.error("[validateUnifiedOrderResponse][发起支付失败,request({}),response({})]", | ||
| 161 | - JsonUtils.toJsonString(request), JsonUtils.toJsonString(response)); | ||
| 162 | - throw exception0(ORDER_UNIFIED_ERROR.getCode(), response.getSubMsg()); | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | } | 154 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 4 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 5 | 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.pay.core.enums.order.PayOrderDisplayModeEnum; | 6 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 7 | import com.alipay.api.AlipayApiException; | 7 | import com.alipay.api.AlipayApiException; |
| @@ -27,7 +27,7 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { | @@ -27,7 +27,7 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { | ||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | @Override | 29 | @Override |
| 30 | - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { | 30 | + public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 31 | // 1.1 构建 AlipayTradeAppPayModel 请求 | 31 | // 1.1 构建 AlipayTradeAppPayModel 请求 |
| 32 | AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); | 32 | AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); |
| 33 | // ① 通用的参数 | 33 | // ① 通用的参数 |
| @@ -49,8 +49,11 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { | @@ -49,8 +49,11 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { | ||
| 49 | // 2.1 执行请求 | 49 | // 2.1 执行请求 |
| 50 | AlipayTradeAppPayResponse response = client.execute(request); | 50 | AlipayTradeAppPayResponse response = client.execute(request); |
| 51 | // 2.2 处理结果 | 51 | // 2.2 处理结果 |
| 52 | - validateUnifiedOrderResponse(request, response); | ||
| 53 | - return new PayOrderUnifiedRespDTO(displayMode, ""); | 52 | + if (!response.isSuccess()) { |
| 53 | + return buildClosedPayOrderRespDTO(reqDTO, response); | ||
| 54 | + } | ||
| 55 | + return new PayOrderRespDTO(displayMode, "", | ||
| 56 | + reqDTO.getOutTradeNo(), response); | ||
| 54 | } | 57 | } |
| 55 | 58 | ||
| 56 | } | 59 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java
| @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.map.MapUtil; | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 6 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 7 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 7 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 8 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | 8 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 9 | import com.alipay.api.AlipayApiException; | 9 | import com.alipay.api.AlipayApiException; |
| @@ -30,7 +30,7 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { | @@ -30,7 +30,7 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { | ||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | @Override | 32 | @Override |
| 33 | - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { | 33 | + public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 34 | String authCode = MapUtil.getStr(reqDTO.getChannelExtras(), "auth_code"); | 34 | String authCode = MapUtil.getStr(reqDTO.getChannelExtras(), "auth_code"); |
| 35 | if (StrUtil.isEmpty(authCode)) { | 35 | if (StrUtil.isEmpty(authCode)) { |
| 36 | throw exception0(BAD_REQUEST.getCode(), "条形码不能为空"); | 36 | throw exception0(BAD_REQUEST.getCode(), "条形码不能为空"); |
| @@ -55,11 +55,15 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { | @@ -55,11 +55,15 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { | ||
| 55 | request.setNotifyUrl(reqDTO.getNotifyUrl()); | 55 | request.setNotifyUrl(reqDTO.getNotifyUrl()); |
| 56 | request.setReturnUrl(reqDTO.getReturnUrl()); | 56 | request.setReturnUrl(reqDTO.getReturnUrl()); |
| 57 | 57 | ||
| 58 | + // TODO 芋艿:各种边界的处理 | ||
| 58 | // 2.1 执行请求 | 59 | // 2.1 执行请求 |
| 59 | AlipayTradePayResponse response = client.execute(request); | 60 | AlipayTradePayResponse response = client.execute(request); |
| 60 | // 2.2 处理结果 | 61 | // 2.2 处理结果 |
| 61 | - validateUnifiedOrderResponse(request, response); | ||
| 62 | - return new PayOrderUnifiedRespDTO(displayMode, ""); | 62 | + if (!response.isSuccess()) { |
| 63 | + return buildClosedPayOrderRespDTO(reqDTO, response); | ||
| 64 | + } | ||
| 65 | + return new PayOrderRespDTO(displayMode, "", | ||
| 66 | + reqDTO.getOutTradeNo(), response); | ||
| 63 | } | 67 | } |
| 64 | 68 | ||
| 65 | } | 69 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
| @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.ObjectUtil; | 3 | import cn.hutool.core.util.ObjectUtil; |
| 4 | import cn.hutool.http.Method; | 4 | import cn.hutool.http.Method; |
| 5 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 6 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 7 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 7 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 8 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | 8 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 9 | import com.alipay.api.AlipayApiException; | 9 | import com.alipay.api.AlipayApiException; |
| @@ -29,7 +29,7 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { | @@ -29,7 +29,7 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { | ||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | @Override | 31 | @Override |
| 32 | - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { | 32 | + public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 33 | // 1.1 构建 AlipayTradePagePayModel 请求 | 33 | // 1.1 构建 AlipayTradePagePayModel 请求 |
| 34 | AlipayTradePagePayModel model = new AlipayTradePagePayModel(); | 34 | AlipayTradePagePayModel model = new AlipayTradePagePayModel(); |
| 35 | // ① 通用的参数 | 35 | // ① 通用的参数 |
| @@ -60,8 +60,11 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { | @@ -60,8 +60,11 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { | ||
| 60 | response = client.pageExecute(request, Method.GET.name()); | 60 | response = client.pageExecute(request, Method.GET.name()); |
| 61 | } | 61 | } |
| 62 | // 2.2 处理结果 | 62 | // 2.2 处理结果 |
| 63 | - validateUnifiedOrderResponse(request, response); | ||
| 64 | - return new PayOrderUnifiedRespDTO(displayMode, response.getBody()); | 63 | + if (!response.isSuccess()) { |
| 64 | + return buildClosedPayOrderRespDTO(reqDTO, response); | ||
| 65 | + } | ||
| 66 | + return new PayOrderRespDTO(displayMode, response.getBody(), | ||
| 67 | + reqDTO.getOutTradeNo(), response); | ||
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | } | 70 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 4 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 5 | 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.pay.core.enums.order.PayOrderDisplayModeEnum; | 6 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 7 | import com.alipay.api.AlipayApiException; | 7 | import com.alipay.api.AlipayApiException; |
| @@ -25,7 +25,7 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { | @@ -25,7 +25,7 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { | ||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | @Override | 27 | @Override |
| 28 | - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { | 28 | + public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 29 | // 1.1 构建 AlipayTradePrecreateModel 请求 | 29 | // 1.1 构建 AlipayTradePrecreateModel 请求 |
| 30 | AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); | 30 | AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); |
| 31 | // ① 通用的参数 | 31 | // ① 通用的参数 |
| @@ -47,8 +47,11 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { | @@ -47,8 +47,11 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { | ||
| 47 | // 2.1 执行请求 | 47 | // 2.1 执行请求 |
| 48 | AlipayTradePrecreateResponse response = client.execute(request); | 48 | AlipayTradePrecreateResponse response = client.execute(request); |
| 49 | // 2.2 处理结果 | 49 | // 2.2 处理结果 |
| 50 | - validateUnifiedOrderResponse(request, response); | ||
| 51 | - return new PayOrderUnifiedRespDTO(displayMode, response.getQrCode()); | 50 | + if (!response.isSuccess()) { |
| 51 | + return buildClosedPayOrderRespDTO(reqDTO, response); | ||
| 52 | + } | ||
| 53 | + return new PayOrderRespDTO(displayMode, response.getQrCode(), | ||
| 54 | + reqDTO.getOutTradeNo(), response); | ||
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | } | 57 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; |
| 2 | 2 | ||
| 3 | import cn.hutool.http.Method; | 3 | import cn.hutool.http.Method; |
| 4 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 5 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 6 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 6 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 7 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | 7 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 8 | import com.alipay.api.AlipayApiException; | 8 | import com.alipay.api.AlipayApiException; |
| @@ -26,7 +26,7 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { | @@ -26,7 +26,7 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { | ||
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | @Override | 28 | @Override |
| 29 | - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { | 29 | + public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 30 | // 1.1 构建 AlipayTradeWapPayModel 请求 | 30 | // 1.1 构建 AlipayTradeWapPayModel 请求 |
| 31 | AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); | 31 | AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); |
| 32 | // ① 通用的参数 | 32 | // ① 通用的参数 |
| @@ -48,10 +48,12 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { | @@ -48,10 +48,12 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { | ||
| 48 | 48 | ||
| 49 | // 2.1 执行请求 | 49 | // 2.1 执行请求 |
| 50 | AlipayTradeWapPayResponse response = client.pageExecute(request, Method.GET.name()); | 50 | AlipayTradeWapPayResponse response = client.pageExecute(request, Method.GET.name()); |
| 51 | - | ||
| 52 | // 2.2 处理结果 | 51 | // 2.2 处理结果 |
| 53 | - validateUnifiedOrderResponse(request, response); | ||
| 54 | - return new PayOrderUnifiedRespDTO(displayMode, response.getBody()); | 52 | + if (!response.isSuccess()) { |
| 53 | + return buildClosedPayOrderRespDTO(reqDTO, response); | ||
| 54 | + } | ||
| 55 | + return new PayOrderRespDTO(displayMode, response.getBody(), | ||
| 56 | + reqDTO.getOutTradeNo(), response); | ||
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | } | 59 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
| @@ -8,11 +8,9 @@ import cn.hutool.core.util.StrUtil; | @@ -8,11 +8,9 @@ import cn.hutool.core.util.StrUtil; | ||
| 8 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; | 8 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; |
| 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 11 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 12 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | 11 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; |
| 13 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | 12 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |
| 14 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; | 13 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |
| 15 | -import cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants; | ||
| 16 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; | 14 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; |
| 17 | import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | 15 | import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; |
| 18 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; | 16 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| @@ -35,9 +33,6 @@ import java.util.Map; | @@ -35,9 +33,6 @@ import java.util.Map; | ||
| 35 | import java.util.Objects; | 33 | import java.util.Objects; |
| 36 | 34 | ||
| 37 | import static cn.hutool.core.date.DatePattern.*; | 35 | import static cn.hutool.core.date.DatePattern.*; |
| 38 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 39 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; | ||
| 40 | -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||
| 41 | import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V2; | 36 | import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V2; |
| 42 | 37 | ||
| 43 | /** | 38 | /** |
| @@ -83,7 +78,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -83,7 +78,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 83 | // ============ 支付相关 ========== | 78 | // ============ 支付相关 ========== |
| 84 | 79 | ||
| 85 | @Override | 80 | @Override |
| 86 | - protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception { | 81 | + protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception { |
| 87 | try { | 82 | try { |
| 88 | switch (config.getApiVersion()) { | 83 | switch (config.getApiVersion()) { |
| 89 | case API_VERSION_V2: | 84 | case API_VERSION_V2: |
| @@ -94,8 +89,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -94,8 +89,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 94 | throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | 89 | throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); |
| 95 | } | 90 | } |
| 96 | } catch (WxPayException e) { | 91 | } catch (WxPayException e) { |
| 97 | - // todo 芋艿:异常的处理; | ||
| 98 | - throw buildUnifiedOrderException(reqDTO, e); | 92 | + String errorCode = getErrorCode(e); |
| 93 | + String errorMessage = getErrorMessage(e); | ||
| 94 | + return PayOrderRespDTO.build(errorCode, errorMessage, | ||
| 95 | + reqDTO.getOutTradeNo(), e.getXmlString()); | ||
| 99 | } | 96 | } |
| 100 | } | 97 | } |
| 101 | 98 | ||
| @@ -105,8 +102,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -105,8 +102,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 105 | * @param reqDTO 下单信息 | 102 | * @param reqDTO 下单信息 |
| 106 | * @return 各支付渠道的返回结果 | 103 | * @return 各支付渠道的返回结果 |
| 107 | */ | 104 | */ |
| 108 | - protected abstract PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) | ||
| 109 | - throws WxPayException; | 105 | + protected abstract PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) |
| 106 | + throws Exception; | ||
| 110 | 107 | ||
| 111 | /** | 108 | /** |
| 112 | * 【V3】调用支付渠道,统一下单 | 109 | * 【V3】调用支付渠道,统一下单 |
| @@ -114,57 +111,42 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -114,57 +111,42 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 114 | * @param reqDTO 下单信息 | 111 | * @param reqDTO 下单信息 |
| 115 | * @return 各支付渠道的返回结果 | 112 | * @return 各支付渠道的返回结果 |
| 116 | */ | 113 | */ |
| 117 | - protected abstract PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) | 114 | + protected abstract PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) |
| 118 | throws WxPayException; | 115 | throws WxPayException; |
| 119 | 116 | ||
| 120 | @Override | 117 | @Override |
| 121 | - public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) { | ||
| 122 | - try { | ||
| 123 | - // 微信支付 v2 回调结果处理 | ||
| 124 | - switch (config.getApiVersion()) { | ||
| 125 | - case API_VERSION_V2: | ||
| 126 | - return parseOrderNotifyV2(body); | ||
| 127 | - case WxPayClientConfig.API_VERSION_V3: | ||
| 128 | - return parseOrderNotifyV3(body); | ||
| 129 | - default: | ||
| 130 | - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | ||
| 131 | - } | ||
| 132 | - } catch (WxPayException e) { | ||
| 133 | - log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); | ||
| 134 | -// throw buildPayException(e); | ||
| 135 | - throw new RuntimeException(e); | ||
| 136 | - // TODO 芋艿:缺一个异常翻译 | 118 | + public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws WxPayException { |
| 119 | + // 微信支付 v2 回调结果处理 | ||
| 120 | + switch (config.getApiVersion()) { | ||
| 121 | + case API_VERSION_V2: | ||
| 122 | + return doParseOrderNotifyV2(body); | ||
| 123 | + case WxPayClientConfig.API_VERSION_V3: | ||
| 124 | + return doParseOrderNotifyV3(body); | ||
| 125 | + default: | ||
| 126 | + throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | ||
| 137 | } | 127 | } |
| 138 | } | 128 | } |
| 139 | 129 | ||
| 140 | - private PayOrderRespDTO parseOrderNotifyV2(String body) throws WxPayException { | 130 | + private PayOrderRespDTO doParseOrderNotifyV2(String body) throws WxPayException { |
| 141 | // 1. 解析回调 | 131 | // 1. 解析回调 |
| 142 | WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body); | 132 | WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body); |
| 143 | // 2. 构建结果 | 133 | // 2. 构建结果 |
| 144 | - return PayOrderRespDTO.builder() | ||
| 145 | - .outTradeNo(response.getOutTradeNo()) | ||
| 146 | - .channelOrderNo(response.getTransactionId()) | ||
| 147 | - .channelUserId(response.getOpenid()) | ||
| 148 | - .status(Objects.equals(response.getResultCode(), "SUCCESS") ? | ||
| 149 | - PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus()) | ||
| 150 | - .successTime(parseDateV2(response.getTimeEnd())) | ||
| 151 | - .rawData(response) | ||
| 152 | - .build(); | 134 | + Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ? |
| 135 | + PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus(); | ||
| 136 | + return new PayOrderRespDTO(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()), | ||
| 137 | + response.getOutTradeNo(), body); | ||
| 153 | } | 138 | } |
| 154 | 139 | ||
| 155 | - private PayOrderRespDTO parseOrderNotifyV3(String body) throws WxPayException { | 140 | + private PayOrderRespDTO doParseOrderNotifyV3(String body) throws WxPayException { |
| 156 | // 1. 解析回调 | 141 | // 1. 解析回调 |
| 157 | WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null); | 142 | WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null); |
| 158 | - WxPayOrderNotifyV3Result.DecryptNotifyResult responseResult = response.getResult(); | 143 | + WxPayOrderNotifyV3Result.DecryptNotifyResult result = response.getResult(); |
| 159 | // 2. 构建结果 | 144 | // 2. 构建结果 |
| 160 | - return PayOrderRespDTO.builder() | ||
| 161 | - .outTradeNo(responseResult.getOutTradeNo()) | ||
| 162 | - .channelOrderNo(responseResult.getTradeState()) | ||
| 163 | - .channelUserId(responseResult.getPayer() != null ? responseResult.getPayer().getOpenid() : null) | ||
| 164 | - .status(Objects.equals(responseResult.getTradeState(), "SUCCESS") ? | ||
| 165 | - PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus()) | ||
| 166 | - .successTime(parseDateV3(responseResult.getSuccessTime())) | ||
| 167 | - .build(); | 145 | + Integer status = Objects.equals(result.getTradeState(), "SUCCESS") ? |
| 146 | + PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus(); | ||
| 147 | + String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null; | ||
| 148 | + return new PayOrderRespDTO(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()), | ||
| 149 | + result.getOutTradeNo(), body); | ||
| 168 | } | 150 | } |
| 169 | 151 | ||
| 170 | // ============ 退款相关 ========== | 152 | // ============ 退款相关 ========== |
| @@ -182,7 +164,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -182,7 +164,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 182 | } | 164 | } |
| 183 | } catch (WxPayException e) { | 165 | } catch (WxPayException e) { |
| 184 | // todo 芋艿:异常的处理; | 166 | // todo 芋艿:异常的处理; |
| 185 | - throw buildUnifiedOrderException(null, e); | 167 | +// throw buildUnifiedOrderException(null, e); |
| 168 | + return null; | ||
| 186 | } | 169 | } |
| 187 | } | 170 | } |
| 188 | 171 | ||
| @@ -254,7 +237,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -254,7 +237,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 254 | } | 237 | } |
| 255 | } catch (WxPayException e) { | 238 | } catch (WxPayException e) { |
| 256 | log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); | 239 | log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); |
| 257 | -// throw buildPayException(e); | ||
| 258 | throw new RuntimeException(e); | 240 | throw new RuntimeException(e); |
| 259 | // TODO 芋艿:缺一个异常翻译 | 241 | // TODO 芋艿:缺一个异常翻译 |
| 260 | } | 242 | } |
| @@ -300,33 +282,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -300,33 +282,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 300 | 282 | ||
| 301 | // ========== 各种工具方法 ========== | 283 | // ========== 各种工具方法 ========== |
| 302 | 284 | ||
| 303 | - /** | ||
| 304 | - * 构建统一下单的异常 | ||
| 305 | - * | ||
| 306 | - * 目的:将参数不正确等异常,转换成 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常 | ||
| 307 | - * | ||
| 308 | - * @param reqDTO 请求 | ||
| 309 | - * @param e 微信的支付异常 | ||
| 310 | - * @return 转换后的异常 | ||
| 311 | - * | ||
| 312 | - */ | ||
| 313 | - static Exception buildUnifiedOrderException(PayOrderUnifiedReqDTO reqDTO, WxPayException e) { | ||
| 314 | - // 情况一:业务结果为 FAIL | ||
| 315 | - if (Objects.equals(e.getResultCode(), "FAIL")) { | ||
| 316 | - log.error("[buildUnifiedOrderException][request({}) 发起支付失败]", toJsonString(reqDTO), e); | ||
| 317 | - if (Objects.equals(e.getErrCode(), "PARAM_ERROR")) { | ||
| 318 | - throw invalidParamException(e.getErrCodeDes()); | ||
| 319 | - } | ||
| 320 | - throw exception(PayFrameworkErrorCodeConstants.ORDER_UNIFIED_ERROR, e.getErrCodeDes()); | ||
| 321 | - } | ||
| 322 | - // 情况二:状态码结果为 FAIL | ||
| 323 | - if (Objects.equals(e.getReturnCode(), "FAIL")) { | ||
| 324 | - throw exception(PayFrameworkErrorCodeConstants.ORDER_UNIFIED_ERROR, e.getReturnMsg()); | ||
| 325 | - } | ||
| 326 | - // 情况三:系统异常,这里暂时不打,交给上层的 AbstractPayClient 统一打日志 | ||
| 327 | - return e; | ||
| 328 | - } | ||
| 329 | - | ||
| 330 | static String formatDateV2(LocalDateTime time) { | 285 | static String formatDateV2(LocalDateTime time) { |
| 331 | return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), PURE_DATETIME_PATTERN); | 286 | return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), PURE_DATETIME_PATTERN); |
| 332 | } | 287 | } |
| @@ -347,4 +302,24 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -347,4 +302,24 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 347 | return LocalDateTimeUtil.parse(time, UTC_WITH_XXX_OFFSET_PATTERN); | 302 | return LocalDateTimeUtil.parse(time, UTC_WITH_XXX_OFFSET_PATTERN); |
| 348 | } | 303 | } |
| 349 | 304 | ||
| 305 | + static String getErrorCode(WxPayException e) { | ||
| 306 | + if (StrUtil.isNotEmpty(e.getErrCode())) { | ||
| 307 | + return e.getErrCode(); | ||
| 308 | + } | ||
| 309 | + if (StrUtil.isNotEmpty(e.getCustomErrorMsg())) { | ||
| 310 | + return "CUSTOM_ERROR"; | ||
| 311 | + } | ||
| 312 | + return e.getReturnCode(); | ||
| 313 | + } | ||
| 314 | + | ||
| 315 | + static String getErrorMessage(WxPayException e) { | ||
| 316 | + if (StrUtil.isNotEmpty(e.getErrCode())) { | ||
| 317 | + return e.getErrCodeDes(); | ||
| 318 | + } | ||
| 319 | + if (StrUtil.isNotEmpty(e.getCustomErrorMsg())) { | ||
| 320 | + return e.getCustomErrorMsg(); | ||
| 321 | + } | ||
| 322 | + return e.getReturnMsg(); | ||
| 323 | + } | ||
| 324 | + | ||
| 350 | } | 325 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 4 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 5 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 5 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 6 | import com.github.binarywang.wxpay.constant.WxPayConstants; | 6 | import com.github.binarywang.wxpay.constant.WxPayConstants; |
| 7 | import com.github.binarywang.wxpay.exception.WxPayException; | 7 | import com.github.binarywang.wxpay.exception.WxPayException; |
| @@ -19,12 +19,12 @@ public class WxAppPayClient extends AbstractWxPayClient { | @@ -19,12 +19,12 @@ public class WxAppPayClient extends AbstractWxPayClient { | ||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | @Override | 21 | @Override |
| 22 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 22 | + protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 23 | return null; | 23 | return null; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |
| 27 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 27 | + protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 28 | return null; | 28 | return null; |
| 29 | } | 29 | } |
| 30 | 30 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClient.java
| @@ -4,13 +4,10 @@ import cn.hutool.core.map.MapUtil; | @@ -4,13 +4,10 @@ import cn.hutool.core.map.MapUtil; | ||
| 4 | import cn.hutool.core.thread.ThreadUtil; | 4 | import cn.hutool.core.thread.ThreadUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | 6 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 7 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 7 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 10 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 11 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 9 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 12 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | 10 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 13 | -import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; | ||
| 14 | import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest; | 11 | import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest; |
| 15 | import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult; | 12 | import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult; |
| 16 | import com.github.binarywang.wxpay.constant.WxPayConstants; | 13 | import com.github.binarywang.wxpay.constant.WxPayConstants; |
| @@ -22,6 +19,7 @@ import java.time.LocalDateTime; | @@ -22,6 +19,7 @@ import java.time.LocalDateTime; | ||
| 22 | import java.util.concurrent.TimeUnit; | 19 | import java.util.concurrent.TimeUnit; |
| 23 | 20 | ||
| 24 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; |
| 22 | +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||
| 25 | 23 | ||
| 26 | /** | 24 | /** |
| 27 | * 微信支付【付款码支付】的 PayClient 实现类 | 25 | * 微信支付【付款码支付】的 PayClient 实现类 |
| @@ -48,7 +46,7 @@ public class WxBarPayClient extends AbstractWxPayClient { | @@ -48,7 +46,7 @@ public class WxBarPayClient extends AbstractWxPayClient { | ||
| 48 | } | 46 | } |
| 49 | 47 | ||
| 50 | @Override | 48 | @Override |
| 51 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 49 | + protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 52 | // 由于付款码需要不断轮询,所以需要在较短的时间完成支付 | 50 | // 由于付款码需要不断轮询,所以需要在较短的时间完成支付 |
| 53 | LocalDateTime expireTime = LocalDateTimeUtils.addTime(AUTH_CODE_EXPIRE); | 51 | LocalDateTime expireTime = LocalDateTimeUtils.addTime(AUTH_CODE_EXPIRE); |
| 54 | if (expireTime.isAfter(reqDTO.getExpireTime())) { | 52 | if (expireTime.isAfter(reqDTO.getExpireTime())) { |
| @@ -65,22 +63,16 @@ public class WxBarPayClient extends AbstractWxPayClient { | @@ -65,22 +63,16 @@ public class WxBarPayClient extends AbstractWxPayClient { | ||
| 65 | .authCode(getAuthCode(reqDTO)) | 63 | .authCode(getAuthCode(reqDTO)) |
| 66 | .build(); | 64 | .build(); |
| 67 | // 执行请求,重试直到失败(过期),或者成功 | 65 | // 执行请求,重试直到失败(过期),或者成功 |
| 66 | + WxPayException lastWxPayException = null; | ||
| 68 | for (int i = 1; i < Byte.MAX_VALUE; i++) { | 67 | for (int i = 1; i < Byte.MAX_VALUE; i++) { |
| 69 | try { | 68 | try { |
| 70 | WxPayMicropayResult response = client.micropay(request); | 69 | WxPayMicropayResult response = client.micropay(request); |
| 71 | - // 支付成功(例如说,用户输入了密码) | ||
| 72 | - PayOrderRespDTO order = PayOrderRespDTO.builder() | ||
| 73 | - .status(PayOrderStatusRespEnum.SUCCESS.getStatus()) | ||
| 74 | - .outTradeNo(response.getOutTradeNo()) | ||
| 75 | - .channelOrderNo(response.getTransactionId()) | ||
| 76 | - .channelUserId(response.getOpenid()) | ||
| 77 | - .successTime(parseDateV2(response.getTimeEnd())) | ||
| 78 | - .rawData(response) | ||
| 79 | - .build(); | ||
| 80 | - return new PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.BAR_CODE.getMode(), | ||
| 81 | - JsonUtils.toJsonString(response)) | ||
| 82 | - .setOrder(order); | 70 | + // 支付成功,例如说:1)用户输入了密码;2) |
| 71 | + return new PayOrderRespDTO(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()), | ||
| 72 | + response.getOutTradeNo(), response) | ||
| 73 | + .setDisplayMode(PayOrderDisplayModeEnum.BAR_CODE.getMode()); | ||
| 83 | } catch (WxPayException ex) { | 74 | } catch (WxPayException ex) { |
| 75 | + lastWxPayException = ex; | ||
| 84 | // 如果不满足这 3 种任一的,则直接抛出 WxPayException 异常,不仅需处理 | 76 | // 如果不满足这 3 种任一的,则直接抛出 WxPayException 异常,不仅需处理 |
| 85 | // 1. SYSTEMERROR:接口返回错误:请立即调用被扫订单结果查询API,查询当前订单状态,并根据订单的状态决定下一步的操作。 | 77 | // 1. SYSTEMERROR:接口返回错误:请立即调用被扫订单结果查询API,查询当前订单状态,并根据订单的状态决定下一步的操作。 |
| 86 | // 2. USERPAYING:用户支付中,需要输入密码:等待 5 秒,然后调用被扫订单结果查询 API,查询当前订单的不同状态,决定下一步的操作。 | 78 | // 2. USERPAYING:用户支付中,需要输入密码:等待 5 秒,然后调用被扫订单结果查询 API,查询当前订单的不同状态,决定下一步的操作。 |
| @@ -90,15 +82,15 @@ public class WxBarPayClient extends AbstractWxPayClient { | @@ -90,15 +82,15 @@ public class WxBarPayClient extends AbstractWxPayClient { | ||
| 90 | } | 82 | } |
| 91 | // 等待 5 秒,继续下一轮重新发起支付 | 83 | // 等待 5 秒,继续下一轮重新发起支付 |
| 92 | log.info("[doUnifiedOrderV2][发起微信 Bar 支付第({})失败,等待下一轮重试,请求({}),响应({})]", i, | 84 | log.info("[doUnifiedOrderV2][发起微信 Bar 支付第({})失败,等待下一轮重试,请求({}),响应({})]", i, |
| 93 | - JsonUtils.toJsonString(request), ex.getMessage()); | 85 | + toJsonString(request), ex.getMessage()); |
| 94 | ThreadUtil.sleep(5, TimeUnit.SECONDS); | 86 | ThreadUtil.sleep(5, TimeUnit.SECONDS); |
| 95 | } | 87 | } |
| 96 | } | 88 | } |
| 97 | - throw new IllegalStateException("微信 Bar 支付,重试多次失败"); | 89 | + throw lastWxPayException; |
| 98 | } | 90 | } |
| 99 | 91 | ||
| 100 | @Override | 92 | @Override |
| 101 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 93 | + protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 102 | return doUnifiedOrderV2(reqDTO); | 94 | return doUnifiedOrderV2(reqDTO); |
| 103 | } | 95 | } |
| 104 | 96 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxH5PayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 4 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 5 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 5 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 6 | import com.github.binarywang.wxpay.constant.WxPayConstants; | 6 | import com.github.binarywang.wxpay.constant.WxPayConstants; |
| 7 | import com.github.binarywang.wxpay.exception.WxPayException; | 7 | import com.github.binarywang.wxpay.exception.WxPayException; |
| @@ -19,12 +19,12 @@ public class WxH5PayClient extends AbstractWxPayClient { | @@ -19,12 +19,12 @@ public class WxH5PayClient extends AbstractWxPayClient { | ||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | @Override | 21 | @Override |
| 22 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 22 | + protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 23 | return null; | 23 | return null; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |
| 27 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 27 | + protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 28 | return null; | 28 | return null; |
| 29 | } | 29 | } |
| 30 | 30 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java
| 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 3 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 4 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 5 | 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.pay.core.enums.order.PayOrderDisplayModeEnum; | 6 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 7 | import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; | 7 | import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; |
| @@ -32,7 +32,7 @@ public class WxNativePayClient extends AbstractWxPayClient { | @@ -32,7 +32,7 @@ public class WxNativePayClient extends AbstractWxPayClient { | ||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | @Override | 34 | @Override |
| 35 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 35 | + protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 36 | // 构建 WxPayUnifiedOrderRequest 对象 | 36 | // 构建 WxPayUnifiedOrderRequest 对象 |
| 37 | WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() | 37 | WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() |
| 38 | .outTradeNo(reqDTO.getOutTradeNo()) | 38 | .outTradeNo(reqDTO.getOutTradeNo()) |
| @@ -48,12 +48,12 @@ public class WxNativePayClient extends AbstractWxPayClient { | @@ -48,12 +48,12 @@ public class WxNativePayClient extends AbstractWxPayClient { | ||
| 48 | WxPayNativeOrderResult response = client.createOrder(request); | 48 | WxPayNativeOrderResult response = client.createOrder(request); |
| 49 | 49 | ||
| 50 | // 转换结果 | 50 | // 转换结果 |
| 51 | - return new PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(), | ||
| 52 | - response.getCodeUrl()); | 51 | + return new PayOrderRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(), response.getCodeUrl(), |
| 52 | + reqDTO.getOutTradeNo(), response); | ||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | @Override | 55 | @Override |
| 56 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 56 | + protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 57 | // 构建 WxPayUnifiedOrderRequest 对象 | 57 | // 构建 WxPayUnifiedOrderRequest 对象 |
| 58 | WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request() | 58 | WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request() |
| 59 | .setOutTradeNo(reqDTO.getOutTradeNo()) | 59 | .setOutTradeNo(reqDTO.getOutTradeNo()) |
| @@ -66,8 +66,8 @@ public class WxNativePayClient extends AbstractWxPayClient { | @@ -66,8 +66,8 @@ 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 PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(), | ||
| 70 | - response); | 69 | + return new PayOrderRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(), response, |
| 70 | + reqDTO.getOutTradeNo(), response); | ||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | } | 73 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java
| @@ -2,9 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | @@ -2,9 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.map.MapUtil; | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 5 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 6 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 7 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 8 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 7 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 9 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; | 8 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; |
| 10 | import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; | 9 | import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; |
| @@ -17,6 +16,7 @@ import com.github.binarywang.wxpay.exception.WxPayException; | @@ -17,6 +16,7 @@ import com.github.binarywang.wxpay.exception.WxPayException; | ||
| 17 | import lombok.extern.slf4j.Slf4j; | 16 | import lombok.extern.slf4j.Slf4j; |
| 18 | 17 | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; | 18 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; |
| 19 | +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * 微信支付(公众号)的 PayClient 实现类 | 22 | * 微信支付(公众号)的 PayClient 实现类 |
| @@ -42,7 +42,7 @@ public class WxPubPayClient extends AbstractWxPayClient { | @@ -42,7 +42,7 @@ public class WxPubPayClient extends AbstractWxPayClient { | ||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | @Override | 44 | @Override |
| 45 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 45 | + protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 46 | // 构建 WxPayUnifiedOrderRequest 对象 | 46 | // 构建 WxPayUnifiedOrderRequest 对象 |
| 47 | WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() | 47 | WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() |
| 48 | .outTradeNo(reqDTO.getOutTradeNo()) | 48 | .outTradeNo(reqDTO.getOutTradeNo()) |
| @@ -58,12 +58,12 @@ public class WxPubPayClient extends AbstractWxPayClient { | @@ -58,12 +58,12 @@ public class WxPubPayClient extends AbstractWxPayClient { | ||
| 58 | WxPayMpOrderResult response = client.createOrder(request); | 58 | WxPayMpOrderResult response = client.createOrder(request); |
| 59 | 59 | ||
| 60 | // 转换结果 | 60 | // 转换结果 |
| 61 | - return new PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.CUSTOM.getMode(), | ||
| 62 | - JsonUtils.toJsonString(response)); | 61 | + return new PayOrderRespDTO(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), |
| 62 | + reqDTO.getOutTradeNo(), response); | ||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | @Override | 65 | @Override |
| 66 | - protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 66 | + protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 67 | // 构建 WxPayUnifiedOrderRequest 对象 | 67 | // 构建 WxPayUnifiedOrderRequest 对象 |
| 68 | WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); | 68 | WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); |
| 69 | request.setOutTradeNo(reqDTO.getOutTradeNo()); | 69 | request.setOutTradeNo(reqDTO.getOutTradeNo()); |
| @@ -77,8 +77,8 @@ public class WxPubPayClient extends AbstractWxPayClient { | @@ -77,8 +77,8 @@ 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 PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.CUSTOM.getMode(), | ||
| 81 | - JsonUtils.toJsonString(response)); | 80 | + return new PayOrderRespDTO(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), |
| 81 | + reqDTO.getOutTradeNo(), response); | ||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | // ========== 各种工具方法 ========== | 84 | // ========== 各种工具方法 ========== |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java deleted
| 1 | -package cn.iocoder.yudao.framework.pay.core.enums; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | - | ||
| 5 | -/** | ||
| 6 | - * 支付框架的错误码枚举 | ||
| 7 | - * | ||
| 8 | - * 支付框架,使用 2-002-000-000 段 | ||
| 9 | - * | ||
| 10 | - * @author 芋道源码 | ||
| 11 | - */ | ||
| 12 | -public interface PayFrameworkErrorCodeConstants { | ||
| 13 | - | ||
| 14 | - ErrorCode ORDER_UNIFIED_ERROR = new ErrorCode(2002000000, "发起支付失败,原因:{}"); | ||
| 15 | - | ||
| 16 | -} |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/order/PayOrderDisplayModeEnum.java
| @@ -18,8 +18,7 @@ public enum PayOrderDisplayModeEnum { | @@ -18,8 +18,7 @@ public enum PayOrderDisplayModeEnum { | ||
| 18 | QR_CODE("qr_code"), // 二维码的文字内容 | 18 | QR_CODE("qr_code"), // 二维码的文字内容 |
| 19 | QR_CODE_URL("qr_code_url"), // 二维码的图片链接 | 19 | QR_CODE_URL("qr_code_url"), // 二维码的图片链接 |
| 20 | BAR_CODE("bar_code"), // 条形码 | 20 | BAR_CODE("bar_code"), // 条形码 |
| 21 | - APP("app"), // 应用【目前暂时用不到】 | ||
| 22 | - CUSTOM("custom"), // 自定义:每种支付方式,做个性化处理;例如说,微信公众号支付时,调用 JSAPI 接口 | 21 | + APP("app"), // 应用:Android、iOS、微信小程序、微信公众号等,需要做自定义处理的 |
| 23 | ; | 22 | ; |
| 24 | 23 | ||
| 25 | /** | 24 | /** |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/order/PayOrderStatusRespEnum.java
| @@ -32,4 +32,14 @@ public enum PayOrderStatusRespEnum { | @@ -32,4 +32,14 @@ public enum PayOrderStatusRespEnum { | ||
| 32 | return Objects.equals(status, SUCCESS.getStatus()); | 32 | return Objects.equals(status, SUCCESS.getStatus()); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | + /** | ||
| 36 | + * 判断是否支付关闭 | ||
| 37 | + * | ||
| 38 | + * @param status 状态 | ||
| 39 | + * @return 是否支付关闭 | ||
| 40 | + */ | ||
| 41 | + public static boolean isClosed(Integer status) { | ||
| 42 | + return Objects.equals(status, CLOSED.getStatus()); | ||
| 43 | + } | ||
| 44 | + | ||
| 35 | } | 45 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
| @@ -351,7 +351,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | @@ -351,7 +351,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | ||
| 351 | public void afterCommit() { | 351 | public void afterCommit() { |
| 352 | // 创建退款单 | 352 | // 创建退款单 |
| 353 | PayRefundCreateReqDTO createReqDTO = TradeAfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties); | 353 | PayRefundCreateReqDTO createReqDTO = TradeAfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties); |
| 354 | - Long payRefundId = payRefundApi.createPayRefund(createReqDTO); | 354 | + Long payRefundId = payRefundApi.createRefund(createReqDTO); |
| 355 | // 更新售后单的退款单号 | 355 | // 更新售后单的退款单号 |
| 356 | tradeAfterSaleMapper.updateById(new TradeAfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId)); | 356 | tradeAfterSaleMapper.updateById(new TradeAfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId)); |
| 357 | } | 357 | } |
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java
| @@ -18,7 +18,7 @@ public interface PayRefundApi { | @@ -18,7 +18,7 @@ public interface PayRefundApi { | ||
| 18 | * @param reqDTO 创建请求 | 18 | * @param reqDTO 创建请求 |
| 19 | * @return 退款单编号 | 19 | * @return 退款单编号 |
| 20 | */ | 20 | */ |
| 21 | - Long createPayRefund(@Valid PayRefundCreateReqDTO reqDTO); | 21 | + Long createRefund(@Valid PayRefundCreateReqDTO reqDTO); |
| 22 | 22 | ||
| 23 | /** | 23 | /** |
| 24 | * 获得退款单 | 24 | * 获得退款单 |
| @@ -26,6 +26,6 @@ public interface PayRefundApi { | @@ -26,6 +26,6 @@ public interface PayRefundApi { | ||
| 26 | * @param id 退款单编号 | 26 | * @param id 退款单编号 |
| 27 | * @return 退款单 | 27 | * @return 退款单 |
| 28 | */ | 28 | */ |
| 29 | - PayRefundRespDTO getPayRefund(Long id); | 29 | + PayRefundRespDTO getRefund(Long id); |
| 30 | 30 | ||
| 31 | } | 31 | } |
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
| @@ -27,6 +27,7 @@ public interface ErrorCodeConstants { | @@ -27,6 +27,7 @@ public interface ErrorCodeConstants { | ||
| 27 | ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); | 27 | ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); |
| 28 | ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); | 28 | ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); |
| 29 | ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); | 29 | ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); |
| 30 | + ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); | ||
| 30 | 31 | ||
| 31 | // ========== ORDER 模块(拓展单) 1007003000 ========== | 32 | // ========== ORDER 模块(拓展单) 1007003000 ========== |
| 32 | ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); | 33 | ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
| @@ -22,12 +22,12 @@ public class PayRefundApiImpl implements PayRefundApi { | @@ -22,12 +22,12 @@ public class PayRefundApiImpl implements PayRefundApi { | ||
| 22 | private PayRefundService payRefundService; | 22 | private PayRefundService payRefundService; |
| 23 | 23 | ||
| 24 | @Override | 24 | @Override |
| 25 | - public Long createPayRefund(PayRefundCreateReqDTO reqDTO) { | 25 | + public Long createRefund(PayRefundCreateReqDTO reqDTO) { |
| 26 | return payRefundService.createPayRefund(reqDTO); | 26 | return payRefundService.createPayRefund(reqDTO); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | @Override | 29 | @Override |
| 30 | - public PayRefundRespDTO getPayRefund(Long id) { | 30 | + public PayRefundRespDTO getRefund(Long id) { |
| 31 | return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id)); | 31 | return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id)); |
| 32 | } | 32 | } |
| 33 | 33 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.pay.convert.order; | @@ -2,7 +2,6 @@ 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.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 5 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 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.api.order.dto.PayOrderRespDTO; | 6 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; |
| 8 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; | 7 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; |
| @@ -93,7 +92,8 @@ public interface PayOrderConvert { | @@ -93,7 +92,8 @@ public interface PayOrderConvert { | ||
| 93 | 92 | ||
| 94 | PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqVO reqVO, String userIp); | 93 | PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqVO reqVO, String userIp); |
| 95 | 94 | ||
| 96 | - PayOrderSubmitRespVO convert(PayOrderDO order, PayOrderUnifiedRespDTO unifiedRespDTO); | 95 | + @Mapping(source = "order.status", target = "status") |
| 96 | + PayOrderSubmitRespVO convert(PayOrderDO order, cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO respDTO); | ||
| 97 | 97 | ||
| 98 | AppPayOrderSubmitRespVO convert3(PayOrderSubmitRespVO bean); | 98 | AppPayOrderSubmitRespVO convert3(PayOrderSubmitRespVO bean); |
| 99 | 99 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java
| 1 | package cn.iocoder.yudao.module.pay.dal.dataobject.order; | 1 | package cn.iocoder.yudao.module.pay.dal.dataobject.order; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 3 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; | 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; |
| 4 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 5 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 6 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| @@ -65,7 +66,6 @@ public class PayOrderExtensionDO extends BaseDO { | @@ -65,7 +66,6 @@ public class PayOrderExtensionDO extends BaseDO { | ||
| 65 | * 支付状态 | 66 | * 支付状态 |
| 66 | * | 67 | * |
| 67 | * 枚举 {@link PayOrderStatusEnum} | 68 | * 枚举 {@link PayOrderStatusEnum} |
| 68 | - * 注意,只包含上述枚举的 WAITING 和 SUCCESS | ||
| 69 | */ | 69 | */ |
| 70 | private Integer status; | 70 | private Integer status; |
| 71 | /** | 71 | /** |
| @@ -75,10 +75,20 @@ public class PayOrderExtensionDO extends BaseDO { | @@ -75,10 +75,20 @@ public class PayOrderExtensionDO extends BaseDO { | ||
| 75 | */ | 75 | */ |
| 76 | @TableField(typeHandler = JacksonTypeHandler.class) | 76 | @TableField(typeHandler = JacksonTypeHandler.class) |
| 77 | private Map<String, String> channelExtras; | 77 | private Map<String, String> channelExtras; |
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 调用渠道的错误码 | ||
| 81 | + */ | ||
| 82 | + private String channelErrorCode; | ||
| 83 | + /** | ||
| 84 | + * 调用渠道报错时,错误信息 | ||
| 85 | + */ | ||
| 86 | + private String channelErrorMsg; | ||
| 87 | + | ||
| 78 | /** | 88 | /** |
| 79 | - * 支付渠道异步通知的内容 | 89 | + * 支付渠道的同步/异步通知的内容 |
| 80 | * | 90 | * |
| 81 | - * 在支持成功后,会记录回调的数据 | 91 | + * 对应 {@link PayOrderRespDTO#getRawData()} |
| 82 | */ | 92 | */ |
| 83 | private String channelNotifyData; | 93 | private String channelNotifyData; |
| 84 | 94 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java
| 1 | package cn.iocoder.yudao.module.pay.dal.dataobject.refund; | 1 | package cn.iocoder.yudao.module.pay.dal.dataobject.refund; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | ||
| 4 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | 5 | import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; |
| 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; |
| @@ -151,9 +152,9 @@ public class PayRefundDO extends BaseDO { | @@ -151,9 +152,9 @@ public class PayRefundDO extends BaseDO { | ||
| 151 | private String channelErrorMsg; | 152 | private String channelErrorMsg; |
| 152 | 153 | ||
| 153 | /** | 154 | /** |
| 154 | - * 支付渠道异步通知的内容 | 155 | + * 支付渠道的同步/异步通知的内容 |
| 155 | * | 156 | * |
| 156 | - * 在退款成功后,会记录回调的数据 | 157 | + * 对应 {@link PayRefundRespDTO#getRawData()} |
| 157 | */ | 158 | */ |
| 158 | private String channelNotifyData; | 159 | private String channelNotifyData; |
| 159 | 160 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
| @@ -189,7 +189,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | @@ -189,7 +189,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||
| 189 | // 这里我们是个简单的 demo,所以没有售后维权表,直接使用订单 id + "-refund" 来演示 | 189 | // 这里我们是个简单的 demo,所以没有售后维权表,直接使用订单 id + "-refund" 来演示 |
| 190 | String refundId = order.getId() + "-refund"; | 190 | String refundId = order.getId() + "-refund"; |
| 191 | // 2.2 创建退款单 | 191 | // 2.2 创建退款单 |
| 192 | - Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO() | 192 | + Long payRefundId = payRefundApi.createRefund(new PayRefundCreateReqDTO() |
| 193 | .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用 | 193 | .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用 |
| 194 | .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 | 194 | .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 |
| 195 | .setMerchantRefundId(refundId) | 195 | .setMerchantRefundId(refundId) |
| @@ -239,7 +239,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | @@ -239,7 +239,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | // 2.1 校验退款订单 | 241 | // 2.1 校验退款订单 |
| 242 | - PayRefundRespDTO payRefund = payRefundApi.getPayRefund(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(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND); |
| 245 | } | 245 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
| @@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil; | @@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil; | ||
| 4 | import cn.hutool.core.lang.Pair; | 4 | import cn.hutool.core.lang.Pair; |
| 5 | import cn.hutool.core.util.ObjectUtil; | 5 | import cn.hutool.core.util.ObjectUtil; |
| 6 | import cn.hutool.core.util.RandomUtil; | 6 | import cn.hutool.core.util.RandomUtil; |
| 7 | +import cn.hutool.core.util.StrUtil; | ||
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | 9 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 9 | import cn.iocoder.yudao.framework.pay.config.PayProperties; | 10 | import cn.iocoder.yudao.framework.pay.config.PayProperties; |
| @@ -11,7 +12,6 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient; | @@ -11,7 +12,6 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient; | ||
| 11 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 12 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 12 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 13 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| 13 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; | 14 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |
| 14 | -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; | ||
| 15 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; | 15 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; |
| 16 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | 16 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; |
| 17 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | 17 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| @@ -134,8 +134,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -134,8 +134,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 134 | return order.getId(); | 134 | return order.getId(); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | - @Override | ||
| 138 | - @Transactional(rollbackFor = Exception.class) | 137 | + @Override // 注意,这里不能添加事务注解,避免调用支付渠道失败时,将 PayOrderExtensionDO 回滚了 |
| 139 | public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) { | 138 | public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) { |
| 140 | // 1. 获得 PayOrderDO ,并校验其是否存在 | 139 | // 1. 获得 PayOrderDO ,并校验其是否存在 |
| 141 | PayOrderDO order = validateOrderCanSubmit(reqVO.getId()); | 140 | PayOrderDO order = validateOrderCanSubmit(reqVO.getId()); |
| @@ -159,17 +158,20 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -159,17 +158,20 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 159 | .setReturnUrl(reqVO.getReturnUrl()) | 158 | .setReturnUrl(reqVO.getReturnUrl()) |
| 160 | // 订单相关字段 | 159 | // 订单相关字段 |
| 161 | .setPrice(order.getPrice()).setExpireTime(order.getExpireTime()); | 160 | .setPrice(order.getPrice()).setExpireTime(order.getExpireTime()); |
| 162 | - PayOrderUnifiedRespDTO unifiedOrderRespDTO = client.unifiedOrder(unifiedOrderReqDTO); | 161 | + PayOrderRespDTO unifiedOrderResp = client.unifiedOrder(unifiedOrderReqDTO); |
| 163 | 162 | ||
| 164 | // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功 | 163 | // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功 |
| 165 | - if (unifiedOrderRespDTO.getOrder() != null) { | ||
| 166 | - notifyPayOrder(channel, unifiedOrderRespDTO.getOrder()); | 164 | + if (unifiedOrderResp != null) { |
| 165 | + notifyPayOrder(channel, unifiedOrderResp); | ||
| 166 | + // 如有渠道错误码,则抛出业务异常,提示用户 | ||
| 167 | + if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) { | ||
| 168 | + throw exception(PAY_ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), | ||
| 169 | + unifiedOrderResp.getChannelErrorMsg()); | ||
| 170 | + } | ||
| 167 | // 此处需要读取最新的状态 | 171 | // 此处需要读取最新的状态 |
| 168 | order = orderMapper.selectById(order.getId()); | 172 | order = orderMapper.selectById(order.getId()); |
| 169 | } | 173 | } |
| 170 | - | ||
| 171 | - // 返回成功 | ||
| 172 | - return PayOrderConvert.INSTANCE.convert(order, unifiedOrderRespDTO); | 174 | + return PayOrderConvert.INSTANCE.convert(order, unifiedOrderResp); |
| 173 | } | 175 | } |
| 174 | 176 | ||
| 175 | private PayOrderDO validateOrderCanSubmit(Long id) { | 177 | private PayOrderDO validateOrderCanSubmit(Long id) { |
| @@ -269,8 +271,10 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -269,8 +271,10 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 269 | notifyOrderSuccess(channel, notify); | 271 | notifyOrderSuccess(channel, notify); |
| 270 | return; | 272 | return; |
| 271 | } | 273 | } |
| 272 | - // 情况二:非支付成功的回调,进行忽略 | ||
| 273 | - log.info("[notifyPayOrder][非支付成功的回调({}),直接忽略]", toJsonString(notify)); | 274 | + // 情况二:支付失败的回调 |
| 275 | + if (PayOrderStatusRespEnum.isClosed(notify.getStatus())) { | ||
| 276 | + notifyOrderClosed(channel, notify); | ||
| 277 | + } | ||
| 274 | } | 278 | } |
| 275 | 279 | ||
| 276 | private void notifyOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) { | 280 | private void notifyOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) { |
| @@ -300,7 +304,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -300,7 +304,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 300 | throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); | 304 | throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); |
| 301 | } | 305 | } |
| 302 | if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 | 306 | if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 |
| 303 | - log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新为已支付]", orderExtension.getId()); | 307 | + log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新]", orderExtension.getId()); |
| 304 | return orderExtension; | 308 | return orderExtension; |
| 305 | } | 309 | } |
| 306 | if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 | 310 | if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 |
| @@ -327,7 +331,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -327,7 +331,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 327 | * value:PayOrderDO 对象 | 331 | * value:PayOrderDO 对象 |
| 328 | */ | 332 | */ |
| 329 | private Pair<Boolean, PayOrderDO> updateOrderExtensionSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, | 333 | private Pair<Boolean, PayOrderDO> updateOrderExtensionSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, |
| 330 | - PayOrderRespDTO notify) { | 334 | + PayOrderRespDTO notify) { |
| 331 | // 1. 判断 PayOrderDO 是否处于待支付 | 335 | // 1. 判断 PayOrderDO 是否处于待支付 |
| 332 | PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); | 336 | PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); |
| 333 | if (order == null) { | 337 | if (order == null) { |
| @@ -335,7 +339,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -335,7 +339,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 335 | } | 339 | } |
| 336 | if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 | 340 | if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 |
| 337 | && Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) { | 341 | && Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) { |
| 338 | - log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新为已支付]", order.getId()); | 342 | + log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新]", order.getId()); |
| 339 | return Pair.of(true, order); | 343 | return Pair.of(true, order); |
| 340 | } | 344 | } |
| 341 | if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 | 345 | if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 |
| @@ -356,4 +360,37 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -356,4 +360,37 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 356 | return Pair.of(false, order); | 360 | return Pair.of(false, order); |
| 357 | } | 361 | } |
| 358 | 362 | ||
| 363 | + private void notifyOrderClosed(PayChannelDO channel, PayOrderRespDTO notify) { | ||
| 364 | + updateOrderExtensionClosed(channel, notify); | ||
| 365 | + } | ||
| 366 | + | ||
| 367 | + private void updateOrderExtensionClosed(PayChannelDO channel, PayOrderRespDTO notify) { | ||
| 368 | + // 1. 查询 PayOrderExtensionDO | ||
| 369 | + PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); | ||
| 370 | + if (orderExtension == null) { | ||
| 371 | + throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); | ||
| 372 | + } | ||
| 373 | + if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { // 如果已经是关闭,直接返回,不用重复更新 | ||
| 374 | + log.info("[updateOrderExtensionClosed][支付拓展单({}) 已经是支付关闭,无需更新]", orderExtension.getId()); | ||
| 375 | + return; | ||
| 376 | + } | ||
| 377 | + // 一般出现先是支付成功,然后支付关闭,都是全部退款导致关闭的场景。这个情况,我们不更新支付拓展单,只通过退款流程,更新支付单 | ||
| 378 | + if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { | ||
| 379 | + log.info("[updateOrderExtensionClosed][支付拓展单({}) 是已支付,无需更新为支付关闭]", orderExtension.getId()); | ||
| 380 | + return; | ||
| 381 | + } | ||
| 382 | + if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 | ||
| 383 | + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | ||
| 384 | + } | ||
| 385 | + | ||
| 386 | + // 2. 更新 PayOrderExtensionDO | ||
| 387 | + int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(), | ||
| 388 | + PayOrderExtensionDO.builder().status(PayOrderStatusEnum.CLOSED.getStatus()).channelNotifyData(toJsonString(notify)) | ||
| 389 | + .channelErrorCode(notify.getChannelErrorCode()).channelErrorMsg(notify.getChannelErrorMsg()).build()); | ||
| 390 | + if (updateCounts == 0) { // 校验状态,必须是待支付 | ||
| 391 | + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); | ||
| 392 | + } | ||
| 393 | + log.info("[updateOrderExtensionClosed][支付拓展单({}) 更新为支付关闭]", orderExtension.getId()); | ||
| 394 | + } | ||
| 395 | + | ||
| 359 | } | 396 | } |