Commit c44ace601160ae562e85e38240c318591257f93b

Authored by YunaiV
1 parent 518e89dc

mall + pay:

1. 完成支付宝的退款重构
2. 完成 demo 模块的退款接入
Showing 23 changed files with 333 additions and 274 deletions
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundRespDTO.java
@@ -21,6 +21,13 @@ public class PayRefundRespDTO { @@ -21,6 +21,13 @@ public class PayRefundRespDTO {
21 private Integer status; 21 private Integer status;
22 22
23 /** 23 /**
  24 + * 外部退款号
  25 + *
  26 + * 对应 PayRefundDO 的 no 字段
  27 + */
  28 + private String outRefundNo;
  29 +
  30 + /**
24 * 渠道退款单号 31 * 渠道退款单号
25 * 32 *
26 * 对应 PayRefundDO.channelRefundNo 字段 33 * 对应 PayRefundDO.channelRefundNo 字段
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
@@ -68,7 +68,6 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa @@ -68,7 +68,6 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
68 model.setOutTradeNo(reqDTO.getOutTradeNo()); 68 model.setOutTradeNo(reqDTO.getOutTradeNo());
69 model.setOutRequestNo(reqDTO.getOutRefundNo()); 69 model.setOutRequestNo(reqDTO.getOutRefundNo());
70 model.setRefundAmount(formatAmount(reqDTO.getPrice())); 70 model.setRefundAmount(formatAmount(reqDTO.getPrice()));
71 -// model.setRefundAmount(formatAmount(reqDTO.getPrice() / 2));  
72 model.setRefundReason(reqDTO.getReason()); 71 model.setRefundReason(reqDTO.getReason());
73 // 1.2 构建 AlipayTradePayRequest 请求 72 // 1.2 构建 AlipayTradePayRequest 请求
74 AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); 73 AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
@@ -77,6 +76,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa @@ -77,6 +76,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
77 // 2.1 执行请求 76 // 2.1 执行请求
78 AlipayTradeRefundResponse response = client.execute(request); 77 AlipayTradeRefundResponse response = client.execute(request);
79 PayRefundRespDTO refund = new PayRefundRespDTO() 78 PayRefundRespDTO refund = new PayRefundRespDTO()
  79 + .setOutRefundNo(reqDTO.getOutRefundNo())
80 .setRawData(response); 80 .setRawData(response);
81 // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。 81 // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。
82 // 另外,支付宝没有退款单号,所以不用设置 82 // 另外,支付宝没有退款单号,所以不用设置
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java
@@ -27,26 +27,32 @@ public class PayRefundCreateReqDTO { @@ -27,26 +27,32 @@ public class PayRefundCreateReqDTO {
27 private String userIp; 27 private String userIp;
28 28
29 // ========== 商户相关字段 ========== 29 // ========== 商户相关字段 ==========
  30 + /**
  31 + * 商户订单编号
  32 + */
  33 + @NotEmpty(message = "商户订单编号不能为空")
  34 + private String merchantOrderId;
  35 +
  36 + /**
  37 + * 商户退款编号
  38 + */
  39 + @NotEmpty(message = "商户退款编号不能为空")
  40 + private String merchantRefundId;
30 41
31 /** 42 /**
32 * 退款描述 43 * 退款描述
33 */ 44 */
34 @NotEmpty(message = "退款描述不能为空") 45 @NotEmpty(message = "退款描述不能为空")
35 - @Length(max = 128, message = "退款描述长度不能超过128") 46 + @Length(max = 128, message = "退款描述长度不能超过 128")
36 private String reason; 47 private String reason;
37 48
38 // ========== 订单相关字段 ========== 49 // ========== 订单相关字段 ==========
39 50
40 /** 51 /**
41 - * 支付单号  
42 - */  
43 - @NotNull(message = "支付单号不能为空")  
44 - private Long payOrderId;  
45 -  
46 - /**  
47 * 退款金额,单位:分 52 * 退款金额,单位:分
48 */ 53 */
49 @NotNull(message = "退款金额不能为空") 54 @NotNull(message = "退款金额不能为空")
50 @Min(value = 1, message = "退款金额必须大于零") 55 @Min(value = 1, message = "退款金额必须大于零")
51 private Integer price; 56 private Integer price;
  57 +
52 } 58 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -33,11 +33,12 @@ public interface ErrorCodeConstants { @@ -33,11 +33,12 @@ public interface ErrorCodeConstants {
33 ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); 33 ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
34 34
35 // ========== 支付模块(退款) 1007006000 ========== 35 // ========== 支付模块(退款) 1007006000 ==========
36 - ErrorCode PAY_PRICE_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); 36 + ErrorCode PAY_REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额");
37 ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款"); 37 ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款");
38 - ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空");  
39 - ErrorCode PAY_REFUND_SUCCEED = new ErrorCode(1007006003, "已经退款成功"); 38 + ErrorCode PAY_REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中");
  39 + ErrorCode PAY_REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单");
40 ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); 40 ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
  41 + ErrorCode PAY_REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款");
41 42
42 // ========== 示例订单 1007900000 ========== 43 // ========== 示例订单 1007900000 ==========
43 ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); 44 ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在");
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java
@@ -38,4 +38,14 @@ public enum PayOrderStatusEnum implements IntArrayValuable { @@ -38,4 +38,14 @@ public enum PayOrderStatusEnum implements IntArrayValuable {
38 return Objects.equals(status, SUCCESS.getStatus()); 38 return Objects.equals(status, SUCCESS.getStatus());
39 } 39 }
40 40
  41 + /**
  42 + * 判断是否支付关闭
  43 + *
  44 + * @param status 状态
  45 + * @return 是否支付关闭
  46 + */
  47 + public static boolean isClosed(Integer status) {
  48 + return Objects.equals(status, CLOSED.getStatus());
  49 + }
  50 +
41 } 51 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java
@@ -22,7 +22,7 @@ public class PayOrderApiImpl implements PayOrderApi { @@ -22,7 +22,7 @@ public class PayOrderApiImpl implements PayOrderApi {
22 22
23 @Override 23 @Override
24 public Long createOrder(PayOrderCreateReqDTO reqDTO) { 24 public Long createOrder(PayOrderCreateReqDTO reqDTO) {
25 - return payOrderService.createPayOrder(reqDTO); 25 + return payOrderService.createOrder(reqDTO);
26 } 26 }
27 27
28 @Override 28 @Override
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.api.refund; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.api.refund;
2 2
3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
4 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; 4 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
  5 +import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;
5 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 6 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
6 import org.springframework.stereotype.Service; 7 import org.springframework.stereotype.Service;
7 import org.springframework.validation.annotation.Validated; 8 import org.springframework.validation.annotation.Validated;
@@ -27,8 +28,7 @@ public class PayRefundApiImpl implements PayRefundApi { @@ -27,8 +28,7 @@ public class PayRefundApiImpl implements PayRefundApi {
27 28
28 @Override 29 @Override
29 public PayRefundRespDTO getPayRefund(Long id) { 30 public PayRefundRespDTO getPayRefund(Long id) {
30 - // TODO 芋艿:暂未实现  
31 - return null; 31 + return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id));
32 } 32 }
33 33
34 } 34 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
@@ -65,12 +65,12 @@ public class PayNotifyController { @@ -65,12 +65,12 @@ public class PayNotifyController {
65 // 3. 处理通知 65 // 3. 处理通知
66 // 3.1:退款通知 66 // 3.1:退款通知
67 if (notify instanceof PayRefundRespDTO) { 67 if (notify instanceof PayRefundRespDTO) {
68 - refundService.notifyPayRefund(channelId, (PayRefundRespDTO) notify); 68 + refundService.notifyRefund(channelId, (PayRefundRespDTO) notify);
69 return "success"; 69 return "success";
70 } 70 }
71 // 3.2:支付通知 71 // 3.2:支付通知
72 if (notify instanceof PayOrderRespDTO) { 72 if (notify instanceof PayOrderRespDTO) {
73 - orderService.notifyPayOrder(channelId, (PayOrderRespDTO) notify); 73 + orderService.notifyOrder(channelId, (PayOrderRespDTO) notify);
74 return "success"; 74 return "success";
75 } 75 }
76 throw new UnsupportedOperationException("未知通知:" + toJsonString(notify)); 76 throw new UnsupportedOperationException("未知通知:" + toJsonString(notify));
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java
@@ -86,7 +86,7 @@ public class PayOrderController { @@ -86,7 +86,7 @@ public class PayOrderController {
86 @PostMapping("/submit") 86 @PostMapping("/submit")
87 @Operation(summary = "提交支付订单") 87 @Operation(summary = "提交支付订单")
88 public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { 88 public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) {
89 - PayOrderSubmitRespVO respVO = payOrderService.submitPayOrder(reqVO, getClientIP()); 89 + PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP());
90 return success(respVO); 90 return success(respVO);
91 } 91 }
92 92
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
@@ -40,7 +40,7 @@ public class AppPayOrderController { @@ -40,7 +40,7 @@ public class AppPayOrderController {
40 @PostMapping("/submit") 40 @PostMapping("/submit")
41 @Operation(summary = "提交支付订单") 41 @Operation(summary = "提交支付订单")
42 public CommonResult<AppPayOrderSubmitRespVO> submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) { 42 public CommonResult<AppPayOrderSubmitRespVO> submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) {
43 - PayOrderSubmitRespVO respVO = payOrderService.submitPayOrder(reqVO, getClientIP()); 43 + PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP());
44 return success(PayOrderConvert.INSTANCE.convert3(respVO)); 44 return success(PayOrderConvert.INSTANCE.convert3(respVO));
45 } 45 }
46 46
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java
1 package cn.iocoder.yudao.module.pay.convert.refund; 1 package cn.iocoder.yudao.module.pay.convert.refund;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
  5 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
4 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*; 6 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*;
5 -import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;  
6 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
7 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
8 -import org.mapstruct.Mapping;  
9 -import org.mapstruct.Mappings;  
10 import org.mapstruct.factory.Mappers; 9 import org.mapstruct.factory.Mappers;
11 10
12 import java.math.BigDecimal; 11 import java.math.BigDecimal;
@@ -44,8 +43,6 @@ public interface PayRefundConvert { @@ -44,8 +43,6 @@ public interface PayRefundConvert {
44 43
45 PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page); 44 PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page);
46 45
47 - List<PayRefundExcelVO> convertList02(List<PayRefundDO> list);  
48 -  
49 /** 46 /**
50 * 退款订单DO 转 导出excel VO 47 * 退款订单DO 转 导出excel VO
51 * 48 *
@@ -67,7 +64,6 @@ public interface PayRefundConvert { @@ -67,7 +64,6 @@ public interface PayRefundConvert {
67 payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl()); 64 payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl());
68 payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus()); 65 payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus());
69 payRefundExcelVO.setStatus(bean.getStatus()); 66 payRefundExcelVO.setStatus(bean.getStatus());
70 - payRefundExcelVO.setType(bean.getType());  
71 payRefundExcelVO.setReason(bean.getReason()); 67 payRefundExcelVO.setReason(bean.getReason());
72 payRefundExcelVO.setUserIp(bean.getUserIp()); 68 payRefundExcelVO.setUserIp(bean.getUserIp());
73 payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo()); 69 payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo());
@@ -84,12 +80,8 @@ public interface PayRefundConvert { @@ -84,12 +80,8 @@ public interface PayRefundConvert {
84 return payRefundExcelVO; 80 return payRefundExcelVO;
85 } 81 }
86 82
87 - //TODO 太多需要处理了, 暂时不用  
88 - @Mappings(value = {  
89 - @Mapping(source = "price", target = "payPrice"),  
90 - @Mapping(source = "id", target = "orderId"),  
91 - @Mapping(target = "status",ignore = true)  
92 - })  
93 - PayRefundDO convert(PayOrderDO orderDO); 83 + PayRefundDO convert(PayRefundCreateReqDTO bean);
  84 +
  85 + PayRefundRespDTO convert02(PayRefundDO bean);
94 86
95 } 87 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
7 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; 7 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
8 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 8 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
9 -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; 9 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
10 import com.baomidou.mybatisplus.annotation.KeySequence; 10 import com.baomidou.mybatisplus.annotation.KeySequence;
11 import com.baomidou.mybatisplus.annotation.TableName; 11 import com.baomidou.mybatisplus.annotation.TableName;
12 import lombok.*; 12 import lombok.*;
@@ -127,7 +127,7 @@ public class PayOrderDO extends BaseDO { @@ -127,7 +127,7 @@ public class PayOrderDO extends BaseDO {
127 /** 127 /**
128 * 退款状态 128 * 退款状态
129 * 129 *
130 - * 枚举 {@link PayRefundTypeEnum} 130 + * 枚举 {@link PayOrderRefundStatusEnum}
131 */ 131 */
132 private Integer refundStatus; 132 private Integer refundStatus;
133 /** 133 /**
@@ -137,7 +137,7 @@ public class PayOrderDO extends BaseDO { @@ -137,7 +137,7 @@ public class PayOrderDO extends BaseDO {
137 /** 137 /**
138 * 退款总金额,单位:分 138 * 退款总金额,单位:分
139 */ 139 */
140 - private Long refundPrice; 140 + private Integer refundPrice;
141 141
142 // ========== 渠道相关字段 ========== 142 // ========== 渠道相关字段 ==========
143 /** 143 /**
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java
@@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
7 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
8 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; 8 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
9 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; 9 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
10 -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;  
11 import com.baomidou.mybatisplus.annotation.KeySequence; 10 import com.baomidou.mybatisplus.annotation.KeySequence;
12 import com.baomidou.mybatisplus.annotation.TableId; 11 import com.baomidou.mybatisplus.annotation.TableId;
13 import com.baomidou.mybatisplus.annotation.TableName; 12 import com.baomidou.mybatisplus.annotation.TableName;
@@ -105,12 +104,6 @@ public class PayRefundDO extends BaseDO { @@ -105,12 +104,6 @@ public class PayRefundDO extends BaseDO {
105 private Integer status; 104 private Integer status;
106 105
107 /** 106 /**
108 - * 退款类型(部分退款,全部退款)  
109 - *  
110 - * 枚举 {@link PayRefundTypeEnum}  
111 - */  
112 - private Integer type;  
113 - /**  
114 * 支付金额,单位:分 107 * 支付金额,单位:分
115 */ 108 */
116 private Integer payPrice; 109 private Integer payPrice;
@@ -158,12 +151,6 @@ public class PayRefundDO extends BaseDO { @@ -158,12 +151,6 @@ public class PayRefundDO extends BaseDO {
158 private String channelErrorMsg; 151 private String channelErrorMsg;
159 152
160 /** 153 /**
161 - * 支付渠道的额外参数  
162 - *  
163 - * 参见 <a href="https://www.pingxx.com/api/支付渠道%20extra%20参数说明.html">参数说明</>  
164 - */  
165 - private String channelExtras;  
166 - /**  
167 * 支付渠道异步通知的内容 154 * 支付渠道异步通知的内容
168 * 155 *
169 * 在退款成功后,会记录回调的数据 156 * 在退款成功后,会记录回调的数据
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java
1 package cn.iocoder.yudao.module.pay.dal.mysql.refund; 1 package cn.iocoder.yudao.module.pay.dal.mysql.refund;
2 2
3 -import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;  
4 -import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;  
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  7 +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
  8 +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
8 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 9 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
  10 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 import org.apache.ibatis.annotations.Mapper; 11 import org.apache.ibatis.annotations.Mapper;
10 12
11 import java.util.List; 13 import java.util.List;
@@ -13,6 +15,34 @@ import java.util.List; @@ -13,6 +15,34 @@ import java.util.List;
13 @Mapper 15 @Mapper
14 public interface PayRefundMapper extends BaseMapperX<PayRefundDO> { 16 public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
15 17
  18 + default Long selectCountByAppId(Long appId) {
  19 + return selectCount(PayRefundDO::getAppId, appId);
  20 + }
  21 +
  22 + default PayRefundDO selectByAppIdAndMerchantRefundId(Long appId, String merchantRefundId) {
  23 + return selectOne(new LambdaQueryWrapperX<PayRefundDO>()
  24 + .eq(PayRefundDO::getAppId, appId)
  25 + .eq(PayRefundDO::getMerchantRefundId, merchantRefundId));
  26 + }
  27 +
  28 + default Long selectCountByAppIdAndOrderId(Long appId, Long orderId, Integer status) {
  29 + return selectCount(new LambdaQueryWrapperX<PayRefundDO>()
  30 + .eq(PayRefundDO::getAppId, appId)
  31 + .eq(PayRefundDO::getOrderId, orderId)
  32 + .eq(PayRefundDO::getStatus, status));
  33 + }
  34 +
  35 + default PayRefundDO selectByAppIdAndNo(Long appId, String no) {
  36 + return selectOne(new LambdaQueryWrapperX<PayRefundDO>()
  37 + .eq(PayRefundDO::getAppId, appId)
  38 + .eq(PayRefundDO::getNo, no));
  39 + }
  40 +
  41 + default int updateByIdAndStatus(Long id, Integer status, PayRefundDO update) {
  42 + return update(update, new LambdaQueryWrapper<PayRefundDO>()
  43 + .eq(PayRefundDO::getId, id).eq(PayRefundDO::getStatus, status));
  44 + }
  45 +
16 default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) { 46 default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) {
17 return selectPage(reqVO, new QueryWrapperX<PayRefundDO>() 47 return selectPage(reqVO, new QueryWrapperX<PayRefundDO>()
18 .eqIfPresent("app_id", reqVO.getAppId()) 48 .eqIfPresent("app_id", reqVO.getAppId())
@@ -37,18 +67,4 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; { @@ -37,18 +67,4 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; {
37 .orderByDesc("id")); 67 .orderByDesc("id"));
38 } 68 }
39 69
40 - default Long selectCountByApp(Long appId) {  
41 - return selectCount(PayRefundDO::getAppId, appId);  
42 - }  
43 -  
44 - default PayRefundDO selectByReqNo(String reqNo) {  
45 - return selectOne("req_no", reqNo);  
46 - }  
47 -  
48 - // TODO 芋艿:要重构  
49 - default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){  
50 -// return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);  
51 - return null;  
52 - }  
53 -  
54 } 70 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundTypeEnum.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderRefundStatusEnum.java
1 -package cn.iocoder.yudao.module.pay.enums.refund; 1 +package cn.iocoder.yudao.module.pay.enums.order;
2 2
3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable; 3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
@@ -11,10 +11,10 @@ import lombok.Getter; @@ -11,10 +11,10 @@ import lombok.Getter;
11 */ 11 */
12 @Getter 12 @Getter
13 @AllArgsConstructor 13 @AllArgsConstructor
14 -public enum PayRefundTypeEnum implements IntArrayValuable { 14 +public enum PayOrderRefundStatusEnum implements IntArrayValuable {
15 15
16 NO(0, "未退款"), 16 NO(0, "未退款"),
17 - SOME(10, "部分退款"), 17 + PART(10, "部分退款"),
18 ALL(20, "全部退款") 18 ALL(20, "全部退款")
19 ; 19 ;
20 20
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
@@ -184,12 +184,17 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -184,12 +184,17 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
184 // 1. 校验订单是否可以退款 184 // 1. 校验订单是否可以退款
185 PayDemoOrderDO order = validateDemoOrderCanRefund(id); 185 PayDemoOrderDO order = validateDemoOrderCanRefund(id);
186 186
187 - // 2.1 创建退款单 187 + // 2.1 生成退款单号
  188 + // 一般来说,用户发起退款的时候,都会单独插入一个售后维权表,然后使用该表的 id 作为 refundId
  189 + // 这里我们是个简单的 demo,所以没有售后维权表,直接使用订单 id + "-refund" 来演示
  190 + String refundId = order.getId() + "-refund";
  191 + // 2.2 创建退款单
188 Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO() 192 Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO()
189 .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用 193 .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
190 - .setPayOrderId(order.getPayOrderId()) // 支付单号 194 + .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号
  195 + .setMerchantRefundId(refundId)
191 .setReason("想退钱").setPrice(order.getPrice()));// 价格信息 196 .setReason("想退钱").setPrice(order.getPrice()));// 价格信息
192 - // 2.2 更新退款单到 demo 订单 197 + // 2.3 更新退款单到 demo 订单
193 payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id) 198 payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
194 .setPayRefundId(payRefundId).setRefundPrice(order.getPrice())); 199 .setPayRefundId(payRefundId).setRefundPrice(order.getPrice()));
195 } 200 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionService.java
@@ -7,6 +7,7 @@ import java.util.Collection; @@ -7,6 +7,7 @@ import java.util.Collection;
7 import java.util.List; 7 import java.util.List;
8 import java.util.Map; 8 import java.util.Map;
9 9
  10 +// TODO 芋艿:合并到 PayOrder 里;
10 /** 11 /**
11 * 支付订单 Service 接口 12 * 支付订单 Service 接口
12 * 13 *
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
@@ -32,6 +32,15 @@ public interface PayOrderService { @@ -32,6 +32,15 @@ public interface PayOrderService {
32 PayOrderDO getOrder(Long id); 32 PayOrderDO getOrder(Long id);
33 33
34 /** 34 /**
  35 + * 获得支付订单
  36 + *
  37 + * @param appId 应用编号
  38 + * @param merchantOrderId 商户订单编号
  39 + * @return 支付订单
  40 + */
  41 + PayOrderDO getOrder(Long appId, String merchantOrderId);
  42 +
  43 + /**
35 * 获得指定应用的订单数量 44 * 获得指定应用的订单数量
36 * 45 *
37 * @param appId 应用编号 46 * @param appId 应用编号
@@ -70,11 +79,11 @@ public interface PayOrderService { @@ -70,11 +79,11 @@ public interface PayOrderService {
70 /** 79 /**
71 * 根据订单 ID 集合获取订单商品名称Map集合 80 * 根据订单 ID 集合获取订单商品名称Map集合
72 * 81 *
73 - * @param idList 订单 ID 集合 82 + * @param ids 订单 ID 集合
74 * @return 订单商品 map 集合 83 * @return 订单商品 map 集合
75 */ 84 */
76 - default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> idList) {  
77 - List<PayOrderDO> list = getOrderSubjectList(idList); 85 + default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> ids) {
  86 + List<PayOrderDO> list = getOrderSubjectList(ids);
78 return CollectionUtils.convertMap(list, PayOrderDO::getId); 87 return CollectionUtils.convertMap(list, PayOrderDO::getId);
79 } 88 }
80 89
@@ -84,7 +93,7 @@ public interface PayOrderService { @@ -84,7 +93,7 @@ public interface PayOrderService {
84 * @param reqDTO 创建请求 93 * @param reqDTO 创建请求
85 * @return 支付单编号 94 * @return 支付单编号
86 */ 95 */
87 - Long createPayOrder(@Valid PayOrderCreateReqDTO reqDTO); 96 + Long createOrder(@Valid PayOrderCreateReqDTO reqDTO);
88 97
89 /** 98 /**
90 * 提交支付 99 * 提交支付
@@ -94,8 +103,8 @@ public interface PayOrderService { @@ -94,8 +103,8 @@ public interface PayOrderService {
94 * @param userIp 提交 IP 103 * @param userIp 提交 IP
95 * @return 提交结果 104 * @return 提交结果
96 */ 105 */
97 - PayOrderSubmitRespVO submitPayOrder(@Valid PayOrderSubmitReqVO reqVO,  
98 - @NotEmpty(message = "提交 IP 不能为空") String userIp); 106 + PayOrderSubmitRespVO submitOrder(@Valid PayOrderSubmitReqVO reqVO,
  107 + @NotEmpty(message = "提交 IP 不能为空") String userIp);
99 108
100 /** 109 /**
101 * 通知支付单成功 110 * 通知支付单成功
@@ -103,6 +112,14 @@ public interface PayOrderService { @@ -103,6 +112,14 @@ public interface PayOrderService {
103 * @param channelId 渠道编号 112 * @param channelId 渠道编号
104 * @param notify 通知 113 * @param notify 通知
105 */ 114 */
106 - void notifyPayOrder(Long channelId, PayOrderRespDTO notify); 115 + void notifyOrder(Long channelId, PayOrderRespDTO notify);
  116 +
  117 + /**
  118 + * 更新支付订单的退款金额
  119 + *
  120 + * @param id 编号
  121 + * @param incrRefundPrice 增加的退款金额
  122 + */
  123 + void updateOrderRefundPrice(Long id, Integer incrRefundPrice);
107 124
108 } 125 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -26,11 +26,10 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; @@ -26,11 +26,10 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
26 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; 26 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
27 import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; 27 import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper;
28 import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; 28 import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
29 -import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;  
30 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; 29 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
31 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; 30 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
  31 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
32 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 32 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
33 -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;  
34 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 33 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
35 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; 34 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
36 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; 35 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
@@ -48,6 +47,7 @@ import java.util.Objects; @@ -48,6 +47,7 @@ import java.util.Objects;
48 47
49 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 48 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
50 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 49 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
  50 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
51 51
52 /** 52 /**
53 * 支付订单 Service 实现类 53 * 支付订单 Service 实现类
@@ -83,6 +83,11 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -83,6 +83,11 @@ public class PayOrderServiceImpl implements PayOrderService {
83 } 83 }
84 84
85 @Override 85 @Override
  86 + public PayOrderDO getOrder(Long appId, String merchantOrderId) {
  87 + return orderMapper.selectByAppIdAndMerchantOrderId(appId, merchantOrderId);
  88 + }
  89 +
  90 + @Override
86 public Long getOrderCountByAppId(Long appId) { 91 public Long getOrderCountByAppId(Long appId) {
87 return orderMapper.selectCountByAppId(appId); 92 return orderMapper.selectCountByAppId(appId);
88 } 93 }
@@ -104,7 +109,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -104,7 +109,7 @@ public class PayOrderServiceImpl implements PayOrderService {
104 } 109 }
105 110
106 @Override 111 @Override
107 - public Long createPayOrder(PayOrderCreateReqDTO reqDTO) { 112 + public Long createOrder(PayOrderCreateReqDTO reqDTO) {
108 // 校验 App 113 // 校验 App
109 PayAppDO app = appService.validPayApp(reqDTO.getAppId()); 114 PayAppDO app = appService.validPayApp(reqDTO.getAppId());
110 115
@@ -112,7 +117,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -112,7 +117,7 @@ public class PayOrderServiceImpl implements PayOrderService {
112 PayOrderDO order = orderMapper.selectByAppIdAndMerchantOrderId( 117 PayOrderDO order = orderMapper.selectByAppIdAndMerchantOrderId(
113 reqDTO.getAppId(), reqDTO.getMerchantOrderId()); 118 reqDTO.getAppId(), reqDTO.getMerchantOrderId());
114 if (order != null) { 119 if (order != null) {
115 - log.warn("[createPayOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(), 120 + log.warn("[createOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(),
116 order.getMerchantOrderId(), toJsonString(order)); // 理论来说,不会出现这个情况 121 order.getMerchantOrderId(), toJsonString(order)); // 理论来说,不会出现这个情况
117 return order.getId(); 122 return order.getId();
118 } 123 }
@@ -124,16 +129,16 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -124,16 +129,16 @@ public class PayOrderServiceImpl implements PayOrderService {
124 // 订单相关字段 129 // 订单相关字段
125 .setStatus(PayOrderStatusEnum.WAITING.getStatus()) 130 .setStatus(PayOrderStatusEnum.WAITING.getStatus())
126 // 退款相关字段 131 // 退款相关字段
127 - .setRefundStatus(PayRefundTypeEnum.NO.getStatus()).setRefundTimes(0).setRefundPrice(0L); 132 + .setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()).setRefundTimes(0).setRefundPrice(0);
128 orderMapper.insert(order); 133 orderMapper.insert(order);
129 return order.getId(); 134 return order.getId();
130 } 135 }
131 136
132 @Override 137 @Override
133 @Transactional(rollbackFor = Exception.class) 138 @Transactional(rollbackFor = Exception.class)
134 - public PayOrderSubmitRespVO submitPayOrder(PayOrderSubmitReqVO reqVO, String userIp) { 139 + public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) {
135 // 1. 获得 PayOrderDO ,并校验其是否存在 140 // 1. 获得 PayOrderDO ,并校验其是否存在
136 - PayOrderDO order = validatePayOrderCanSubmit(reqVO.getId()); 141 + PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
137 // 1.2 校验支付渠道是否有效 142 // 1.2 校验支付渠道是否有效
138 PayChannelDO channel = validatePayChannelCanSubmit(order.getAppId(), reqVO.getChannelCode()); 143 PayChannelDO channel = validatePayChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
139 PayClient client = payClientFactory.getPayClient(channel.getId()); 144 PayClient client = payClientFactory.getPayClient(channel.getId());
@@ -167,16 +172,16 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -167,16 +172,16 @@ public class PayOrderServiceImpl implements PayOrderService {
167 return PayOrderConvert.INSTANCE.convert(order, unifiedOrderRespDTO); 172 return PayOrderConvert.INSTANCE.convert(order, unifiedOrderRespDTO);
168 } 173 }
169 174
170 - private PayOrderDO validatePayOrderCanSubmit(Long id) { 175 + private PayOrderDO validateOrderCanSubmit(Long id) {
171 PayOrderDO order = orderMapper.selectById(id); 176 PayOrderDO order = orderMapper.selectById(id);
172 if (order == null) { // 是否存在 177 if (order == null) { // 是否存在
173 - throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); 178 + throw exception(PAY_ORDER_NOT_FOUND);
174 } 179 }
175 if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 180 if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
176 - throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); 181 + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
177 } 182 }
178 if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期 183 if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期
179 - throw exception(ErrorCodeConstants.PAY_ORDER_IS_EXPIRED); 184 + throw exception(PAY_ORDER_IS_EXPIRED);
180 } 185 }
181 return order; 186 return order;
182 } 187 }
@@ -184,14 +189,12 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -184,14 +189,12 @@ public class PayOrderServiceImpl implements PayOrderService {
184 private PayChannelDO validatePayChannelCanSubmit(Long appId, String channelCode) { 189 private PayChannelDO validatePayChannelCanSubmit(Long appId, String channelCode) {
185 // 校验 App 190 // 校验 App
186 appService.validPayApp(appId); 191 appService.validPayApp(appId);
187 -  
188 // 校验支付渠道是否有效 192 // 校验支付渠道是否有效
189 PayChannelDO channel = channelService.validPayChannel(appId, channelCode); 193 PayChannelDO channel = channelService.validPayChannel(appId, channelCode);
190 - // 校验支付客户端是否正确初始化  
191 PayClient client = payClientFactory.getPayClient(channel.getId()); 194 PayClient client = payClientFactory.getPayClient(channel.getId());
192 if (client == null) { 195 if (client == null) {
193 log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 196 log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
194 - throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); 197 + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
195 } 198 }
196 return channel; 199 return channel;
197 } 200 }
@@ -226,28 +229,55 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -226,28 +229,55 @@ public class PayOrderServiceImpl implements PayOrderService {
226 229
227 @Override 230 @Override
228 @Transactional(rollbackFor = Exception.class) 231 @Transactional(rollbackFor = Exception.class)
229 - public void notifyPayOrder(Long channelId, PayOrderRespDTO notify) { 232 + public void notifyOrder(Long channelId, PayOrderRespDTO notify) {
230 // 校验支付渠道是否有效 233 // 校验支付渠道是否有效
231 PayChannelDO channel = channelService.validPayChannel(channelId); 234 PayChannelDO channel = channelService.validPayChannel(channelId);
232 // 更新支付订单为已支付 235 // 更新支付订单为已支付
233 TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify)); 236 TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify));
234 } 237 }
235 238
  239 + @Override
  240 + public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) {
  241 + PayOrderDO order = orderMapper.selectById(id);
  242 + if (order == null) {
  243 + throw exception(PAY_ORDER_NOT_FOUND);
  244 + }
  245 + if (!PayOrderStatusEnum.isSuccess(order.getStatus())) {
  246 + throw exception(PAY_REFUND_PRICE_EXCEED);
  247 + }
  248 + if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) {
  249 + throw exception(PAY_REFUND_PRICE_EXCEED);
  250 + }
  251 +
  252 + // 更新订单
  253 + PayOrderDO updateObj = new PayOrderDO()
  254 + .setRefundPrice(order.getRefundPrice() + incrRefundPrice)
  255 + .setRefundTimes(order.getRefundTimes() + 1);
  256 + if (Objects.equals(updateObj.getRefundPrice(), order.getPrice())) {
  257 + updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
  258 + .setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus());
  259 + } else {
  260 + updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
  261 + .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus());
  262 + }
  263 + orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj);
  264 + }
  265 +
236 private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { 266 private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) {
237 // 情况一:支付成功的回调 267 // 情况一:支付成功的回调
238 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { 268 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) {
239 - notifyPayOrderSuccess(channel, notify); 269 + notifyOrderSuccess(channel, notify);
240 return; 270 return;
241 } 271 }
242 // 情况二:非支付成功的回调,进行忽略 272 // 情况二:非支付成功的回调,进行忽略
243 log.info("[notifyPayOrder][非支付成功的回调({}),直接忽略]", toJsonString(notify)); 273 log.info("[notifyPayOrder][非支付成功的回调({}),直接忽略]", toJsonString(notify));
244 } 274 }
245 275
246 - private void notifyPayOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) { 276 + private void notifyOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) {
247 // 1. 更新 PayOrderExtensionDO 支付成功 277 // 1. 更新 PayOrderExtensionDO 支付成功
248 - PayOrderExtensionDO orderExtension = updatePayOrderExtensionSuccess(notify); 278 + PayOrderExtensionDO orderExtension = updateOrderExtensionSuccess(notify);
249 // 2. 更新 PayOrderDO 支付成功 279 // 2. 更新 PayOrderDO 支付成功
250 - Pair<Boolean, PayOrderDO> order = updatePayOrderSuccess(channel, orderExtension, notify); 280 + Pair<Boolean, PayOrderDO> order = updateOrderExtensionSuccess(channel, orderExtension, notify);
251 if (order.getKey()) { // 如果之前已经成功回调,则直接返回,不用重复记录支付通知记录;例如说:支付平台重复回调 281 if (order.getKey()) { // 如果之前已经成功回调,则直接返回,不用重复记录支付通知记录;例如说:支付平台重复回调
252 return; 282 return;
253 } 283 }
@@ -263,27 +293,27 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -263,27 +293,27 @@ public class PayOrderServiceImpl implements PayOrderService {
263 * @param notify 通知 293 * @param notify 通知
264 * @return PayOrderExtensionDO 对象 294 * @return PayOrderExtensionDO 对象
265 */ 295 */
266 - private PayOrderExtensionDO updatePayOrderExtensionSuccess(PayOrderRespDTO notify) { 296 + private PayOrderExtensionDO updateOrderExtensionSuccess(PayOrderRespDTO notify) {
267 // 1. 查询 PayOrderExtensionDO 297 // 1. 查询 PayOrderExtensionDO
268 PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); 298 PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo());
269 if (orderExtension == null) { 299 if (orderExtension == null) {
270 - throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND); 300 + throw exception(PAY_ORDER_EXTENSION_NOT_FOUND);
271 } 301 }
272 if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 302 if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
273 - log.info("[updatePayOrderSuccess][支付拓展单({}) 已经是已支付,无需更新为已支付]", orderExtension.getId()); 303 + log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新为已支付]", orderExtension.getId());
274 return orderExtension; 304 return orderExtension;
275 } 305 }
276 if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 306 if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付
277 - throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); 307 + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
278 } 308 }
279 309
280 // 2. 更新 PayOrderExtensionDO 310 // 2. 更新 PayOrderExtensionDO
281 - int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), PayOrderStatusEnum.WAITING.getStatus(), 311 + int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(),
282 PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build()); 312 PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build());
283 if (updateCounts == 0) { // 校验状态,必须是待支付 313 if (updateCounts == 0) { // 校验状态,必须是待支付
284 - throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); 314 + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
285 } 315 }
286 - log.info("[updatePayOrderSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId()); 316 + log.info("[updateOrderExtensionSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId());
287 return orderExtension; 317 return orderExtension;
288 } 318 }
289 319
@@ -296,20 +326,20 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -296,20 +326,20 @@ public class PayOrderServiceImpl implements PayOrderService {
296 * @return key:是否之前已经成功回调 326 * @return key:是否之前已经成功回调
297 * value:PayOrderDO 对象 327 * value:PayOrderDO 对象
298 */ 328 */
299 - private Pair<Boolean, PayOrderDO> updatePayOrderSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, 329 + private Pair<Boolean, PayOrderDO> updateOrderExtensionSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension,
300 PayOrderRespDTO notify) { 330 PayOrderRespDTO notify) {
301 // 1. 判断 PayOrderDO 是否处于待支付 331 // 1. 判断 PayOrderDO 是否处于待支付
302 PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); 332 PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId());
303 if (order == null) { 333 if (order == null) {
304 - throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); 334 + throw exception(PAY_ORDER_NOT_FOUND);
305 } 335 }
306 if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 336 if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新
307 && Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) { 337 && Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) {
308 - log.info("[updatePayOrderSuccess][支付订单({}) 已经是已支付,无需更新为已支付]", order.getId()); 338 + log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新为已支付]", order.getId());
309 return Pair.of(true, order); 339 return Pair.of(true, order);
310 } 340 }
311 if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 341 if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
312 - throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); 342 + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
313 } 343 }
314 344
315 // 2. 更新 PayOrderDO 345 // 2. 更新 PayOrderDO
@@ -320,9 +350,9 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -320,9 +350,9 @@ public class PayOrderServiceImpl implements PayOrderService {
320 .channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId()) 350 .channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId())
321 .notifyTime(LocalDateTime.now()).build()); 351 .notifyTime(LocalDateTime.now()).build());
322 if (updateCounts == 0) { // 校验状态,必须是待支付 352 if (updateCounts == 0) { // 校验状态,必须是待支付
323 - throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); 353 + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
324 } 354 }
325 - log.info("[updatePayOrderSuccess][支付订单({}) 更新为已支付]", order.getId()); 355 + log.info("[updateOrderExtensionSuccess][支付订单({}) 更新为已支付]", order.getId());
326 return Pair.of(false, order); 356 return Pair.of(false, order);
327 } 357 }
328 358
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java
@@ -62,6 +62,6 @@ public interface PayRefundService { @@ -62,6 +62,6 @@ public interface PayRefundService {
62 * @param channelId 渠道编号 62 * @param channelId 渠道编号
63 * @param notify 通知 63 * @param notify 通知
64 */ 64 */
65 - void notifyPayRefund(Long channelId, PayRefundRespDTO notify); 65 + void notifyRefund(Long channelId, PayRefundRespDTO notify);
66 66
67 } 67 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
1 package cn.iocoder.yudao.module.pay.service.refund; 1 package cn.iocoder.yudao.module.pay.service.refund;
2 2
  3 +import cn.hutool.core.date.DateUtil;
3 import cn.hutool.core.util.RandomUtil; 4 import cn.hutool.core.util.RandomUtil;
4 -import cn.hutool.core.util.StrUtil;  
5 -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;  
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.pay.config.PayProperties; 6 import cn.iocoder.yudao.framework.pay.config.PayProperties;
8 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 7 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
@@ -10,22 +9,23 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; @@ -10,22 +9,23 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
10 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; 9 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
11 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; 10 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
12 import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; 11 import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
  12 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
13 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 13 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
14 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; 14 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
15 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; 15 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
  16 +import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;
16 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; 17 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 18 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
18 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 19 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
19 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; 20 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
20 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 21 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
21 -import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;  
22 import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; 22 import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
23 import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; 23 import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
  24 +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
24 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; 25 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
25 -import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; 26 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
26 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 27 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
27 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; 28 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
28 -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;  
29 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 29 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
30 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; 30 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
31 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; 31 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
@@ -38,8 +38,11 @@ import org.springframework.transaction.annotation.Transactional; @@ -38,8 +38,11 @@ import org.springframework.transaction.annotation.Transactional;
38 import org.springframework.validation.annotation.Validated; 38 import org.springframework.validation.annotation.Validated;
39 39
40 import javax.annotation.Resource; 40 import javax.annotation.Resource;
  41 +import java.time.LocalDateTime;
41 import java.util.List; 42 import java.util.List;
42 -import java.util.Objects; 43 +
  44 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  45 +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
43 46
44 /** 47 /**
45 * 退款订单 Service 实现类 48 * 退款订单 Service 实现类
@@ -59,8 +62,6 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -59,8 +62,6 @@ public class PayRefundServiceImpl implements PayRefundService {
59 62
60 @Resource 63 @Resource
61 private PayRefundMapper refundMapper; 64 private PayRefundMapper refundMapper;
62 - @Resource  
63 - private PayOrderMapper orderMapper; // TODO @jason:需要改成不直接操作 db;  
64 65
65 @Resource 66 @Resource
66 private PayOrderService orderService; 67 private PayOrderService orderService;
@@ -80,7 +81,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -80,7 +81,7 @@ public class PayRefundServiceImpl implements PayRefundService {
80 81
81 @Override 82 @Override
82 public Long getRefundCountByAppId(Long appId) { 83 public Long getRefundCountByAppId(Long appId) {
83 - return refundMapper.selectCountByApp(appId); 84 + return refundMapper.selectCountByAppId(appId);
84 } 85 }
85 86
86 @Override 87 @Override
@@ -96,82 +97,82 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -96,82 +97,82 @@ public class PayRefundServiceImpl implements PayRefundService {
96 @Override 97 @Override
97 @Transactional(rollbackFor = Exception.class) 98 @Transactional(rollbackFor = Exception.class)
98 public Long createPayRefund(PayRefundCreateReqDTO reqDTO) { 99 public Long createPayRefund(PayRefundCreateReqDTO reqDTO) {
99 - // 获得 PayOrderDO  
100 - PayOrderDO order = orderService.getOrder(reqDTO.getPayOrderId());  
101 - // 校验订单是否存在  
102 - if (Objects.isNull(order) ) {  
103 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);  
104 - }  
105 - // 校验 App  
106 - PayAppDO app = appService.validPayApp(order.getAppId());  
107 - // 校验支付渠道是否有效 100 + // 1.1 校验 App
  101 + PayAppDO app = appService.validPayApp(reqDTO.getAppId());
  102 + // 1.2 校验支付订单
  103 + PayOrderDO order = validatePayOrderCanRefund(reqDTO);
  104 + // 1.3 校验支付渠道是否有效
108 PayChannelDO channel = channelService.validPayChannel(order.getChannelId()); 105 PayChannelDO channel = channelService.validPayChannel(order.getChannelId());
109 - // 校验支付客户端是否正确初始化  
110 PayClient client = payClientFactory.getPayClient(channel.getId()); 106 PayClient client = payClientFactory.getPayClient(channel.getId());
111 if (client == null) { 107 if (client == null) {
112 log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 108 log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
113 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); 109 + throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND);
114 } 110 }
115 -  
116 - // TODO 芋艿:待实现  
117 - String merchantRefundId = "rrr" + RandomUtil.randomNumbers(16);  
118 -  
119 - // 校验退款的条件  
120 - validatePayRefund(reqDTO, order);  
121 - // 退款类型  
122 - PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME;  
123 - if (Objects.equals(reqDTO.getPrice(), order.getPrice())) {  
124 - refundType = PayRefundTypeEnum.ALL; 111 + // 1.4 校验退款订单是否已经存在
  112 + PayRefundDO refund = refundMapper.selectByAppIdAndMerchantRefundId(
  113 + app.getId(), reqDTO.getMerchantRefundId());
  114 + if (refund != null) {
  115 + throw exception(ErrorCodeConstants.PAY_REFUND_EXISTS);
125 } 116 }
126 - PayOrderExtensionDO orderExtensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());  
127 - PayRefundDO payRefundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(),  
128 - merchantRefundId); // TODO 芋艿:需要优化  
129 - if (Objects.nonNull(payRefundDO)) {  
130 - // 退款订单已经提交过。  
131 - //TODO 校验相同退款单的金额  
132 - // TODO @jason:咱要不封装一个 ObjectUtils.equalsAny  
133 - if (Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus())) {  
134 - //已成功退款  
135 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_SUCCEED);  
136 - }  
137 - //可以重复提交,保证 退款请求号 一致,由渠道保证幂等  
138 - } else {  
139 - // 成功,插入退款单 状态为生成.没有和渠道交互  
140 - // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下;  
141 - payRefundDO = PayRefundDO.builder()  
142 - .appId(order.getAppId())  
143 - .channelOrderNo(order.getChannelOrderNo())  
144 - .channelCode(order.getChannelCode())  
145 - .channelId(order.getChannelId())  
146 - .orderId(order.getId())  
147 - .merchantRefundId(merchantRefundId)  
148 - .notifyUrl(app.getRefundNotifyUrl())  
149 - .payPrice(order.getPrice())  
150 - .refundPrice(reqDTO.getPrice())  
151 - .userIp(reqDTO.getUserIp())  
152 - .merchantOrderId(order.getMerchantOrderId())  
153 - .no(orderExtensionDO.getNo())  
154 - .status(PayRefundStatusEnum.WAITING.getStatus())  
155 - .reason(reqDTO.getReason())  
156 - .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus())  
157 - .type(refundType.getStatus())  
158 - .build();  
159 - refundMapper.insert(payRefundDO);  
160 - }  
161 - // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; 117 +
  118 + // 2.1 插入退款单
  119 + refund = PayRefundConvert.INSTANCE.convert(reqDTO)
  120 + .setNo(generateRefundNo()).setOrderId(order.getId())
  121 + .setChannelId(order.getChannelId()).setChannelCode(order.getChannelCode())
  122 + // 商户相关的字段
  123 + .setNotifyUrl(app.getRefundNotifyUrl()).setNotifyStatus(PayNotifyStatusEnum.WAITING.getStatus())
  124 + // 渠道相关字段
  125 + .setChannelOrderNo(order.getChannelOrderNo())
  126 + // 退款相关字段
  127 + .setStatus(PayRefundStatusEnum.WAITING.getStatus())
  128 + .setPayPrice(order.getPrice()).setRefundPrice(reqDTO.getPrice());
  129 + refundMapper.insert(refund);
  130 + // 2.2 向渠道发起退款申请
  131 + PayOrderExtensionDO orderExtension = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());
162 PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO(); 132 PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
163 unifiedReqDTO.setPrice(reqDTO.getPrice()) 133 unifiedReqDTO.setPrice(reqDTO.getPrice())
164 - .setOutTradeNo(orderExtensionDO.getNo())  
165 - .setOutRefundNo(merchantRefundId) // TODO 芋艿:需要优化 134 + .setOutTradeNo(orderExtension.getNo())
  135 + .setOutRefundNo(refund.getNo())
166 .setNotifyUrl(genChannelPayNotifyUrl(channel)) // TODO 芋艿:优化下 notifyUrl 136 .setNotifyUrl(genChannelPayNotifyUrl(channel)) // TODO 芋艿:优化下 notifyUrl
167 .setReason(reqDTO.getReason()); 137 .setReason(reqDTO.getReason());
168 - // 向渠道发起退款申请  
169 - client.unifiedRefund(unifiedReqDTO);  
170 - // 检查是否失败,失败抛出业务异常。  
171 - // TODO 渠道的异常记录。  
172 - // TODO @jason:可以先打个 warn log 哈; 138 + PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO); // TODO 增加一个 channelErrorCode、channelErrorMsg 字段
  139 + // 2.3 处理退款返回
  140 + notifyRefund(channel, refundRespDTO);
  141 +
173 // 成功在 退款回调中处理 142 // 成功在 退款回调中处理
174 - return payRefundDO.getId(); 143 + return refund.getId();
  144 + }
  145 +
  146 + /**
  147 + * 校验支付订单是否可以退款
  148 + *
  149 + * @param reqDTO 退款申请信息
  150 + * @return 支付订单
  151 + */
  152 + private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) {
  153 + PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId());
  154 + if (order == null) {
  155 + throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);
  156 + }
  157 + // 校验状态,必须是支付状态
  158 + if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
  159 + throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS);
  160 + }
  161 +
  162 + // 是否已经全额退款
  163 + if (PayOrderRefundStatusEnum.ALL.getStatus().equals(order.getRefundStatus())) {
  164 + throw exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED);
  165 + }
  166 + // 校验金额 退款金额不能大于原定的金额
  167 + if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){
  168 + throw exception(ErrorCodeConstants.PAY_REFUND_PRICE_EXCEED);
  169 + }
  170 + // 是否有退款中的订单
  171 + if (refundMapper.selectCountByAppIdAndOrderId(reqDTO.getAppId(), order.getId(),
  172 + PayRefundStatusEnum.WAITING.getStatus()) > 0) {
  173 + throw exception(ErrorCodeConstants.PAY_REFUND_HAS_REFUNDING);
  174 + }
  175 + return order;
175 } 176 }
176 177
177 /** 178 /**
@@ -184,88 +185,80 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -184,88 +185,80 @@ public class PayRefundServiceImpl implements PayRefundService {
184 return payProperties.getCallbackUrl() + "/" + channel.getId(); 185 return payProperties.getCallbackUrl() + "/" + channel.getId();
185 } 186 }
186 187
  188 + private String generateRefundNo() {
  189 +// wx
  190 +// 2014
  191 +// 10
  192 +// 27
  193 +// 20
  194 +// 09
  195 +// 39
  196 +// 5522657
  197 +// a690389285100
  198 + // 目前的算法
  199 + // 时间序列,年月日时分秒 14 位
  200 + // 纯随机,6 位 TODO 芋艿:此处估计是会有问题的,后续在调整
  201 + return DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + // 时间序列
  202 + RandomUtil.randomInt(100000, 999999) // 随机。为什么是这个范围,因为偷懒
  203 + ;
  204 + }
  205 +
187 @Override 206 @Override
188 @Transactional(rollbackFor = Exception.class) 207 @Transactional(rollbackFor = Exception.class)
189 - public void notifyPayRefund(Long channelId, PayRefundRespDTO notify) { 208 + public void notifyRefund(Long channelId, PayRefundRespDTO notify) {
  209 + // 校验支付渠道是否有效
  210 + channelService.validPayChannel(channelId);
  211 + // 通知结果
  212 +
190 // 校验支付渠道是否有效 213 // 校验支付渠道是否有效
191 - // TODO 芋艿:需要重构下这块的逻辑  
192 PayChannelDO channel = channelService.validPayChannel(channelId); 214 PayChannelDO channel = channelService.validPayChannel(channelId);
  215 + // 更新退款订单
  216 + TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify));
  217 + }
  218 +
  219 + private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) {
193 if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) { 220 if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) {
194 - payRefundSuccess(notify); 221 + notifyRefundSuccess(channel, notify);
195 } else { 222 } else {
196 - // TODO @jason:那这里可以考虑打个 error logger @芋艿 微信是否存在支付异常通知 223 + notifyRefundFailure(channel, notify);
197 } 224 }
198 } 225 }
199 226
200 - private void payRefundSuccess(PayRefundRespDTO refundNotify) {  
201 - // 校验退款单存在  
202 - PayRefundDO refundDO = null; // TODO 芋艿:临时注释  
203 -// PayRefundDO refundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(),  
204 -// refundNotify.getReqNo());  
205 - if (refundDO == null) {  
206 - // TODO 芋艿:临时注释  
207 -// log.error("[payRefundSuccess][不存在 seqNo 为{} 的支付退款单]", refundNotify.getReqNo());  
208 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND); 227 + private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) {
  228 + // 1.1 查询 PayRefundDO
  229 + PayRefundDO refund = refundMapper.selectByAppIdAndNo(
  230 + channel.getAppId(), notify.getOutRefundNo());
  231 + if (refund == null) {
  232 + throw exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND);
  233 + }
  234 + if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
  235 + return;
  236 + }
  237 + if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) {
  238 + throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING);
209 } 239 }
210 240
211 - // 得到已退金额  
212 - PayOrderDO payOrderDO = orderService.getOrder(refundDO.getOrderId());  
213 - Long refundedAmount = payOrderDO.getRefundPrice();  
214 -  
215 - PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS;  
216 - if(Objects.equals(payOrderDO.getPrice(), refundedAmount+ refundDO.getRefundPrice())){  
217 - //支付金额 = 已退金额 + 本次退款金额。  
218 - orderStatus = PayOrderStatusEnum.CLOSED; 241 + // 1.2 更新 PayRefundDO
  242 + PayRefundDO updateRefundObj = new PayRefundDO()
  243 + .setSuccessTime(notify.getSuccessTime())
  244 + .setChannelRefundNo(notify.getChannelRefundNo())
  245 + .setStatus(PayRefundStatusEnum.SUCCESS.getStatus())
  246 + .setChannelNotifyData(toJsonString(notify));
  247 + int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj);
  248 + if (updateCounts == 0) { // 校验状态,必须是等待状态
  249 + throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING);
219 } 250 }
220 - // 更新支付订单  
221 - PayOrderDO updateOrderDO = new PayOrderDO();  
222 - updateOrderDO.setId(refundDO.getOrderId())  
223 - .setRefundPrice(refundedAmount + refundDO.getRefundPrice())  
224 - .setStatus(orderStatus.getStatus())  
225 - .setRefundTimes(payOrderDO.getRefundTimes() + 1)  
226 - .setRefundStatus(refundDO.getType());  
227 - orderMapper.updateById(updateOrderDO);  
228 251
229 - // 更新退款订单  
230 - PayRefundDO updateRefundDO = new PayRefundDO();  
231 - updateRefundDO.setId(refundDO.getId())  
232 - .setSuccessTime(refundNotify.getSuccessTime())  
233 - // TODO 芋艿:如下两行,临时注释  
234 -// .setChannelRefundNo(refundNotify.getChannelOrderNo())  
235 -// .setNo(refundNotify.getTradeNo())  
236 - .setStatus(PayRefundStatusEnum.SUCCESS.getStatus());  
237 - refundMapper.updateById(updateRefundDO); 252 + // 2. 更新订单
  253 + orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
238 254
239 - // 插入退款通知记录  
240 - // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调 255 + // 3. 插入退款通知记录
241 notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() 256 notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
242 - .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build()); 257 + .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
243 } 258 }
244 259
245 - /**  
246 - * 校验是否进行退款  
247 - *  
248 - * @param reqDTO 退款申请信息  
249 - * @param order 原始支付订单信息  
250 - */  
251 - private void validatePayRefund(PayRefundCreateReqDTO reqDTO, PayOrderDO order) {  
252 - // 校验状态,必须是支付状态  
253 - if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {  
254 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS);  
255 - }  
256 - // 是否已经全额退款  
257 - if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) {  
258 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED);  
259 - }  
260 - // 校验金额 退款金额不能大于 原定的金额  
261 - if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){  
262 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_PRICE_PRICE_EXCEED);  
263 - }  
264 - // 校验渠道订单号  
265 - if (StrUtil.isEmpty(order.getChannelOrderNo())) {  
266 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_CHN_ORDER_NO_IS_NULL);  
267 - }  
268 - //TODO 退款的期限 退款次数的控制 260 + private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
  261 + // TODO 芋艿:未实现
269 } 262 }
270 263
271 } 264 }
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
@@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
13 import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; 13 import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
14 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; 14 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
15 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 15 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
16 -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; 16 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
17 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 17 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
18 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; 18 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
19 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; 19 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
@@ -85,7 +85,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @@ -85,7 +85,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
85 o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2)); 85 o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2));
86 o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); 86 o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
87 o.setSuccessExtensionId(1L); 87 o.setSuccessExtensionId(1L);
88 - o.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); 88 + o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
89 o.setRefundTimes(0); 89 o.setRefundTimes(0);
90 o.setRefundPrice(0L); 90 o.setRefundPrice(0L);
91 o.setChannelUserId("1008611"); 91 o.setChannelUserId("1008611");
@@ -106,7 +106,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @@ -106,7 +106,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
106 // 测试 status 不匹配 106 // 测试 status 不匹配
107 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); 107 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
108 // 测试 refundStatus 不匹配 108 // 测试 refundStatus 不匹配
109 - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus()))); 109 + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus())));
110 // 测试 createTime 不匹配 110 // 测试 createTime 不匹配
111 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10, 111 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10,
112 1)))); 112 1))));
@@ -118,7 +118,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @@ -118,7 +118,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
118 reqVO.setMerchantOrderId(merchantOrderId); 118 reqVO.setMerchantOrderId(merchantOrderId);
119 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); 119 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
120 reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); 120 reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
121 - reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); 121 + reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
122 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)})); 122 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)}));
123 // 调用 123 // 调用
124 PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO); 124 PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO);
@@ -153,7 +153,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @@ -153,7 +153,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
153 o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2)); 153 o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2));
154 o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15)); 154 o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
155 o.setSuccessExtensionId(1L); 155 o.setSuccessExtensionId(1L);
156 - o.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); 156 + o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
157 o.setRefundTimes(0); 157 o.setRefundTimes(0);
158 o.setRefundPrice(0L); 158 o.setRefundPrice(0L);
159 o.setChannelUserId("1008611"); 159 o.setChannelUserId("1008611");
@@ -175,7 +175,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @@ -175,7 +175,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
175 // 测试 status 不匹配 175 // 测试 status 不匹配
176 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); 176 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
177 // 测试 refundStatus 不匹配 177 // 测试 refundStatus 不匹配
178 - orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus()))); 178 + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus())));
179 // 测试 createTime 不匹配 179 // 测试 createTime 不匹配
180 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10, 180 orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10,
181 1)))); 181 1))));
@@ -187,7 +187,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @@ -187,7 +187,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
187 reqVO.setMerchantOrderId(merchantOrderId); 187 reqVO.setMerchantOrderId(merchantOrderId);
188 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); 188 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
189 reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); 189 reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
190 - reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); 190 + reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
191 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)})); 191 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)}));
192 192
193 // 调用 193 // 调用
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java
@@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; @@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
11 import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; 11 import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
12 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; 12 import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
13 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; 13 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
14 -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; 14 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
15 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 15 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
16 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; 16 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
17 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; 17 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
@@ -64,11 +64,11 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -64,11 +64,11 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
64 o.setOrderId(1L); 64 o.setOrderId(1L);
65 o.setNo("OT0000001"); 65 o.setNo("OT0000001");
66 o.setMerchantOrderId("MOT0000001"); 66 o.setMerchantOrderId("MOT0000001");
67 - o.setMerchantRefundNo("MRF0000001"); 67 + o.setMerchantRefundId("MRF0000001");
68 o.setNotifyUrl("https://www.cancanzi.com"); 68 o.setNotifyUrl("https://www.cancanzi.com");
69 o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); 69 o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
70 o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); 70 o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
71 - o.setType(PayRefundTypeEnum.SOME.getStatus()); 71 + o.setType(PayOrderRefundStatusEnum.PART.getStatus());
72 o.setPayPrice(100); 72 o.setPayPrice(100);
73 o.setRefundPrice(500); 73 o.setRefundPrice(500);
74 o.setReason("就是想退款了,你有意见吗"); 74 o.setReason("就是想退款了,你有意见吗");
@@ -77,10 +77,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -77,10 +77,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
77 o.setChannelRefundNo("CHR0000001"); 77 o.setChannelRefundNo("CHR0000001");
78 o.setChannelErrorCode(""); 78 o.setChannelErrorCode("");
79 o.setChannelErrorMsg(""); 79 o.setChannelErrorMsg("");
80 - o.setChannelExtras("");  
81 - o.setExpireTime(LocalDateTime.of(2021, 1, 1, 10, 10, 30));  
82 o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15)); 80 o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
83 - o.setNotifyTime(LocalDateTime.of(2021, 1, 1, 10, 10, 20));  
84 o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10)); 81 o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
85 o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35)); 82 o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
86 }); 83 });
@@ -90,14 +87,14 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -90,14 +87,14 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
90 // 测试 channelCode 不匹配 87 // 测试 channelCode 不匹配
91 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); 88 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
92 // 测试 merchantRefundNo 不匹配 89 // 测试 merchantRefundNo 不匹配
93 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112"))); 90 + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112")));
94 // 测试 notifyStatus 不匹配 91 // 测试 notifyStatus 不匹配
95 refundMapper.insert( 92 refundMapper.insert(
96 cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); 93 cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
97 // 测试 status 不匹配 94 // 测试 status 不匹配
98 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus()))); 95 + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus())));
99 // 测试 type 不匹配 96 // 测试 type 不匹配
100 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus()))); 97 + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayOrderRefundStatusEnum.ALL.getStatus())));
101 // 测试 createTime 不匹配 98 // 测试 createTime 不匹配
102 refundMapper.insert(cloneIgnoreId(dbRefund, o -> 99 refundMapper.insert(cloneIgnoreId(dbRefund, o ->
103 o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10)))); 100 o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
@@ -108,7 +105,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -108,7 +105,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
108 reqVO.setMerchantRefundNo("MRF0000001"); 105 reqVO.setMerchantRefundNo("MRF0000001");
109 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); 106 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
110 reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); 107 reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
111 - reqVO.setType(PayRefundTypeEnum.SOME.getStatus()); 108 + reqVO.setType(PayOrderRefundStatusEnum.PART.getStatus());
112 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)})); 109 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
113 110
114 // 调用 111 // 调用
@@ -129,11 +126,11 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -129,11 +126,11 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
129 o.setOrderId(1L); 126 o.setOrderId(1L);
130 o.setNo("OT0000001"); 127 o.setNo("OT0000001");
131 o.setMerchantOrderId("MOT0000001"); 128 o.setMerchantOrderId("MOT0000001");
132 - o.setMerchantRefundNo("MRF0000001"); 129 + o.setMerchantRefundId("MRF0000001");
133 o.setNotifyUrl("https://www.cancanzi.com"); 130 o.setNotifyUrl("https://www.cancanzi.com");
134 o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); 131 o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
135 o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); 132 o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
136 - o.setType(PayRefundTypeEnum.SOME.getStatus()); 133 + o.setType(PayOrderRefundStatusEnum.PART.getStatus());
137 o.setPayPrice(100); 134 o.setPayPrice(100);
138 o.setRefundPrice(500); 135 o.setRefundPrice(500);
139 o.setReason("就是想退款了,你有意见吗"); 136 o.setReason("就是想退款了,你有意见吗");
@@ -142,10 +139,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -142,10 +139,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
142 o.setChannelRefundNo("CHR0000001"); 139 o.setChannelRefundNo("CHR0000001");
143 o.setChannelErrorCode(""); 140 o.setChannelErrorCode("");
144 o.setChannelErrorMsg(""); 141 o.setChannelErrorMsg("");
145 - o.setChannelExtras("");  
146 - o.setExpireTime(LocalDateTime.of(2021, 1, 1, 10, 10, 30));  
147 o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15)); 142 o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
148 - o.setNotifyTime(LocalDateTime.of(2021, 1, 1, 10, 10, 20));  
149 o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10)); 143 o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
150 o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35)); 144 o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
151 }); 145 });
@@ -155,14 +149,14 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -155,14 +149,14 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
155 // 测试 channelCode 不匹配 149 // 测试 channelCode 不匹配
156 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); 150 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
157 // 测试 merchantRefundNo 不匹配 151 // 测试 merchantRefundNo 不匹配
158 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112"))); 152 + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112")));
159 // 测试 notifyStatus 不匹配 153 // 测试 notifyStatus 不匹配
160 refundMapper.insert( 154 refundMapper.insert(
161 cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); 155 cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
162 // 测试 status 不匹配 156 // 测试 status 不匹配
163 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus()))); 157 + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus())));
164 // 测试 type 不匹配 158 // 测试 type 不匹配
165 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus()))); 159 + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayOrderRefundStatusEnum.ALL.getStatus())));
166 // 测试 createTime 不匹配 160 // 测试 createTime 不匹配
167 refundMapper.insert(cloneIgnoreId(dbRefund, o -> 161 refundMapper.insert(cloneIgnoreId(dbRefund, o ->
168 o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10)))); 162 o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
@@ -174,7 +168,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -174,7 +168,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
174 reqVO.setMerchantRefundNo("MRF0000001"); 168 reqVO.setMerchantRefundNo("MRF0000001");
175 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); 169 reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
176 reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); 170 reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
177 - reqVO.setType(PayRefundTypeEnum.SOME.getStatus()); 171 + reqVO.setType(PayOrderRefundStatusEnum.PART.getStatus());
178 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)})); 172 reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
179 173
180 // 调用 174 // 调用