mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-07 04:58:28 +00:00
feat 支付订单/退款订单/支付通道配置列表
This commit is contained in:
@@ -50,10 +50,13 @@
|
||||
- [x] (前端) 支付修复记录
|
||||
- 2024-01-12:
|
||||
- [x] (前端) 支付订单
|
||||
- [ ] (前端) 退款订单
|
||||
- [x] (前端) 退款订单
|
||||
- [x] (前端) 支付通道配置列表
|
||||
- 2024-01-13:
|
||||
- [ ] (前端) 微信/支付宝支付通道配置
|
||||
- [ ] 支付通道支持停用
|
||||
- **任务池**
|
||||
- [ ] 支付宝方式支持撤销方式,
|
||||
- [ ] 支付宝关闭支付时支持撤销方式,
|
||||
- [ ] 支持转账操作, 通过支付通道专有参数进行实现, 转账时只能单个通道进行操作
|
||||
- [ ] 支付成功回调后, 如果订单已超时, 则进入待退款订单中,提示进行退款,或者自动退款
|
||||
- [ ] 退款状态同步逻辑
|
||||
|
@@ -4,15 +4,22 @@ import cn.bootx.platform.common.core.rest.PageResult;
|
||||
import cn.bootx.platform.common.core.rest.Res;
|
||||
import cn.bootx.platform.common.core.rest.ResResult;
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.spring.util.WebServletUtil;
|
||||
import cn.bootx.platform.daxpay.param.pay.RefundParam;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.service.PayRefundOrderService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.refund.service.PayRefundService;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.param.order.PayOrderRefundParam;
|
||||
import cn.bootx.platform.daxpay.service.param.order.PayRefundOrderQuery;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 支付退款控制器
|
||||
@@ -25,6 +32,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequiredArgsConstructor
|
||||
public class PayRefundOrderController {
|
||||
private final PayRefundOrderService payRefundOrderService;
|
||||
private final PayRefundService payRefundService;
|
||||
|
||||
|
||||
@Operation(summary = "分页查询")
|
||||
@@ -38,4 +46,22 @@ public class PayRefundOrderController {
|
||||
public ResResult<PayRefundOrderDto> findById(Long paymentId){
|
||||
return Res.ok(payRefundOrderService.findById(paymentId));
|
||||
}
|
||||
|
||||
@Operation(summary = "发起退款")
|
||||
@PostMapping("/refund")
|
||||
public ResResult<Void> refund(@RequestBody PayOrderRefundParam param){
|
||||
|
||||
String ip = Optional.ofNullable(WebServletUtil.getRequest())
|
||||
.map(ServletUtil::getClientIP)
|
||||
.orElse("未知");
|
||||
|
||||
RefundParam refundParam = new RefundParam();
|
||||
refundParam.setRefundNo(IdUtil.getSnowflakeNextIdStr());
|
||||
refundParam.setPaymentId(param.getPaymentId());
|
||||
refundParam.setRefundChannels(param.getRefundChannels());
|
||||
refundParam.setReqTime(LocalDateTime.now());
|
||||
refundParam.setClientIp(ip);
|
||||
payRefundService.refund(refundParam);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ import lombok.Getter;
|
||||
public enum PayRefundStatusEnum {
|
||||
|
||||
SUCCESS("success","成功"),
|
||||
FAIL("fail","失败");
|
||||
FAIL("fail"," ");
|
||||
|
||||
/** 编码 */
|
||||
private final String code;
|
||||
|
@@ -49,7 +49,7 @@ public abstract class PayCommonParam {
|
||||
/** API版本号 */
|
||||
@Schema(description = "API版本号")
|
||||
@NotBlank(message = "API版本号必填")
|
||||
private String version;
|
||||
private String version = "1.0.0";
|
||||
|
||||
/** 请求时间,时间戳转时间 */
|
||||
@Schema(description = "请求时间,传输时间戳")
|
||||
|
@@ -24,7 +24,7 @@ public class RefundParam extends PayCommonParam {
|
||||
private String businessNo;
|
||||
|
||||
/**
|
||||
* 部分退款需要传输refundModes参数
|
||||
* 部分退款需要传输支付通道参数参数
|
||||
*/
|
||||
@Schema(description = "是否全部退款")
|
||||
private boolean refundAll;
|
||||
|
@@ -33,10 +33,10 @@ public class PaySyncResult extends PayCommonResult{
|
||||
private boolean repair;
|
||||
|
||||
@Schema(description = "支付单修复前状态")
|
||||
private String oldStatus;
|
||||
private String beforeStatus;
|
||||
|
||||
@Schema(description = "支付单修复后状态")
|
||||
private String repairStatus;
|
||||
private String afterStatus;
|
||||
|
||||
@Schema(description = "失败原因")
|
||||
private String errorMsg;
|
||||
|
@@ -13,6 +13,7 @@ import lombok.experimental.Accessors;
|
||||
@Accessors(chain = true)
|
||||
public class RefundableInfo {
|
||||
/**
|
||||
* 通道
|
||||
* @see PayChannelEnum#getCode()
|
||||
*/
|
||||
private String channel;
|
||||
|
@@ -63,7 +63,7 @@ public class WechatRefundService {
|
||||
if (StrUtil.isBlank(weChatPayConfig.getP12())){
|
||||
String errorMsg = "微信p.12证书未配置,无法进行退款";
|
||||
refundInfo.setErrorMsg(errorMsg);
|
||||
refundInfo.setErrorCode(PayRefundStatusEnum.SUCCESS.getCode());
|
||||
refundInfo.setErrorCode(PayRefundStatusEnum.FAIL.getCode());
|
||||
throw new PayFailureException(errorMsg);
|
||||
}
|
||||
byte[] fileBytes = Base64.decode(weChatPayConfig.getP12());
|
||||
|
@@ -92,15 +92,15 @@ public class PaySyncService {
|
||||
AbsPaySyncStrategy syncPayStrategy = PaySyncStrategyFactory.create(payOrder.getAsyncChannel());
|
||||
syncPayStrategy.initPayParam(payOrder);
|
||||
// 记录支付单同步前后的状态
|
||||
String oldStatus = payOrder.getStatus();
|
||||
String repairStatus = null;
|
||||
String beforeStatus = payOrder.getStatus();
|
||||
String afterStatus = null;
|
||||
|
||||
// 执行同步操作, 获取支付网关同步的结果
|
||||
GatewaySyncResult syncResult = syncPayStrategy.doSyncStatus();
|
||||
// 判断是否同步成功
|
||||
if (Objects.equals(syncResult.getSyncStatus(), PaySyncStatusEnum.FAIL)){
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
this.saveRecord(payOrder, syncResult, true, oldStatus, null, syncResult.getErrorMsg());
|
||||
this.saveRecord(payOrder, syncResult, true, beforeStatus, null, syncResult.getErrorMsg());
|
||||
return new PaySyncResult().setErrorMsg(syncResult.getErrorMsg());
|
||||
}
|
||||
|
||||
@@ -110,23 +110,23 @@ public class PaySyncService {
|
||||
// 状态不一致,执行支付单修复逻辑
|
||||
if (!statusSync){
|
||||
this.resultHandler(syncResult, payOrder);
|
||||
repairStatus = payOrder.getStatus();
|
||||
afterStatus = payOrder.getStatus();
|
||||
}
|
||||
} catch (PayFailureException e) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
syncResult.setSyncStatus(PaySyncStatusEnum.FAIL);
|
||||
this.saveRecord(payOrder, syncResult, false, oldStatus, null, e.getMessage());
|
||||
this.saveRecord(payOrder, syncResult, false, beforeStatus, null, e.getMessage());
|
||||
return new PaySyncResult().setErrorMsg(e.getMessage());
|
||||
}
|
||||
|
||||
// 同步成功记录日志
|
||||
this.saveRecord( payOrder, syncResult, !statusSync, oldStatus, repairStatus, null);
|
||||
this.saveRecord( payOrder, syncResult, !statusSync, beforeStatus, afterStatus, null);
|
||||
return new PaySyncResult()
|
||||
.setGatewayStatus(syncResult.getSyncStatus().getCode())
|
||||
.setSuccess(true)
|
||||
.setRepair(!statusSync)
|
||||
.setOldStatus(oldStatus)
|
||||
.setRepairStatus(repairStatus);
|
||||
.setBeforeStatus(beforeStatus)
|
||||
.setAfterStatus(afterStatus);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
@@ -233,11 +233,11 @@ public class PaySyncService {
|
||||
* @param payOrder 支付单
|
||||
* @param syncResult 同步结果
|
||||
* @param repair 是否修复
|
||||
* @param oldStatus 修复前的状态
|
||||
* @param beforeStatus 修复前的状态
|
||||
* @param repairStatus 修复后的状态
|
||||
* @param errorMsg 错误信息
|
||||
*/
|
||||
private void saveRecord(PayOrder payOrder,GatewaySyncResult syncResult, boolean repair, String oldStatus, String repairStatus, String errorMsg){
|
||||
private void saveRecord(PayOrder payOrder,GatewaySyncResult syncResult, boolean repair, String beforeStatus, String repairStatus, String errorMsg){
|
||||
PaySyncRecord paySyncRecord = new PaySyncRecord()
|
||||
.setPaymentId(payOrder.getId())
|
||||
.setBusinessNo(payOrder.getBusinessNo())
|
||||
@@ -245,8 +245,8 @@ public class PaySyncService {
|
||||
.setSyncInfo(syncResult.getSyncInfo())
|
||||
.setGatewayStatus(syncResult.getSyncStatus().getCode())
|
||||
.setRepairOrder(repair)
|
||||
.setOldStatus(oldStatus)
|
||||
.setRepairStatus(repairStatus)
|
||||
.setBeforeStatus(beforeStatus)
|
||||
.setAfterStatus(repairStatus)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setClientIp(PaymentContextLocal.get().getRequest().getClientIp())
|
||||
.setReqId(PaymentContextLocal.get().getRequest().getReqId());
|
||||
|
@@ -62,11 +62,10 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
|
||||
|
||||
/** 支付单修复前状态 */
|
||||
@DbColumn(comment = "支付单修复前状态")
|
||||
private String oldStatus;
|
||||
private String beforeStatus;
|
||||
/** 支付单修复后状态 */
|
||||
|
||||
@DbColumn(comment = "支付单修复后状态")
|
||||
private String repairStatus;
|
||||
private String afterStatus;
|
||||
|
||||
@DbColumn(comment = "错误消息")
|
||||
private String errorMsg;
|
||||
|
@@ -22,15 +22,6 @@ public class AliPayConfigDto extends BaseDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6641158663606363171L;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "商户编码")
|
||||
private String mchCode;
|
||||
|
||||
@Schema(description = "商户应用编码")
|
||||
private String mchAppCode;
|
||||
|
||||
@Schema(description = "支付宝商户appId")
|
||||
@SensitiveInfo
|
||||
private String appId;
|
||||
@@ -38,9 +29,6 @@ public class AliPayConfigDto extends BaseDto implements Serializable {
|
||||
@Schema(description = "服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问")
|
||||
private String notifyUrl;
|
||||
|
||||
@Schema(description = "页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址")
|
||||
private String returnUrl;
|
||||
|
||||
@Schema(description = "请求网关地址")
|
||||
private String serverUrl;
|
||||
|
||||
|
@@ -0,0 +1,28 @@
|
||||
package cn.bootx.platform.daxpay.service.param.order;
|
||||
|
||||
import cn.bootx.platform.daxpay.param.pay.RefundChannelParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付订单退款发起参数
|
||||
* @author xxm
|
||||
* @since 2024/1/12
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付订单退款发起参数")
|
||||
public class PayOrderRefundParam {
|
||||
|
||||
/** 支付id */
|
||||
private Long paymentId;
|
||||
|
||||
/** 原因 */
|
||||
private String reason;
|
||||
|
||||
/** 退款明细 */
|
||||
private List<RefundChannelParam> refundChannels;
|
||||
}
|
Reference in New Issue
Block a user