Commit 44b0346e5ea840fa3154498029ded3b9b3e2e288

Authored by YunaiV
1 parent eb660ca6

pay:示例订单,接入退款回调逻辑

Showing 21 changed files with 157 additions and 265 deletions
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java
1 package cn.iocoder.yudao.module.pay.api.notify.dto; 1 package cn.iocoder.yudao.module.pay.api.notify.dto;
2 2
  3 +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
3 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
4 import lombok.Builder; 5 import lombok.Builder;
5 import lombok.Data; 6 import lombok.Data;
@@ -31,12 +32,4 @@ public class PayRefundNotifyReqDTO { @@ -31,12 +32,4 @@ public class PayRefundNotifyReqDTO {
31 @NotNull(message = "支付退款编号不能为空") 32 @NotNull(message = "支付退款编号不能为空")
32 private Long payRefundId; 33 private Long payRefundId;
33 34
34 - /**  
35 - * 退款状态  
36 - *  
37 - * (成功,失败) TODO 芋艿:枚举  
38 - */  
39 - @NotNull(message = "退款状态不能为空")  
40 - private Integer status;  
41 -  
42 } 35 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java
@@ -29,12 +29,6 @@ public class PayRefundCreateReqDTO { @@ -29,12 +29,6 @@ public class PayRefundCreateReqDTO {
29 // ========== 商户相关字段 ========== 29 // ========== 商户相关字段 ==========
30 30
31 /** 31 /**
32 - * 商户订单编号  
33 - */  
34 - @NotEmpty(message = "商户订单编号不能为空")  
35 - private String merchantOrderId;  
36 -  
37 - /**  
38 * 退款描述 32 * 退款描述
39 */ 33 */
40 @NotEmpty(message = "退款描述不能为空") 34 @NotEmpty(message = "退款描述不能为空")
@@ -44,6 +38,12 @@ public class PayRefundCreateReqDTO { @@ -44,6 +38,12 @@ public class PayRefundCreateReqDTO {
44 // ========== 订单相关字段 ========== 38 // ========== 订单相关字段 ==========
45 39
46 /** 40 /**
  41 + * 支付单号
  42 + */
  43 + @NotNull(message = "支付单号不能为空")
  44 + private Long payOrderId;
  45 +
  46 + /**
47 * 退款金额,单位:分 47 * 退款金额,单位:分
48 */ 48 */
49 @NotNull(message = "退款金额不能为空") 49 @NotNull(message = "退款金额不能为空")
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java
@@ -27,8 +27,16 @@ public class PayRefundRespDTO { @@ -27,8 +27,16 @@ public class PayRefundRespDTO {
27 * 枚举 {@link PayRefundStatusEnum} 27 * 枚举 {@link PayRefundStatusEnum}
28 */ 28 */
29 private Integer status; 29 private Integer status;
  30 + /**
  31 + * 退款金额,单位:分
  32 + */
  33 + private Integer refundAmount;
30 34
31 - // ========== 渠道相关字段 ========== 35 + // ========== 商户相关字段 ==========
  36 + /**
  37 + * 商户订单编号
  38 + */
  39 + private String merchantOrderId;
32 /** 40 /**
33 * 退款成功时间 41 * 退款成功时间
34 */ 42 */
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -51,21 +51,23 @@ public interface ErrorCodeConstants { @@ -51,21 +51,23 @@ public interface ErrorCodeConstants {
51 ErrorCode PAY_REFUND_SUCCEED = new ErrorCode(1007006003, "已经退款成功"); 51 ErrorCode PAY_REFUND_SUCCEED = new ErrorCode(1007006003, "已经退款成功");
52 ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); 52 ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
53 53
54 -  
55 /** 54 /**
56 * ========== 支付商户信息 1-007-004-000 ========== 55 * ========== 支付商户信息 1-007-004-000 ==========
57 */ 56 */
58 ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); 57 ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
59 ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除"); 58 ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除");
60 59
61 -  
62 // ========== 示例订单 1-007-900-000 ========== 60 // ========== 示例订单 1-007-900-000 ==========
63 ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在"); 61 ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在");
64 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(100790001, "示例订单更新支付状态失败,订单不是【未支付】状态"); 62 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(100790001, "示例订单更新支付状态失败,订单不是【未支付】状态");
65 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(100790002, "示例订单更新支付状态失败,支付单编号不匹配"); 63 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(100790002, "示例订单更新支付状态失败,支付单编号不匹配");
66 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(100790003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态"); 64 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(100790003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");
67 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(100790004, "示例订单更新支付状态失败,支付单金额不匹配"); 65 ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(100790004, "示例订单更新支付状态失败,支付单金额不匹配");
68 - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(100790005, "发起退款失败,原因:示例订单未支付");  
69 - ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(100790005, "发起退款失败,原因:示例订单已退款"); 66 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(100790005, "发起退款失败,示例订单未支付");
  67 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(100790006, "发起退款失败,示例订单已退款");
  68 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(100790007, "发起退款失败,退款订单不存在");
  69 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(100790008, "发起退款失败,退款订单未退款成功");
  70 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(100790008, "发起退款失败,退款单编号不匹配");
  71 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(100790004, "发起退款失败,退款单金额不匹配");
70 72
71 } 73 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
@@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.pay.api.refund; @@ -2,9 +2,12 @@ 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.service.refund.PayRefundService;
5 import org.springframework.stereotype.Service; 6 import org.springframework.stereotype.Service;
6 import org.springframework.validation.annotation.Validated; 7 import org.springframework.validation.annotation.Validated;
7 8
  9 +import javax.annotation.Resource;
  10 +
8 /** 11 /**
9 * 退款单 API 实现类 12 * 退款单 API 实现类
10 * 13 *
@@ -14,10 +17,12 @@ import org.springframework.validation.annotation.Validated; @@ -14,10 +17,12 @@ import org.springframework.validation.annotation.Validated;
14 @Validated 17 @Validated
15 public class PayRefundApiImpl implements PayRefundApi { 18 public class PayRefundApiImpl implements PayRefundApi {
16 19
  20 + @Resource
  21 + private PayRefundService payRefundService;
  22 +
17 @Override 23 @Override
18 public Long createPayRefund(PayRefundCreateReqDTO reqDTO) { 24 public Long createPayRefund(PayRefundCreateReqDTO reqDTO) {
19 - // TODO 芋艿:暂未实现  
20 - return null; 25 + return payRefundService.createPayRefund(reqDTO);
21 } 26 }
22 27
23 @Override 28 @Override
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; 7 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
  8 +import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
8 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 9 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
9 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; 10 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO;
10 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert; 11 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
@@ -12,7 +13,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; @@ -12,7 +13,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
12 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService; 13 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
13 import io.swagger.v3.oas.annotations.Operation; 14 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 15 import io.swagger.v3.oas.annotations.Parameter;
15 -import io.swagger.v3.oas.annotations.media.Schema;  
16 import io.swagger.v3.oas.annotations.tags.Tag; 16 import io.swagger.v3.oas.annotations.tags.Tag;
17 import org.springframework.validation.annotation.Validated; 17 import org.springframework.validation.annotation.Validated;
18 import org.springframework.web.bind.annotation.*; 18 import org.springframework.web.bind.annotation.*;
@@ -58,11 +58,21 @@ public class PayDemoOrderController { @@ -58,11 +58,21 @@ public class PayDemoOrderController {
58 } 58 }
59 59
60 @PutMapping("/refund") 60 @PutMapping("/refund")
61 - @Operation(description = "退款示例订单") 61 + @Operation(description = "发起示例订单的退款")
62 @Parameter(name = "id", description = "编号", required = true, example = "1024") 62 @Parameter(name = "id", description = "编号", required = true, example = "1024")
63 public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) { 63 public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) {
64 payDemoOrderService.refundDemoOrder(id, getClientIP()); 64 payDemoOrderService.refundDemoOrder(id, getClientIP());
65 return success(true); 65 return success(true);
66 } 66 }
67 67
  68 + @PostMapping("/update-refunded")
  69 + @Operation(description = "更新示例订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
  70 + @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
  71 + @OperateLog(enable = false) // 禁用操作日志,因为没有操作人
  72 + public CommonResult<Boolean> updateDemoOrderRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
  73 + payDemoOrderService.updateDemoOrderRefunded(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
  74 + notifyReqDTO.getPayRefundId());
  75 + return success(true);
  76 + }
  77 +
68 } 78 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/AppPayRefundController.java deleted
1 -package cn.iocoder.yudao.module.pay.controller.app.refund;  
2 -  
3 -import cn.hutool.core.util.StrUtil;  
4 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
5 -import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundReqVO;  
6 -import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundRespVO;  
7 -import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;  
8 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO;  
9 -import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;  
10 -import cn.iocoder.yudao.module.pay.util.PaySeqUtils;  
11 -import io.swagger.v3.oas.annotations.tags.Tag;  
12 -import io.swagger.v3.oas.annotations.Operation;  
13 -import lombok.extern.slf4j.Slf4j;  
14 -import org.springframework.validation.annotation.Validated;  
15 -import org.springframework.web.bind.annotation.PostMapping;  
16 -import org.springframework.web.bind.annotation.RequestBody;  
17 -import org.springframework.web.bind.annotation.RequestMapping;  
18 -import org.springframework.web.bind.annotation.RestController;  
19 -  
20 -import javax.annotation.Resource;  
21 -  
22 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
23 -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;  
24 -  
25 -@Tag(name = "用户 APP - 退款订单")  
26 -@RestController  
27 -@RequestMapping("/pay/refund")  
28 -@Validated  
29 -@Slf4j  
30 -public class AppPayRefundController {  
31 -  
32 - @Resource  
33 - private PayRefundService refundService;  
34 -  
35 - @PostMapping("/refund")  
36 - @Operation(summary = "提交退款订单")  
37 - public CommonResult<AppPayRefundRespVO> submitRefundOrder(@RequestBody AppPayRefundReqVO reqVO){  
38 - PayRefundReqDTO req = PayRefundConvert.INSTANCE.convert(reqVO);  
39 - req.setUserIp(getClientIP());  
40 - // TODO 测试暂时模拟生成商户退款订单  
41 - if(StrUtil.isEmpty(reqVO.getMerchantRefundId())) {  
42 - req.setMerchantRefundId(PaySeqUtils.genMerchantRefundNo());  
43 - }  
44 - return success(PayRefundConvert.INSTANCE.convert(refundService.submitRefundOrder(req)));  
45 - }  
46 -  
47 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/package-info.java 0 → 100644
  1 +/**
  2 + * TODO 芋艿:占个位置,没啥用
  3 + */
  4 +package cn.iocoder.yudao.module.pay.controller.app.refund;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundReqVO.java deleted
1 -package cn.iocoder.yudao.module.pay.controller.app.refund.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -  
8 -import javax.validation.constraints.NotEmpty;  
9 -import javax.validation.constraints.NotNull;  
10 -  
11 -@Schema(description = "用户 APP - 退款订单 Req VO")  
12 -@Data  
13 -@NoArgsConstructor  
14 -@AllArgsConstructor  
15 -public class AppPayRefundReqVO {  
16 -  
17 - @Schema(description = "支付订单编号自增", required = true, example = "10")  
18 - @NotNull(message = "支付订单编号自增")  
19 - private Long payOrderId;  
20 -  
21 - @Schema(description = "退款金额", required = true, example = "1")  
22 - @NotNull(message = "退款金额")  
23 - private Long amount;  
24 -  
25 - @Schema(description = "退款原因", required = true, example = "不喜欢")  
26 - @NotEmpty(message = "退款原因")  
27 - private String reason;  
28 -  
29 - @Schema(description = "商户退款订单号", required = true, example = "MR202111180000000001")  
30 - //TODO 测试暂时模拟生成  
31 - //@NotEmpty(message = "商户退款订单号")  
32 - private String merchantRefundId;  
33 -  
34 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundRespVO.java deleted
1 -package cn.iocoder.yudao.module.pay.controller.app.refund.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Builder;  
6 -import lombok.Data;  
7 -import lombok.NoArgsConstructor;  
8 -import lombok.experimental.Accessors;  
9 -  
10 -@Schema(description = "用户 APP - 提交退款订单 Response VO")  
11 -@Data  
12 -@Accessors(chain = true)  
13 -@Builder  
14 -@NoArgsConstructor  
15 -@AllArgsConstructor  
16 -public class AppPayRefundRespVO {  
17 -  
18 - @Schema(description = "退款订单编号", required = true, example = "10")  
19 - private Long refundId;  
20 -  
21 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java
@@ -2,12 +2,8 @@ package cn.iocoder.yudao.module.pay.convert.refund; @@ -2,12 +2,8 @@ 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.controller.admin.refund.vo.*; 4 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*;
5 -import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundReqVO;  
6 -import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundRespVO;  
7 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
8 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
9 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO;  
10 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundRespDTO;  
11 import org.mapstruct.Mapper; 7 import org.mapstruct.Mapper;
12 import org.mapstruct.Mapping; 8 import org.mapstruct.Mapping;
13 import org.mapstruct.Mappings; 9 import org.mapstruct.Mappings;
@@ -17,11 +13,6 @@ import java.math.BigDecimal; @@ -17,11 +13,6 @@ import java.math.BigDecimal;
17 import java.math.RoundingMode; 13 import java.math.RoundingMode;
18 import java.util.List; 14 import java.util.List;
19 15
20 -/**  
21 - * 退款订单 Convert  
22 - *  
23 - * @author aquan  
24 - */  
25 @Mapper 16 @Mapper
26 public interface PayRefundConvert { 17 public interface PayRefundConvert {
27 18
@@ -102,8 +93,4 @@ public interface PayRefundConvert { @@ -102,8 +93,4 @@ public interface PayRefundConvert {
102 }) 93 })
103 PayRefundDO convert(PayOrderDO orderDO); 94 PayRefundDO convert(PayOrderDO orderDO);
104 95
105 - PayRefundReqDTO convert(AppPayRefundReqVO bean);  
106 -  
107 - AppPayRefundRespVO convert(PayRefundRespDTO bean);  
108 -  
109 } 96 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoOrderDO.java
@@ -83,6 +83,6 @@ public class PayDemoOrderDO extends BaseDO { @@ -83,6 +83,6 @@ public class PayDemoOrderDO extends BaseDO {
83 /** 83 /**
84 * 退款完成时间 84 * 退款完成时间
85 */ 85 */
86 - private Date refundTime; 86 + private LocalDateTime refundTime;
87 87
88 } 88 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java
@@ -80,7 +80,6 @@ public class PayRefundDO extends BaseDO { @@ -80,7 +80,6 @@ public class PayRefundDO extends BaseDO {
80 */ 80 */
81 private String tradeNo; 81 private String tradeNo;
82 82
83 -  
84 // ========== 商户相关字段 ========== 83 // ========== 商户相关字段 ==========
85 /** 84 /**
86 * 商户订单编号 85 * 商户订单编号
@@ -171,14 +170,12 @@ public class PayRefundDO extends BaseDO { @@ -171,14 +170,12 @@ public class PayRefundDO extends BaseDO {
171 */ 170 */
172 private String channelErrorMsg; 171 private String channelErrorMsg;
173 172
174 -  
175 /** 173 /**
176 * 支付渠道的额外参数 174 * 支付渠道的额外参数
177 * 参见 https://www.pingxx.com/api/Refunds%20退款概述.html 175 * 参见 https://www.pingxx.com/api/Refunds%20退款概述.html
178 */ 176 */
179 private String channelExtras; 177 private String channelExtras;
180 178
181 -  
182 /** 179 /**
183 * TODO 180 * TODO
184 * 退款失效时间 181 * 退款失效时间
@@ -193,5 +190,4 @@ public class PayRefundDO extends BaseDO { @@ -193,5 +190,4 @@ public class PayRefundDO extends BaseDO {
193 */ 190 */
194 private LocalDateTime notifyTime; 191 private LocalDateTime notifyTime;
195 192
196 -  
197 } 193 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderService.java
@@ -48,11 +48,19 @@ public interface PayDemoOrderService { @@ -48,11 +48,19 @@ public interface PayDemoOrderService {
48 void updateDemoOrderPaid(Long id, Long payOrderId); 48 void updateDemoOrderPaid(Long id, Long payOrderId);
49 49
50 /** 50 /**
51 - * 退款示例订单 51 + * 发起示例订单的退款
52 * 52 *
53 * @param id 编号 53 * @param id 编号
54 * @param userIp 用户编号 54 * @param userIp 用户编号
55 */ 55 */
56 void refundDemoOrder(Long id, String userIp); 56 void refundDemoOrder(Long id, String userIp);
57 57
  58 + /**
  59 + * 更新示例订单为已退款
  60 + *
  61 + * @param id 编号
  62 + * @param payRefundId 退款订单号
  63 + */
  64 + void updateDemoOrderRefunded(Long id, Long payRefundId);
  65 +
58 } 66 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
@@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; @@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
10 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 10 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
11 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; 11 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
12 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 12 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
  13 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
13 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 14 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
14 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 15 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
15 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; 16 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
16 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 17 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
  18 +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
17 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
18 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
19 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
@@ -23,9 +25,12 @@ import java.time.Duration; @@ -23,9 +25,12 @@ import java.time.Duration;
23 import java.time.LocalDateTime; 25 import java.time.LocalDateTime;
24 import java.util.HashMap; 26 import java.util.HashMap;
25 import java.util.Map; 27 import java.util.Map;
  28 +import java.util.Objects;
26 29
  30 +import static cn.hutool.core.util.ObjectUtil.*;
27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
28 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; 32 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
  33 +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
29 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 34 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
30 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 35 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
31 36
@@ -137,46 +142,46 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -137,46 +142,46 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
137 * @return 交易订单 142 * @return 交易订单
138 */ 143 */
139 private PayOrderRespDTO validateDemoOrderCanPaid(Long id, Long payOrderId) { 144 private PayOrderRespDTO validateDemoOrderCanPaid(Long id, Long payOrderId) {
140 - // 校验订单是否存在 145 + // 1.1 校验订单是否存在
141 PayDemoOrderDO order = payDemoOrderMapper.selectById(id); 146 PayDemoOrderDO order = payDemoOrderMapper.selectById(id);
142 if (order == null) { 147 if (order == null) {
143 throw exception(PAY_DEMO_ORDER_NOT_FOUND); 148 throw exception(PAY_DEMO_ORDER_NOT_FOUND);
144 } 149 }
145 - // 校验订单未支付 150 + // 1.2 校验订单未支付
146 if (order.getPayed()) { 151 if (order.getPayed()) {
147 log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", 152 log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]",
148 - id, JsonUtils.toJsonString(order)); 153 + id, toJsonString(order));
149 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); 154 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
150 } 155 }
151 - // 校验支付订单匹配  
152 - if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 156 + // 1.3 校验支付订单匹配
  157 + if (notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
153 log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", 158 log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
154 - id, payOrderId, JsonUtils.toJsonString(order)); 159 + id, payOrderId, toJsonString(order));
155 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); 160 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
156 } 161 }
157 162
158 - // 校验支付单是否存在 163 + // 2.1 校验支付单是否存在
159 PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); 164 PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
160 if (payOrder == null) { 165 if (payOrder == null) {
161 log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); 166 log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
162 throw exception(PAY_ORDER_NOT_FOUND); 167 throw exception(PAY_ORDER_NOT_FOUND);
163 } 168 }
164 - // 校验支付单已支付 169 + // 2.2 校验支付单已支付
165 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { 170 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
166 log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", 171 log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
167 - id, payOrderId, JsonUtils.toJsonString(payOrder)); 172 + id, payOrderId, toJsonString(payOrder));
168 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); 173 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS);
169 } 174 }
170 - // 校验支付金额一致  
171 - if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPrice())) { 175 + // 2.3 校验支付金额一致
  176 + if (notEqual(payOrder.getAmount(), order.getPrice())) {
172 log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", 177 log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
173 - id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder)); 178 + id, payOrderId, toJsonString(order), toJsonString(payOrder));
174 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); 179 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH);
175 } 180 }
176 - // 校验支付订单匹配(二次)  
177 - if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) { 181 + // 2.4 校验支付订单匹配(二次)
  182 + if (notEqual(payOrder.getMerchantOrderId(), id.toString())) {
178 log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", 183 log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
179 - id, payOrderId, JsonUtils.toJsonString(payOrder)); 184 + id, payOrderId, toJsonString(payOrder));
180 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); 185 throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
181 } 186 }
182 return payOrder; 187 return payOrder;
@@ -190,9 +195,9 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -190,9 +195,9 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
190 // 2.1 创建退款单 195 // 2.1 创建退款单
191 Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO() 196 Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO()
192 .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用 197 .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
193 - .setMerchantOrderId(order.getId().toString()) // 业务的订单编号  
194 - .setReason("想退钱").setAmount(order.getPrice())); // 价格信息  
195 - // 2.2 更新支付单到 demo 订单 198 + .setPayOrderId(order.getPayOrderId()) // 支付单号
  199 + .setReason("想退钱").setAmount(order.getPrice()));// 价格信息
  200 + // 2.2 更新退款单到 demo 订单
196 payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id) 201 payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
197 .setPayRefundId(payRefundId).setRefundPrice(order.getPrice())); 202 .setPayRefundId(payRefundId).setRefundPrice(order.getPrice()));
198 } 203 }
@@ -207,11 +212,57 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -207,11 +212,57 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
207 if (!order.getPayed()) { 212 if (!order.getPayed()) {
208 throw exception(PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID); 213 throw exception(PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID);
209 } 214 }
210 - // 校验是否已经发起退款 215 + // 校验订单是否已退款
211 if (order.getPayRefundId() != null) { 216 if (order.getPayRefundId() != null) {
212 throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED); 217 throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED);
213 } 218 }
214 return order; 219 return order;
215 } 220 }
216 221
  222 + @Override
  223 + public void updateDemoOrderRefunded(Long id, Long payRefundId) {
  224 + // 1. 校验并获得退款订单(可退款)
  225 + PayRefundRespDTO payRefund = validateDemoOrderCanRefunded(id, payRefundId);
  226 + // 2.2 更新退款单到 demo 订单
  227 + payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
  228 + .setRefundTime(payRefund.getSuccessTime()));
  229 + }
  230 +
  231 + private PayRefundRespDTO validateDemoOrderCanRefunded(Long id, Long payRefundId) {
  232 + // 1.1 校验示例订单
  233 + PayDemoOrderDO order = payDemoOrderMapper.selectById(id);
  234 + if (order == null) {
  235 + throw exception(PAY_DEMO_ORDER_NOT_FOUND);
  236 + }
  237 + // 1.2 校验退款订单匹配
  238 + if (Objects.equals(order.getPayOrderId(), payRefundId)) {
  239 + log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]",
  240 + id, payRefundId, toJsonString(order));
  241 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR);
  242 + }
  243 +
  244 + // 2.1 校验退款订单
  245 + PayRefundRespDTO payRefund = payRefundApi.getPayRefund(payRefundId);
  246 + if (payRefund == null) {
  247 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND);
  248 + }
  249 + // 2.2
  250 + if (!PayRefundStatusEnum.isSuccess(payRefund.getStatus())) {
  251 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS);
  252 + }
  253 + // 2.3 校验退款金额一致
  254 + if (notEqual(payRefund.getRefundAmount(), order.getPrice())) {
  255 + log.error("[validateDemoOrderCanRefunded][order({}) payRefund({}) 退款金额不匹配,请进行处理!order 数据是:{},payRefund 数据是:{}]",
  256 + id, payRefundId, toJsonString(order), toJsonString(payRefund));
  257 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH);
  258 + }
  259 + // 2.4 校验退款订单匹配(二次)
  260 + if (notEqual(payRefund.getMerchantOrderId(), id.toString())) {
  261 + log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!payRefund 数据是:{}]",
  262 + id, payRefundId, toJsonString(payRefund));
  263 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR);
  264 + }
  265 + return payRefund;
  266 + }
  267 +
217 } 268 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java deleted
1 -package cn.iocoder.yudao.module.pay.service.order.dto;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Builder;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -import lombok.experimental.Accessors;  
8 -  
9 -import javax.validation.constraints.DecimalMin;  
10 -import javax.validation.constraints.NotEmpty;  
11 -import javax.validation.constraints.NotNull;  
12 -  
13 -// TODO 芋艿:可能需要改造  
14 -  
15 -/**  
16 - * 退款申请单 Request DTO  
17 - */  
18 -@Data  
19 -@Accessors(chain = true)  
20 -@Builder  
21 -@NoArgsConstructor  
22 -@AllArgsConstructor  
23 -public class PayRefundReqDTO {  
24 -  
25 - /**  
26 - * 支付订单编号  
27 - */  
28 - @NotNull(message = "支付订单编号不能为空")  
29 - private Long payOrderId;  
30 -  
31 - /**  
32 - * 退款金额  
33 - */  
34 - @NotNull(message = "退款金额不能为空")  
35 - @DecimalMin(value = "0", inclusive = false, message = "退款金额必须大于零")  
36 - private Integer amount;  
37 -  
38 - /**  
39 - * 退款原因  
40 - */  
41 - private String reason;  
42 -  
43 - /**  
44 - * 商户退款订单号  
45 - */  
46 - @NotEmpty(message = "商户退款订单号不能为空")  
47 - private String merchantRefundId;  
48 -  
49 - /**  
50 - * 用户 IP  
51 - */  
52 - private String userIp;  
53 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundRespDTO.java deleted
1 -package cn.iocoder.yudao.module.pay.service.order.dto;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Builder;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -import lombok.experimental.Accessors;  
8 -  
9 -/**  
10 - * 退款申请单 Response DTO  
11 - */  
12 -@Data  
13 -@Accessors(chain = true)  
14 -@Builder  
15 -@NoArgsConstructor  
16 -@AllArgsConstructor  
17 -public class PayRefundRespDTO {  
18 -  
19 - /**  
20 - * 支付退款单编号,自增  
21 - */  
22 - private Long refundId;  
23 -  
24 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java
1 package cn.iocoder.yudao.module.pay.service.refund; 1 package cn.iocoder.yudao.module.pay.service.refund;
2 2
3 import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; 3 import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
  4 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
4 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; 5 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
5 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 8 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
8 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO;  
9 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundRespDTO;  
10 9
11 import java.util.List; 10 import java.util.List;
12 11
@@ -42,12 +41,12 @@ public interface PayRefundService { @@ -42,12 +41,12 @@ public interface PayRefundService {
42 List<PayRefundDO> getRefundList(PayRefundExportReqVO exportReqVO); 41 List<PayRefundDO> getRefundList(PayRefundExportReqVO exportReqVO);
43 42
44 /** 43 /**
45 - * 提交退款申请 44 + * 创建退款申请
46 * 45 *
47 * @param reqDTO 退款申请信息 46 * @param reqDTO 退款申请信息
48 - * @return 退款申请返回信息 47 + * @return 退款单号
49 */ 48 */
50 - PayRefundRespDTO submitRefundOrder(PayRefundReqDTO reqDTO); 49 + Long createPayRefund(PayRefundCreateReqDTO reqDTO);
51 50
52 /** 51 /**
53 * 渠道的退款通知 52 * 渠道的退款通知
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.util.RandomUtil;
3 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; 5 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
5 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
@@ -10,6 +11,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO; @@ -10,6 +11,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO;
10 import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; 11 import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO;
11 import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; 12 import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO;
12 import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum; 13 import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
  14 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
13 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; 15 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
14 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; 16 import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
15 import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; 17 import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO;
@@ -32,8 +34,6 @@ import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; @@ -32,8 +34,6 @@ import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
32 import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; 34 import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
33 import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; 35 import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService;
34 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 36 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
35 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO;  
36 -import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundRespDTO;  
37 import lombok.extern.slf4j.Slf4j; 37 import lombok.extern.slf4j.Slf4j;
38 import org.springframework.stereotype.Service; 38 import org.springframework.stereotype.Service;
39 import org.springframework.transaction.annotation.Transactional; 39 import org.springframework.transaction.annotation.Transactional;
@@ -90,9 +90,9 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -90,9 +90,9 @@ public class PayRefundServiceImpl implements PayRefundService {
90 90
91 @Override 91 @Override
92 @Transactional(rollbackFor = Exception.class) 92 @Transactional(rollbackFor = Exception.class)
93 - public PayRefundRespDTO submitRefundOrder(PayRefundReqDTO req) { 93 + public Long createPayRefund(PayRefundCreateReqDTO reqDTO) {
94 // 获得 PayOrderDO 94 // 获得 PayOrderDO
95 - PayOrderDO order = orderService.getOrder(req.getPayOrderId()); 95 + PayOrderDO order = orderService.getOrder(reqDTO.getPayOrderId());
96 // 校验订单是否存在 96 // 校验订单是否存在
97 if (Objects.isNull(order) ) { 97 if (Objects.isNull(order) ) {
98 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); 98 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);
@@ -108,15 +108,19 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -108,15 +108,19 @@ public class PayRefundServiceImpl implements PayRefundService {
108 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); 108 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND);
109 } 109 }
110 110
  111 + // TODO 芋艿:待实现
  112 + String merchantRefundId = RandomUtil.randomNumbers(16);
  113 +
111 // 校验退款的条件 114 // 校验退款的条件
112 - validatePayRefund(req, order); 115 + validatePayRefund(reqDTO, order);
113 // 退款类型 116 // 退款类型
114 PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME; 117 PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME;
115 - if (Objects.equals(req.getAmount(), order.getAmount())) { 118 + if (Objects.equals(reqDTO.getAmount(), order.getAmount())) {
116 refundType = PayRefundTypeEnum.ALL; 119 refundType = PayRefundTypeEnum.ALL;
117 } 120 }
118 PayOrderExtensionDO orderExtensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); 121 PayOrderExtensionDO orderExtensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());
119 - PayRefundDO payRefundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundId()); 122 + PayRefundDO payRefundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(),
  123 + merchantRefundId); // TODO 芋艿:需要优化
120 if(Objects.nonNull(payRefundDO)){ 124 if(Objects.nonNull(payRefundDO)){
121 // 退款订单已经提交过。 125 // 退款订单已经提交过。
122 //TODO 校验相同退款单的金额 126 //TODO 校验相同退款单的金额
@@ -137,15 +141,15 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -137,15 +141,15 @@ public class PayRefundServiceImpl implements PayRefundService {
137 .channelId(order.getChannelId()) 141 .channelId(order.getChannelId())
138 .merchantId(order.getMerchantId()) 142 .merchantId(order.getMerchantId())
139 .orderId(order.getId()) 143 .orderId(order.getId())
140 - .merchantRefundNo(req.getMerchantRefundId()) 144 + .merchantRefundNo(merchantRefundId) // TODO 芋艿:需要优化
141 .notifyUrl(app.getRefundNotifyUrl()) 145 .notifyUrl(app.getRefundNotifyUrl())
142 .payAmount(order.getAmount()) 146 .payAmount(order.getAmount())
143 - .refundAmount(req.getAmount())  
144 - .userIp(req.getUserIp()) 147 + .refundAmount(reqDTO.getAmount())
  148 + .userIp(reqDTO.getUserIp())
145 .merchantOrderId(order.getMerchantOrderId()) 149 .merchantOrderId(order.getMerchantOrderId())
146 .tradeNo(orderExtensionDO.getNo()) 150 .tradeNo(orderExtensionDO.getNo())
147 .status(PayRefundStatusEnum.CREATE.getStatus()) 151 .status(PayRefundStatusEnum.CREATE.getStatus())
148 - .reason(req.getReason()) 152 + .reason(reqDTO.getReason())
149 .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus()) 153 .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus())
150 .type(refundType.getStatus()) 154 .type(refundType.getStatus())
151 .build(); 155 .build();
@@ -153,12 +157,12 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -153,12 +157,12 @@ public class PayRefundServiceImpl implements PayRefundService {
153 } 157 }
154 // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; 158 // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下;
155 PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO(); 159 PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
156 - unifiedReqDTO.setUserIp(req.getUserIp())  
157 - .setAmount(req.getAmount()) 160 + unifiedReqDTO.setUserIp(reqDTO.getUserIp())
  161 + .setAmount(reqDTO.getAmount())
158 .setChannelOrderNo(order.getChannelOrderNo()) 162 .setChannelOrderNo(order.getChannelOrderNo())
159 .setPayTradeNo(orderExtensionDO.getNo()) 163 .setPayTradeNo(orderExtensionDO.getNo())
160 - .setMerchantRefundId(req.getMerchantRefundId())  
161 - .setReason(req.getReason()); 164 + .setMerchantRefundId(merchantRefundId) // TODO 芋艿:需要优化
  165 + .setReason(reqDTO.getReason());
162 // 向渠道发起退款申请 166 // 向渠道发起退款申请
163 PayCommonResult<PayRefundUnifiedRespDTO> refundUnifiedResult = client.unifiedRefund(unifiedReqDTO); 167 PayCommonResult<PayRefundUnifiedRespDTO> refundUnifiedResult = client.unifiedRefund(unifiedReqDTO);
164 // 检查是否失败,失败抛出业务异常。 168 // 检查是否失败,失败抛出业务异常。
@@ -166,7 +170,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -166,7 +170,7 @@ public class PayRefundServiceImpl implements PayRefundService {
166 // TODO @jason:可以先打个 warn log 哈; 170 // TODO @jason:可以先打个 warn log 哈;
167 refundUnifiedResult.checkError(); 171 refundUnifiedResult.checkError();
168 // 成功在 退款回调中处理 172 // 成功在 退款回调中处理
169 - return PayRefundRespDTO.builder().refundId(payRefundDO.getId()).build(); 173 + return payRefundDO.getId();
170 } 174 }
171 175
172 @Override 176 @Override
@@ -235,10 +239,11 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -235,10 +239,11 @@ public class PayRefundServiceImpl implements PayRefundService {
235 239
236 /** 240 /**
237 * 校验是否进行退款 241 * 校验是否进行退款
238 - * @param req 退款申请信息 242 + *
  243 + * @param reqDTO 退款申请信息
239 * @param order 原始支付订单信息 244 * @param order 原始支付订单信息
240 */ 245 */
241 - private void validatePayRefund(PayRefundReqDTO req, PayOrderDO order) { 246 + private void validatePayRefund(PayRefundCreateReqDTO reqDTO, PayOrderDO order) {
242 // 校验状态,必须是支付状态 247 // 校验状态,必须是支付状态
243 if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { 248 if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
244 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS); 249 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS);
@@ -248,7 +253,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -248,7 +253,7 @@ public class PayRefundServiceImpl implements PayRefundService {
248 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED); 253 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED);
249 } 254 }
250 // 校验金额 退款金额不能大于 原定的金额 255 // 校验金额 退款金额不能大于 原定的金额
251 - if (req.getAmount() + order.getRefundAmount() > order.getAmount()){ 256 + if (reqDTO.getAmount() + order.getRefundAmount() > order.getAmount()){
252 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_AMOUNT_EXCEED); 257 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_AMOUNT_EXCEED);
253 } 258 }
254 // 校验渠道订单号 259 // 校验渠道订单号
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/PaySeqUtils.java
@@ -18,6 +18,7 @@ public class PaySeqUtils { @@ -18,6 +18,7 @@ public class PaySeqUtils {
18 18
19 private static final AtomicLong MER_ORDER_NO_SEQ = new AtomicLong(0L); 19 private static final AtomicLong MER_ORDER_NO_SEQ = new AtomicLong(0L);
20 20
  21 + // TODO 芋艿:需要看看
21 /** 22 /**
22 * 生成商户退款单号,用于测试,应该由商户系统生成 23 * 生成商户退款单号,用于测试,应该由商户系统生成
23 * @return 商户退款单 24 * @return 商户退款单
@@ -28,6 +29,8 @@ public class PaySeqUtils { @@ -28,6 +29,8 @@ public class PaySeqUtils {
28 (int) MER_REFUND_NO_SEQ.getAndIncrement() % 10000); 29 (int) MER_REFUND_NO_SEQ.getAndIncrement() % 10000);
29 } 30 }
30 31
  32 + // TODO 芋艿:需要看看
  33 +
31 /** 34 /**
32 * 生成退款请求号 35 * 生成退款请求号
33 * @return 退款请求号 36 * @return 退款请求号
yudao-ui-admin/src/views/pay/demo/index.vue
@@ -206,7 +206,7 @@ export default { @@ -206,7 +206,7 @@ export default {
206 return refundDemoOrder(id); 206 return refundDemoOrder(id);
207 }).then(() => { 207 }).then(() => {
208 this.getList(); 208 this.getList();
209 - this.$modal.msgSuccess("退款成功"); 209 + this.$modal.msgSuccess("发起退款成功!");
210 }).catch(() => {}); 210 }).catch(() => {});
211 } 211 }
212 } 212 }