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 1 package cn.iocoder.yudao.module.pay.enums;
2 2  
  3 +import cn.hutool.core.util.ObjectUtil;
3 4 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 5  
5 6 /**
... ... @@ -60,8 +61,11 @@ public interface ErrorCodeConstants {
60 61  
61 62 // ========== 示例订单 1-007-900-000 ==========
62 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 11 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
12 12 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
13 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 16 import io.swagger.v3.oas.annotations.tags.Tag;
15 17 import org.springframework.validation.annotation.Validated;
16 18 import org.springframework.web.bind.annotation.*;
... ... @@ -20,6 +22,7 @@ import javax.annotation.security.PermitAll;
20 22 import javax.validation.Valid;
21 23  
22 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
23 26 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
24 27  
25 28 @Tag(name = "管理后台 - 示例订单")
... ... @@ -54,4 +57,12 @@ public class PayDemoOrderController {
54 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 36 @Schema(description = "订单支付时间")
37 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 45 @Schema(description = "退款金额,单位:分", required = true, example = "14039")
40 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 73  
74 74 // ========== 退款相关字段 ==========
75 75 /**
76   - * 退款金额
  76 + * 支付退款单号
  77 + */
  78 + private Long payRefundId;
  79 + /**
  80 + * 退款金额,单位:分
77 81 */
78 82 private Integer refundPrice;
79 83 /**
80   - * 退款时间
81   - *
82   - * 由于可以多次退款,记录最后一次退款的时间
  84 + * 退款完成时间
83 85 */
84 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 47 */
48 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 2  
3 3 import cn.hutool.core.lang.Assert;
4 4 import cn.hutool.core.util.ObjectUtil;
5   -import cn.iocoder.yudao.framework.common.core.KeyValue;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageParam;
7 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 8 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
10 9 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
11 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 13 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
13 14 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
14   -import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
15 15 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
16 16 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
17 17 import lombok.extern.slf4j.Slf4j;
... ... @@ -56,6 +56,8 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
56 56  
57 57 @Resource
58 58 private PayOrderApi payOrderApi;
  59 + @Resource
  60 + private PayRefundApi payRefundApi;
59 61  
60 62 @Resource
61 63 private PayDemoOrderMapper payDemoOrderMapper;
... ... @@ -180,4 +182,36 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
180 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 78 # Quartz 配置项,对应 QuartzProperties 配置类
79 79 spring:
80 80 quartz:
81   - auto-startup: false # 本地开发环境,尽量不要开启 Job
  81 + auto-startup: true # 本地开发环境,尽量不要开启 Job
82 82 scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
83 83 job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
84 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 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 48 <template v-slot="scope">
49 49 <el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)"
50 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 53 </template>
52 54 </el-table-column>
53 55 </el-table>
... ... @@ -76,7 +78,8 @@
76 78 </template>
77 79  
78 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 84 export default {
82 85 name: "PayDemoOrder",
... ... @@ -195,6 +198,16 @@ export default {
195 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 };
... ...