Commit 44b0346e5ea840fa3154498029ded3b9b3e2e288
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
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
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 | } |