Commit eb660ca6196b9c2f886b3428b0e4972ac139cb63

Authored by YunaiV
1 parent 333adc98

pay:示例订单,增加发起退款的操作

yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
1 package cn.iocoder.yudao.module.pay.enums; 1 package cn.iocoder.yudao.module.pay.enums;
2 2
  3 +import cn.hutool.core.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.exception.ErrorCode; 4 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 5
5 /** 6 /**
@@ -60,8 +61,11 @@ public interface ErrorCodeConstants { @@ -60,8 +61,11 @@ public interface ErrorCodeConstants {
60 61
61 // ========== 示例订单 1-007-900-000 ========== 62 // ========== 示例订单 1-007-900-000 ==========
62 ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在"); 63 ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在");
63 - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "示例订单更新支付状态失败,订单不是【未支付】状态");  
64 - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "示例订单更新支付状态失败,支付单编号不匹配");  
65 - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");  
66 - ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "示例订单更新支付状态失败,支付单金额不匹配"); 64 + 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, "示例订单更新支付状态失败,支付单编号不匹配");
  66 + 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, "示例订单更新支付状态失败,支付单金额不匹配");
  68 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(100790005, "发起退款失败,原因:示例订单未支付");
  69 + ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(100790005, "发起退款失败,原因:示例订单已退款");
  70 +
67 } 71 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
@@ -11,6 +11,8 @@ import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert; @@ -11,6 +11,8 @@ import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
11 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 11 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
12 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService; 12 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
13 import io.swagger.v3.oas.annotations.Operation; 13 import io.swagger.v3.oas.annotations.Operation;
  14 +import io.swagger.v3.oas.annotations.Parameter;
  15 +import io.swagger.v3.oas.annotations.media.Schema;
14 import io.swagger.v3.oas.annotations.tags.Tag; 16 import io.swagger.v3.oas.annotations.tags.Tag;
15 import org.springframework.validation.annotation.Validated; 17 import org.springframework.validation.annotation.Validated;
16 import org.springframework.web.bind.annotation.*; 18 import org.springframework.web.bind.annotation.*;
@@ -20,6 +22,7 @@ import javax.annotation.security.PermitAll; @@ -20,6 +22,7 @@ import javax.annotation.security.PermitAll;
20 import javax.validation.Valid; 22 import javax.validation.Valid;
21 23
22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
23 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 26 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
24 27
25 @Tag(name = "管理后台 - 示例订单") 28 @Tag(name = "管理后台 - 示例订单")
@@ -54,4 +57,12 @@ public class PayDemoOrderController { @@ -54,4 +57,12 @@ public class PayDemoOrderController {
54 return success(true); 57 return success(true);
55 } 58 }
56 59
  60 + @PutMapping("/refund")
  61 + @Operation(description = "退款示例订单")
  62 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  63 + public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) {
  64 + payDemoOrderService.refundDemoOrder(id, getClientIP());
  65 + return success(true);
  66 + }
  67 +
57 } 68 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/PayDemoOrderRespVO.java
@@ -36,6 +36,12 @@ public class PayDemoOrderRespVO { @@ -36,6 +36,12 @@ public class PayDemoOrderRespVO {
36 @Schema(description = "订单支付时间") 36 @Schema(description = "订单支付时间")
37 private LocalDateTime payTime; 37 private LocalDateTime payTime;
38 38
  39 + @Schema(description = "支付渠道", example = "alipay_qr")
  40 + private String payChannelCode;
  41 +
  42 + @Schema(description = "支付退款编号", example = "23366")
  43 + private Long payRefundId;
  44 +
39 @Schema(description = "退款金额,单位:分", required = true, example = "14039") 45 @Schema(description = "退款金额,单位:分", required = true, example = "14039")
40 private Integer refundPrice; 46 private Integer refundPrice;
41 47
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoOrderDO.java
@@ -73,13 +73,15 @@ public class PayDemoOrderDO extends BaseDO { @@ -73,13 +73,15 @@ public class PayDemoOrderDO extends BaseDO {
73 73
74 // ========== 退款相关字段 ========== 74 // ========== 退款相关字段 ==========
75 /** 75 /**
76 - * 退款金额 76 + * 支付退款单号
  77 + */
  78 + private Long payRefundId;
  79 + /**
  80 + * 退款金额,单位:分
77 */ 81 */
78 private Integer refundPrice; 82 private Integer refundPrice;
79 /** 83 /**
80 - * 退款时间  
81 - *  
82 - * 由于可以多次退款,记录最后一次退款的时间 84 + * 退款完成时间
83 */ 85 */
84 private Date refundTime; 86 private Date refundTime;
85 87
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderService.java
@@ -47,4 +47,12 @@ public interface PayDemoOrderService { @@ -47,4 +47,12 @@ public interface PayDemoOrderService {
47 */ 47 */
48 void updateDemoOrderPaid(Long id, Long payOrderId); 48 void updateDemoOrderPaid(Long id, Long payOrderId);
49 49
  50 + /**
  51 + * 退款示例订单
  52 + *
  53 + * @param id 编号
  54 + * @param userIp 用户编号
  55 + */
  56 + void refundDemoOrder(Long id, String userIp);
  57 +
50 } 58 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
@@ -2,16 +2,16 @@ package cn.iocoder.yudao.module.pay.service.demo; @@ -2,16 +2,16 @@ package cn.iocoder.yudao.module.pay.service.demo;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 -import cn.iocoder.yudao.framework.common.core.KeyValue;  
6 import cn.iocoder.yudao.framework.common.pojo.PageParam; 5 import cn.iocoder.yudao.framework.common.pojo.PageParam;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; 8 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
10 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 9 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
11 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;
  12 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
12 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 13 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
13 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 14 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
14 -import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;  
15 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; 15 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
16 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 16 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
17 import lombok.extern.slf4j.Slf4j; 17 import lombok.extern.slf4j.Slf4j;
@@ -56,6 +56,8 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -56,6 +56,8 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
56 56
57 @Resource 57 @Resource
58 private PayOrderApi payOrderApi; 58 private PayOrderApi payOrderApi;
  59 + @Resource
  60 + private PayRefundApi payRefundApi;
59 61
60 @Resource 62 @Resource
61 private PayDemoOrderMapper payDemoOrderMapper; 63 private PayDemoOrderMapper payDemoOrderMapper;
@@ -180,4 +182,36 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -180,4 +182,36 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
180 return payOrder; 182 return payOrder;
181 } 183 }
182 184
  185 + @Override
  186 + public void refundDemoOrder(Long id, String userIp) {
  187 + // 1. 校验订单是否可以退款
  188 + PayDemoOrderDO order = validateDemoOrderCanRefund(id);
  189 +
  190 + // 2.1 创建退款单
  191 + Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO()
  192 + .setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
  193 + .setMerchantOrderId(order.getId().toString()) // 业务的订单编号
  194 + .setReason("想退钱").setAmount(order.getPrice())); // 价格信息
  195 + // 2.2 更新支付单到 demo 订单
  196 + payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
  197 + .setPayRefundId(payRefundId).setRefundPrice(order.getPrice()));
  198 + }
  199 +
  200 + private PayDemoOrderDO validateDemoOrderCanRefund(Long id) {
  201 + // 校验订单是否存在
  202 + PayDemoOrderDO order = payDemoOrderMapper.selectById(id);
  203 + if (order == null) {
  204 + throw exception(PAY_DEMO_ORDER_NOT_FOUND);
  205 + }
  206 + // 校验订单是否支付
  207 + if (!order.getPayed()) {
  208 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID);
  209 + }
  210 + // 校验是否已经发起退款
  211 + if (order.getPayRefundId() != null) {
  212 + throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED);
  213 + }
  214 + return order;
  215 + }
  216 +
183 } 217 }
yudao-server/src/main/resources/application-local.yaml
@@ -78,7 +78,7 @@ spring: @@ -78,7 +78,7 @@ spring:
78 # Quartz 配置项,对应 QuartzProperties 配置类 78 # Quartz 配置项,对应 QuartzProperties 配置类
79 spring: 79 spring:
80 quartz: 80 quartz:
81 - auto-startup: false # 本地开发环境,尽量不要开启 Job 81 + auto-startup: true # 本地开发环境,尽量不要开启 Job
82 scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName 82 scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
83 job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 83 job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
84 wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true 84 wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
yudao-ui-admin/src/api/pay/demo.js
@@ -25,3 +25,11 @@ export function getDemoOrderPage(query) { @@ -25,3 +25,11 @@ export function getDemoOrderPage(query) {
25 params: query 25 params: query
26 }) 26 })
27 } 27 }
  28 +
  29 +// 退款示例订单
  30 +export function refundDemoOrder(id) {
  31 + return request({
  32 + url: '/pay/demo-order/refund?id=' + id,
  33 + method: 'put'
  34 + })
  35 +}
yudao-ui-admin/src/views/pay/demo/index.vue
@@ -48,6 +48,8 @@ @@ -48,6 +48,8 @@
48 <template v-slot="scope"> 48 <template v-slot="scope">
49 <el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)" 49 <el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)"
50 v-if="!scope.row.payed">前往支付</el-button> 50 v-if="!scope.row.payed">前往支付</el-button>
  51 + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleRefund(scope.row)"
  52 + v-if="scope.row.payed && !scope.row.payRefundId">发起退款</el-button>
51 </template> 53 </template>
52 </el-table-column> 54 </el-table-column>
53 </el-table> 55 </el-table>
@@ -76,7 +78,8 @@ @@ -76,7 +78,8 @@
76 </template> 78 </template>
77 79
78 <script> 80 <script>
79 -import { createDemoOrder, getDemoOrderPage } from "@/api/pay/demo"; 81 +import {createDemoOrder, getDemoOrderPage, refundDemoOrder} from "@/api/pay/demo";
  82 +import {deleteMerchant} from "@/api/pay/merchant";
80 83
81 export default { 84 export default {
82 name: "PayDemoOrder", 85 name: "PayDemoOrder",
@@ -195,6 +198,16 @@ export default { @@ -195,6 +198,16 @@ export default {
195 id: row.payOrderId 198 id: row.payOrderId
196 } 199 }
197 }) 200 })
  201 + },
  202 + /** 退款按钮操作 */
  203 + handleRefund(row) {
  204 + const id = row.id;
  205 + this.$modal.confirm('是否确认退款编号为"' + id + '"的示例订单?').then(function() {
  206 + return refundDemoOrder(id);
  207 + }).then(() => {
  208 + this.getList();
  209 + this.$modal.msgSuccess("退款成功");
  210 + }).catch(() => {});
198 } 211 }
199 } 212 }
200 }; 213 };