fix 支付同步/退款/回调/修复, 状态流转错误和部分数据保存错误

This commit is contained in:
bootx
2024-02-09 22:55:43 +08:00
parent 40f61c0740
commit fcc73d680e
11 changed files with 42 additions and 29 deletions

View File

@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 支付修复方式
* 支付修复方式, 包含退款的修复方式, 退款修复方式是支付修复的子集
* @author xxm
* @since 2023/12/28
*/
@@ -12,11 +12,13 @@ import lombok.Getter;
@AllArgsConstructor
public enum PayRepairWayEnum {
SUCCESS("pay_success","支付成功"),
PAY_SUCCESS("pay_success","支付成功"),
CLOSE_LOCAL("pay_close_local","关闭本地支付"),
PROGRESS("pay_progress","切换到支付中"),
/** 同时也会关闭本地支付 */
CLOSE_GATEWAY("pay_close_gateway","关闭网关支付");
CLOSE_GATEWAY("pay_close_gateway","关闭网关支付"),
REFUND_SUCCESS("refund_success","退款成功"),
REFUND_FAIL("refund_fail","退款失败");;
private final String code;
private final String name;

View File

@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 退款修复方式枚举
* 退款修复方式枚举, 支付修复方式包含退款的修复方式, 退款修复方式是支付修复的子集
* @author xxm
* @since 2024/1/26
*/
@@ -12,8 +12,8 @@ import lombok.Getter;
@AllArgsConstructor
public enum RefundRepairWayEnum {
SUCCESS("refund_success","退款成功"),
FAIL("refund_fail","退款失败");
REFUND_SUCCESS("refund_success","退款成功"),
REFUND_FAIL("refund_fail","退款失败");
private final String code;
private final String name;

View File

@@ -93,8 +93,10 @@ public class PayCallbackService {
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.EXCEPTION).setMsg("支付单不是待支付状态,记录回调记录");
return;
}
// 设置支付成功时间
PaymentContextLocal.get().getRepairInfo().setFinishTime(callbackInfo.getFinishTime());
// 执行支付完成修复逻辑
PayRepairResult repair = payRepairService.repair(payOrder, PayRepairWayEnum.SUCCESS);
PayRepairResult repair = payRepairService.repair(payOrder, PayRepairWayEnum.PAY_SUCCESS);
callbackInfo.setPayRepairNo(repair.getRepairNo());
}

View File

@@ -56,14 +56,17 @@ public class PayRefundCallbackService {
// 退款单已经被处理, 记录回调记录
if (!Objects.equals(RefundStatusEnum.PROGRESS.getCode(), refundOrder.getStatus())) {
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.IGNORE).setMsg("退款单状态已处理,记录回调记录");
return;
}
// 退款成功还是失败
if (Objects.equals(RefundStatusEnum.SUCCESS.getCode(), callbackInfo.getGatewayStatus())) {
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.SUCCESS);
PaymentContextLocal.get().getRepairInfo().setFinishTime(callbackInfo.getFinishTime());
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.REFUND_SUCCESS);
callbackInfo.setPayRepairNo(repair.getRepairNo());
} else {
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.FAIL);
// 设置退款订单完成时间
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.REFUND_FAIL);
callbackInfo.setPayRepairNo(repair.getRepairNo());
}
@@ -71,5 +74,4 @@ public class PayRefundCallbackService {
lockTemplate.releaseLock(lock);
}
}
}

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.service;
import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
@@ -67,7 +68,7 @@ public class PayRepairService {
// 3. 根据不同的类型执行对应的修复逻辑
PayRepairResult repairResult = new PayRepairResult().setBeforeStatus(PayStatusEnum.findByCode(order.getStatus()));
switch (repairType) {
case SUCCESS:
case PAY_SUCCESS:
this.success(order, repairStrategies);
repairResult.setAfterPayStatus(PayStatusEnum.SUCCESS);
break;
@@ -85,6 +86,7 @@ public class PayRepairService {
break;
default:
log.error("走到了理论上讲不会走到的分支");
throw new PayFailureException("走到了理论上讲不会走到的分支");
}
// 设置修复iD
repairResult.setRepairNo(IdUtil.getSnowflakeNextIdStr());

View File

@@ -82,9 +82,9 @@ public class RefundRepairService {
// 根据不同的类型执行对应的修复逻辑
RefundRepairResult repairResult = new RefundRepairResult();
if (Objects.requireNonNull(repairType) == RefundRepairWayEnum.SUCCESS) {
if (Objects.requireNonNull(repairType) == RefundRepairWayEnum.REFUND_SUCCESS) {
repairResult = this.success(refundOrder,payOrder,repairStrategies);
} else if (repairType == RefundRepairWayEnum.FAIL) {
} else if (repairType == RefundRepairWayEnum.REFUND_FAIL) {
repairResult = this.close(refundOrder,payOrder,repairStrategies);
} else {
log.error("走到了理论上讲不会走到的分支");
@@ -92,7 +92,9 @@ public class RefundRepairService {
// 设置修复ID并保存修复记录
repairResult.setRepairNo(IdUtil.getSnowflakeNextIdStr());
// 支付修复记录
PayRepairRecord payRepairRecord = this.payRepairRecord(payOrder, repairType, repairResult);
// 退款修复记录
PayRepairRecord refundRepairRecord = this.refundRepairRecord(refundOrder, repairType, repairResult);
recordService.saveAllRecord(Arrays.asList(payRepairRecord, refundRepairRecord));
@@ -105,7 +107,7 @@ public class RefundRepairService {
private RefundRepairResult success(PayRefundOrder refundOrder, PayOrder payOrder, List<AbsRefundRepairStrategy> repairStrategies) {
RepairLocal repairInfo = PaymentContextLocal.get().getRepairInfo();
// 订单相关状态
PayStatusEnum beforePayStatus = PayStatusEnum.findByCode(refundOrder.getStatus());
PayStatusEnum beforePayStatus = PayStatusEnum.findByCode(payOrder.getStatus());
PayStatusEnum afterPayRefundStatus;
RefundStatusEnum beforeRefundStatus = RefundStatusEnum.findByCode(refundOrder.getStatus());
@@ -198,10 +200,11 @@ public class RefundRepairService {
* 支付订单的修复记录
* 支付完成 -> 退款
* 退款 -> 全部退款
* @param repairType 支付订单修复方式状态编码跟退款修复的状态一致,
*/
private PayRepairRecord payRepairRecord(PayOrder order, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
// 修复的状态
String afterStatus = Optional.ofNullable(repairResult.getBeforePayStatus()).map(PayStatusEnum::getCode).orElse(null);
// 修复的状态
String beforeStatus = Optional.ofNullable(repairResult.getBeforePayStatus()).map(PayStatusEnum::getCode).orElse(null);
// 修复发起来源
String source = PaymentContextLocal.get()
.getRepairInfo()
@@ -214,8 +217,8 @@ public class RefundRepairService {
.setRepairWay(repairType.getCode())
.setAsyncChannel(order.getAsyncChannel())
.setOrderNo(order.getBusinessNo())
.setBeforeStatus(repairResult.getAfterPayStatus().getCode())
.setAfterStatus(afterStatus);
.setBeforeStatus(beforeStatus)
.setAfterStatus(repairResult.getAfterPayStatus().getCode());
}
/**

View File

@@ -172,14 +172,14 @@ public class PayRefundSyncService {
switch (syncStatusEnum) {
// 调用出错
case SUCCESS:
repair = repairService.repair(order, RefundRepairWayEnum.SUCCESS);
repair = repairService.repair(order, RefundRepairWayEnum.REFUND_SUCCESS);
break;
case PROGRESS:
// 不进行处理
log.warn("退款状态同步接口调用出错");
break;
case FAIL: {
repair = repairService.repair(order, RefundRepairWayEnum.FAIL);
repair = repairService.repair(order, RefundRepairWayEnum.REFUND_FAIL);
break;
}
default: {

View File

@@ -131,7 +131,6 @@ public class PaySyncService {
// 同步失败, 返回失败响应, 同时记录失败的日志
syncResult.setSyncStatus(PaySyncStatusEnum.FAIL);
this.saveRecord(payOrder, syncResult, false, null, e.getMessage());
// return new SyncResult().setErrorMsg(e.getMessage());
throw e;
}
@@ -199,7 +198,7 @@ public class PaySyncService {
switch (syncStatusEnum) {
// 支付成功 支付宝退款时也是支付成功状态, 除非支付完成
case SUCCESS: {
repair = repairService.repair(payOrder, PayRepairWayEnum.SUCCESS);
repair = repairService.repair(payOrder, PayRepairWayEnum.PAY_SUCCESS);
break;
}
// 待支付, 将订单状态重新设置为待支付

View File

@@ -37,7 +37,7 @@ public class PayExpiredTimeTask {
*/
@Scheduled(cron = "*/5 * * * * ?")
public void task(){
log.debug("执行超时取消任务....");
// log.debug("执行超时取消任务....");
Set<String> expiredKeys = repository.getExpiredKeys(LocalDateTime.now());
for (String expiredKey : expiredKeys) {
LockInfo lock = lockTemplate.lock("payment:expired:" + expiredKey,10000,0);

View File

@@ -7,6 +7,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 支付订单关联通道信息
* @author xxm
@@ -36,6 +38,11 @@ public class PayChannelOrderDto extends BaseDto {
@Schema(description = "关联网关支付号")
private String gatewayOrderNo;
@Schema(description = "金额")
private Integer amount;
@Schema(description = "可退款金额")
private Integer refundableBalance;
/**
* 支付状态
* @see PayStatusEnum
@@ -43,9 +50,6 @@ public class PayChannelOrderDto extends BaseDto {
@Schema(description = "支付状态")
private String status;
@Schema(description = "金额")
private Integer amount;
@Schema(description = "可退款金额")
private Integer refundableBalance;
@Schema(description = "支付时间")
private LocalDateTime payTime;
}

View File

@@ -54,7 +54,6 @@ public abstract class AbsCallbackStrategy implements PayStrategy {
// 提前设置订单修复的来源
PaymentContextLocal.get().getRepairInfo().setSource(PayRepairSourceEnum.CALLBACK);
if (callbackType == PaymentTypeEnum.PAY){
// 解析支付数据并放处理
this.resolvePayData();