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

This commit is contained in:
YunaiV 2023-02-15 22:40:56 +08:00
parent 333adc989f
commit eb660ca619
9 changed files with 98 additions and 12 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.pay.enums; package cn.iocoder.yudao.module.pay.enums;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/** /**
@ -60,8 +61,11 @@ public interface ErrorCodeConstants {
// ========== 示例订单 1-007-900-000 ========== // ========== 示例订单 1-007-900-000 ==========
ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在"); ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "示例订单更新支付状态失败,订单不是【未支付】状态"); ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(100790001, "示例订单更新支付状态失败,订单不是【未支付】状态");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "示例订单更新支付状态失败,支付单编号不匹配"); ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(100790002, "示例订单更新支付状态失败,支付单编号不匹配");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态"); ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(100790003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "示例订单更新支付状态失败,支付单金额不匹配"); ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(100790004, "示例订单更新支付状态失败,支付单金额不匹配");
ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(100790005, "发起退款失败,原因:示例订单未支付");
ErrorCode PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(100790005, "发起退款失败,原因:示例订单已退款");
} }

View File

@ -11,6 +11,8 @@ import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService; import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -20,6 +22,7 @@ import javax.annotation.security.PermitAll;
import javax.validation.Valid; import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 示例订单") @Tag(name = "管理后台 - 示例订单")
@ -54,4 +57,12 @@ public class PayDemoOrderController {
return success(true); return success(true);
} }
@PutMapping("/refund")
@Operation(description = "退款示例订单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) {
payDemoOrderService.refundDemoOrder(id, getClientIP());
return success(true);
}
} }

View File

@ -36,6 +36,12 @@ public class PayDemoOrderRespVO {
@Schema(description = "订单支付时间") @Schema(description = "订单支付时间")
private LocalDateTime payTime; private LocalDateTime payTime;
@Schema(description = "支付渠道", example = "alipay_qr")
private String payChannelCode;
@Schema(description = "支付退款编号", example = "23366")
private Long payRefundId;
@Schema(description = "退款金额,单位:分", required = true, example = "14039") @Schema(description = "退款金额,单位:分", required = true, example = "14039")
private Integer refundPrice; private Integer refundPrice;

View File

@ -73,13 +73,15 @@ public class PayDemoOrderDO extends BaseDO {
// ========== 退款相关字段 ========== // ========== 退款相关字段 ==========
/** /**
* 退款金额 * 支付退款单号
*/
private Long payRefundId;
/**
* 退款金额单位
*/ */
private Integer refundPrice; private Integer refundPrice;
/** /**
* 退款时间 * 退款完成时间
*
* 由于可以多次退款记录最后一次退款的时间
*/ */
private Date refundTime; private Date refundTime;

View File

@ -47,4 +47,12 @@ public interface PayDemoOrderService {
*/ */
void updateDemoOrderPaid(Long id, Long payOrderId); void updateDemoOrderPaid(Long id, Long payOrderId);
/**
* 退款示例订单
*
* @param id 编号
* @param userIp 用户编号
*/
void refundDemoOrder(Long id, String userIp);
} }

View File

@ -2,16 +2,16 @@ package cn.iocoder.yudao.module.pay.service.demo;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -56,6 +56,8 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
@Resource @Resource
private PayOrderApi payOrderApi; private PayOrderApi payOrderApi;
@Resource
private PayRefundApi payRefundApi;
@Resource @Resource
private PayDemoOrderMapper payDemoOrderMapper; private PayDemoOrderMapper payDemoOrderMapper;
@ -180,4 +182,36 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
return payOrder; return payOrder;
} }
@Override
public void refundDemoOrder(Long id, String userIp) {
// 1. 校验订单是否可以退款
PayDemoOrderDO order = validateDemoOrderCanRefund(id);
// 2.1 创建退款单
Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO()
.setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
.setMerchantOrderId(order.getId().toString()) // 业务的订单编号
.setReason("想退钱").setAmount(order.getPrice())); // 价格信息
// 2.2 更新支付单到 demo 订单
payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
.setPayRefundId(payRefundId).setRefundPrice(order.getPrice()));
}
private PayDemoOrderDO validateDemoOrderCanRefund(Long id) {
// 校验订单是否存在
PayDemoOrderDO order = payDemoOrderMapper.selectById(id);
if (order == null) {
throw exception(PAY_DEMO_ORDER_NOT_FOUND);
}
// 校验订单是否支付
if (!order.getPayed()) {
throw exception(PAY_DEMO_ORDER_REFUND_FAIL_NOT_PAID);
}
// 校验是否已经发起退款
if (order.getPayRefundId() != null) {
throw exception(PAY_DEMO_ORDER_REFUND_FAIL_REFUNDED);
}
return order;
}
} }

View File

@ -78,7 +78,7 @@ spring:
# Quartz 配置项,对应 QuartzProperties 配置类 # Quartz 配置项,对应 QuartzProperties 配置类
spring: spring:
quartz: quartz:
auto-startup: false # 本地开发环境,尽量不要开启 Job auto-startup: true # 本地开发环境,尽量不要开启 Job
scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true

View File

@ -25,3 +25,11 @@ export function getDemoOrderPage(query) {
params: query params: query
}) })
} }
// 退款示例订单
export function refundDemoOrder(id) {
return request({
url: '/pay/demo-order/refund?id=' + id,
method: 'put'
})
}

View File

@ -48,6 +48,8 @@
<template v-slot="scope"> <template v-slot="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)" <el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)"
v-if="!scope.row.payed">前往支付</el-button> v-if="!scope.row.payed">前往支付</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleRefund(scope.row)"
v-if="scope.row.payed && !scope.row.payRefundId">发起退款</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -76,7 +78,8 @@
</template> </template>
<script> <script>
import { createDemoOrder, getDemoOrderPage } from "@/api/pay/demo"; import {createDemoOrder, getDemoOrderPage, refundDemoOrder} from "@/api/pay/demo";
import {deleteMerchant} from "@/api/pay/merchant";
export default { export default {
name: "PayDemoOrder", name: "PayDemoOrder",
@ -195,6 +198,16 @@ export default {
id: row.payOrderId id: row.payOrderId
} }
}) })
},
/** 退款按钮操作 */
handleRefund(row) {
const id = row.id;
this.$modal.confirm('是否确认退款编号为"' + id + '"的示例订单?').then(function() {
return refundDemoOrder(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("退款成功");
}).catch(() => {});
} }
} }
}; };