mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-06 12:39:38 +00:00
ref 交易调整功能重构
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package cn.daxpay.single.service.code;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 退款修复方式枚举
|
||||
* @author xxm
|
||||
* @since 2024/1/26
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RefundAdjustWayEnum {
|
||||
|
||||
SUCCESS("success","退款成功"),
|
||||
FAIL("fail","退款失败");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package cn.daxpay.single.service.code;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 退款修复方式枚举, 支付修复方式包含退款的修复方式, 退款修复方式是支付修复的子集
|
||||
* @author xxm
|
||||
* @since 2024/1/26
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RefundRepairWayEnum {
|
||||
|
||||
REFUND_SUCCESS("refund_success","退款成功"),
|
||||
REFUND_FAIL("refund_fail","退款失败");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
}
|
@@ -14,7 +14,6 @@ public enum TradeAdjustSourceEnum {
|
||||
|
||||
SYNC("sync","同步"),
|
||||
CALLBACK("callback","回调"),
|
||||
TASK("task","定时任务"),
|
||||
;
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
@@ -12,7 +12,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 回调信息上下文
|
||||
* 回调信息上下文 针对支付和退款的回调
|
||||
* @author xxm
|
||||
* @since 2024/1/24
|
||||
*/
|
||||
@@ -49,9 +49,6 @@ public class CallbackLocal {
|
||||
/** 完成时间(支付/退款) */
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
/** 修复号 */
|
||||
private String repairNo;
|
||||
|
||||
/** 回调类型 */
|
||||
private TradeTypeEnum callbackType;
|
||||
|
||||
@@ -61,6 +58,10 @@ public class CallbackLocal {
|
||||
*/
|
||||
private PayCallbackStatusEnum callbackStatus = PayCallbackStatusEnum.SUCCESS;
|
||||
|
||||
|
||||
/** 调整号 */
|
||||
private String adjustNo;
|
||||
|
||||
/** 提示信息 */
|
||||
private String errorMsg;
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
@@ -71,9 +70,6 @@ public class AliPayCallbackService {
|
||||
callbackService.saveCallbackRecord();
|
||||
return null;
|
||||
}
|
||||
// 提前设置订单修复的来源
|
||||
PaymentContextLocal.get().getRepairInfo().setSource(TradeAdjustSourceEnum.CALLBACK);
|
||||
|
||||
if (callbackType == TradeTypeEnum.PAY){
|
||||
// 解析支付数据并放处理
|
||||
this.resolvePayData();
|
||||
|
@@ -73,7 +73,7 @@ public class AliPaySyncService {
|
||||
if (Objects.equals(tradeStatus, AliPayCode.NOTIFY_TRADE_SUCCESS) || Objects.equals(tradeStatus, AliPayCode.NOTIFY_TRADE_FINISHED)) {
|
||||
// 支付完成时间
|
||||
LocalDateTime payTime = LocalDateTimeUtil.of(response.getSendPayDate());
|
||||
return syncResult.setSyncStatus(PaySyncStatusEnum.SUCCESS).setPayTime(payTime);
|
||||
return syncResult.setSyncStatus(PaySyncStatusEnum.SUCCESS).setFinishTime(payTime);
|
||||
}
|
||||
// 待支付
|
||||
if (Objects.equals(tradeStatus, AliPayCode.NOTIFY_WAIT_BUYER_PAY)) {
|
||||
|
@@ -5,7 +5,6 @@ import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.code.UnionPayCode;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
@@ -69,9 +68,6 @@ public class UnionPayCallbackService {
|
||||
callbackService.saveCallbackRecord();
|
||||
return null;
|
||||
}
|
||||
// 提前设置订单修复的来源
|
||||
PaymentContextLocal.get().getRepairInfo().setSource(TradeAdjustSourceEnum.CALLBACK);
|
||||
|
||||
if (callbackType == TradeTypeEnum.PAY){
|
||||
// 解析支付数据并放处理
|
||||
this.resolvePayData();
|
||||
|
@@ -72,7 +72,7 @@ public class UnionPaySyncService {
|
||||
String queryId = MapUtil.getStr(result, QUERY_ID);
|
||||
String timeEnd = MapUtil.getStr(result, TXN_TIME);
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(timeEnd, DatePattern.PURE_DATETIME_PATTERN);
|
||||
return syncResult.setOutOrderNo(queryId).setPayTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS);
|
||||
return syncResult.setOutOrderNo(queryId).setFinishTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS);
|
||||
}
|
||||
|
||||
// 支付超时 交易不在受理时间范围内
|
||||
|
@@ -5,7 +5,6 @@ import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
@@ -69,9 +68,6 @@ public class WeChatPayCallbackService {
|
||||
callbackService.saveCallbackRecord();
|
||||
return null;
|
||||
}
|
||||
// 提前设置订单修复的来源
|
||||
PaymentContextLocal.get().getRepairInfo().setSource(TradeAdjustSourceEnum.CALLBACK);
|
||||
|
||||
if (callbackType == TradeTypeEnum.PAY){
|
||||
// 解析支付数据并放处理
|
||||
this.resolvePayData();
|
||||
|
@@ -74,7 +74,7 @@ public class WeChatPaySyncService {
|
||||
if (Objects.equals(tradeStatus, WeChatPayCode.PAY_SUCCESS) || Objects.equals(tradeStatus, WeChatPayCode.PAY_ACCEPT)) {
|
||||
String timeEnd = result.get(WeChatPayCode.TIME_END);
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(timeEnd, DatePattern.PURE_DATETIME_PATTERN);
|
||||
return syncResult.setPayTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS);
|
||||
return syncResult.setFinishTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS);
|
||||
}
|
||||
// 待支付
|
||||
if (Objects.equals(tradeStatus, WeChatPayCode.PAY_NOTPAY)
|
||||
|
@@ -1,11 +1,14 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.param;
|
||||
package cn.daxpay.single.service.core.payment.adjust.param;
|
||||
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付订单修复参数
|
||||
* @author xxm
|
||||
@@ -13,14 +16,20 @@ import lombok.experimental.Accessors;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRepairParam {
|
||||
public class PayAdjustParam {
|
||||
|
||||
@Schema(description = "支付订单")
|
||||
private PayOrder order;
|
||||
|
||||
@Schema(description = "通道交易号")
|
||||
private String outTradeNo;
|
||||
|
||||
@Schema(description = "完成时间")
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
@Schema(description = "触发来源")
|
||||
private TradeAdjustSourceEnum source;
|
||||
|
||||
@Schema(description = "调整方式")
|
||||
private PayAdjustWayEnum adjustWay;
|
||||
|
||||
@Schema(description = "支付订单号")
|
||||
private String orderNo;
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.param;
|
||||
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 退款订单修复参数
|
||||
* @author xxm
|
||||
* @since 2023/12/27
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RefundAdjustParam {
|
||||
|
||||
@Schema(description = "退款订单")
|
||||
private RefundOrder order;
|
||||
|
||||
@Schema(description = "通道交易号")
|
||||
private String outTradeNo;
|
||||
|
||||
@Schema(description = "完成时间")
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
@Schema(description = "触发来源")
|
||||
private TradeAdjustSourceEnum source;
|
||||
|
||||
@Schema(description = "调整方式")
|
||||
private RefundAdjustWayEnum adjustWay;
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.service;
|
||||
package cn.daxpay.single.service.core.payment.adjust.service;
|
||||
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.exception.OperationProcessingException;
|
||||
@@ -6,11 +6,10 @@ import cn.daxpay.single.core.exception.SystemUnknownErrorException;
|
||||
import cn.daxpay.single.core.exception.TradeStatusErrorException;
|
||||
import cn.daxpay.single.core.util.TradeNoGenerateUtil;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.repair.param.PayRepairParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.PayAdjustParam;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.repair.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.core.record.repair.service.TradeAdjustRecordService;
|
||||
@@ -21,6 +20,7 @@ import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
@@ -45,7 +45,9 @@ public class PayAdjustService {
|
||||
/**
|
||||
* 调整服务
|
||||
*/
|
||||
public String adjust(PayOrder order, PayRepairParam param){
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String adjust(PayAdjustParam param){
|
||||
PayOrder order = param.getOrder();
|
||||
// 添加分布式锁
|
||||
LockInfo lock = lockTemplate.lock("repair:pay:" + order.getId(), 10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
@@ -67,7 +69,7 @@ public class PayAdjustService {
|
||||
// 根据不同的调整方式执行对应的修复逻辑
|
||||
switch (param.getAdjustWay()) {
|
||||
case SUCCESS:
|
||||
this.success(order);
|
||||
this.success(order, param);
|
||||
break;
|
||||
case CLOSE_LOCAL:
|
||||
this.closeLocal(order);
|
||||
@@ -83,7 +85,7 @@ public class PayAdjustService {
|
||||
// 发送通知
|
||||
clientNoticeService.registerPayNotice(order);
|
||||
TradeAdjustRecord record = this.saveRecord(order, param, beforeStatus);
|
||||
return record.getRepairNo();
|
||||
return record.getAdjustNo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,14 +93,11 @@ public class PayAdjustService {
|
||||
* 同步: 将异步支付状态修改为成功
|
||||
* 回调: 将异步支付状态修改为成功
|
||||
*/
|
||||
private void success(PayOrder order) {
|
||||
// 读取支付网关中的完成时间
|
||||
LocalDateTime payTime = PaymentContextLocal.get()
|
||||
.getRepairInfo()
|
||||
.getFinishTime();
|
||||
private void success(PayOrder order, PayAdjustParam param) {
|
||||
// 修改订单支付状态为成功
|
||||
order.setStatus(PayStatusEnum.SUCCESS.getCode())
|
||||
.setPayTime(payTime)
|
||||
.setPayTime(param.getFinishTime())
|
||||
.setOutOrderNo(param.getOutTradeNo())
|
||||
.setCloseTime(null);
|
||||
tradeFlowRecordService.savePay(order);
|
||||
payOrderService.updateById(order);
|
||||
@@ -129,10 +128,10 @@ public class PayAdjustService {
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
private TradeAdjustRecord saveRecord(PayOrder order, PayRepairParam param, String beforeStatus){
|
||||
private TradeAdjustRecord saveRecord(PayOrder order, PayAdjustParam param, String beforeStatus){
|
||||
// 修复后的状态
|
||||
TradeAdjustRecord record = new TradeAdjustRecord()
|
||||
.setRepairNo(TradeNoGenerateUtil.adjust())
|
||||
.setAdjustNo(TradeNoGenerateUtil.adjust())
|
||||
.setTradeId(order.getId())
|
||||
.setChannel(order.getChannel())
|
||||
.setSource(param.getSource().getCode())
|
@@ -0,0 +1,180 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.service;
|
||||
|
||||
import cn.daxpay.single.core.code.PayOrderRefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.core.exception.OperationProcessingException;
|
||||
import cn.daxpay.single.core.exception.TradeStatusErrorException;
|
||||
import cn.daxpay.single.core.util.TradeNoGenerateUtil;
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.RefundAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.repair.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.core.record.repair.service.TradeAdjustRecordService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 退款订单修复, 只有存在异步支付的退款订单才存在修复
|
||||
* @author xxm
|
||||
* @since 2024/1/26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RefundAdjustService {
|
||||
|
||||
private final PayOrderService payOrderService;
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
|
||||
private final TradeAdjustRecordService tradeAdjustRecordService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
/**
|
||||
* 调整退款单
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String adjust(RefundAdjustParam param){
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
RefundAdjustWayEnum repairType = param.getAdjustWay();
|
||||
// 添加分布式锁
|
||||
LockInfo lock = lockTemplate.lock("repair:refund:" + refundOrder.getId(), 10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
log.warn("当前退款订单正在调整中: {}", refundOrder.getId());
|
||||
throw new OperationProcessingException("当前退款订单正在调整中");
|
||||
}
|
||||
// 如果到达终态不能向前回滚
|
||||
if (Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode()).contains(refundOrder.getStatus())){
|
||||
throw new TradeStatusErrorException("当前退款订单已处理完成");
|
||||
}
|
||||
try {
|
||||
// 获取关联支付单
|
||||
PayOrder payOrder = payOrderQueryService.findById(refundOrder.getOrderId()).orElseThrow(() -> new RuntimeException("支付单不存在"));
|
||||
String adjustNo = null;
|
||||
// 根据不同的类型执行对应的修复逻辑
|
||||
if (repairType == RefundAdjustWayEnum.SUCCESS) {
|
||||
adjustNo = this.success(param, payOrder);
|
||||
} else if (repairType == RefundAdjustWayEnum.FAIL) {
|
||||
adjustNo = this.close(param, payOrder);
|
||||
} else {
|
||||
log.error("走到了理论上讲不会走到的分支");
|
||||
}
|
||||
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
return adjustNo;
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款成功, 更新退款单和支付单
|
||||
*/
|
||||
private String success(RefundAdjustParam param, PayOrder payOrder) {
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
String beforeRefundStatus = refundOrder.getStatus();
|
||||
|
||||
// 订单相关状态
|
||||
PayOrderRefundStatusEnum afterPayRefundStatus;
|
||||
|
||||
// 判断订单全部退款还是部分退款
|
||||
if (Objects.equals(payOrder.getRefundableBalance(),0)){
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.REFUNDED;
|
||||
} else {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.PARTIAL_REFUND;
|
||||
}
|
||||
// 设置退款为完成状态和完成时间
|
||||
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
|
||||
.setFinishTime(param.getFinishTime());
|
||||
payOrder.setRefundStatus(afterPayRefundStatus.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
|
||||
// 记录流水
|
||||
tradeFlowRecordService.saveRefund(refundOrder);
|
||||
|
||||
// 发送通知
|
||||
List<String> list = Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode(), RefundStatusEnum.FAIL.getCode());
|
||||
if (list.contains(refundOrder.getStatus())){
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
// 保存调整记录
|
||||
TradeAdjustRecord adjustRecord = this.saveRecord(param, beforeRefundStatus);
|
||||
return adjustRecord.getAdjustNo();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款失败, 关闭退款单并将失败的退款金额归还回订单
|
||||
*/
|
||||
private String close(RefundAdjustParam param, PayOrder payOrder) {
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
String beforeRefundStatus = refundOrder.getStatus();
|
||||
|
||||
// 退款失败返还后的余额
|
||||
int payOrderAmount = refundOrder.getAmount() + payOrder.getRefundableBalance();
|
||||
// 退款失败返还后的余额+可退余额 == 订单金额 支付订单回退为为支付成功状态
|
||||
if (payOrderAmount == payOrder.getAmount()){
|
||||
payOrder.setStatus(PayStatusEnum.SUCCESS.getCode());
|
||||
} else {
|
||||
// 回归部分退款状态
|
||||
payOrder.setRefundStatus(PayOrderRefundStatusEnum.PARTIAL_REFUND.getCode());
|
||||
}
|
||||
|
||||
// 更新支付订单相关的可退款金额
|
||||
payOrder.setRefundableBalance(payOrderAmount);
|
||||
refundOrder.setStatus(RefundStatusEnum.CLOSE.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
TradeAdjustRecord adjustRecord = this.saveRecord(param, beforeRefundStatus);
|
||||
return adjustRecord.getAdjustNo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存退款订单的调整记录
|
||||
*/
|
||||
private TradeAdjustRecord saveRecord(RefundAdjustParam param, String beforeRefundStatus){
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
// 修复发起来源
|
||||
TradeAdjustRecord record = new TradeAdjustRecord()
|
||||
.setTradeId(refundOrder.getId())
|
||||
.setAdjustNo(TradeNoGenerateUtil.adjust())
|
||||
.setTradeNo(refundOrder.getRefundNo())
|
||||
.setChannel(refundOrder.getChannel())
|
||||
.setType(TradeTypeEnum.REFUND.getCode())
|
||||
.setBeforeStatus(beforeRefundStatus)
|
||||
.setAfterStatus(refundOrder.getStatus())
|
||||
.setSource(param.getSource().getCode())
|
||||
.setWay(param.getAdjustWay().getCode());
|
||||
tradeAdjustRecordService.saveRecord(record);
|
||||
return record;
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.strategy.pay;
|
||||
package cn.daxpay.single.service.core.payment.adjust.strategy.pay;
|
||||
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliPayConfig;
|
@@ -1,4 +1,4 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.strategy.pay;
|
||||
package cn.daxpay.single.service.core.payment.adjust.strategy.pay;
|
||||
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.service.func.AbsPayAdjustStrategy;
|
@@ -1,4 +1,4 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.strategy.pay;
|
||||
package cn.daxpay.single.service.core.payment.adjust.strategy.pay;
|
||||
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.service.core.channel.wechat.entity.WeChatPayConfig;
|
@@ -15,8 +15,8 @@ import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.PaySyncRecordService;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.TradeSyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsAllocationStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
@@ -47,7 +47,7 @@ public class AllocationSyncService {
|
||||
|
||||
private final AllocOrderDetailManager allocOrderDetailManager;
|
||||
|
||||
private final PaySyncRecordService paySyncRecordService;
|
||||
private final TradeSyncRecordService tradeSyncRecordService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
@@ -158,16 +158,16 @@ public class AllocationSyncService {
|
||||
* 保存同步记录
|
||||
*/
|
||||
private void saveRecord(AllocOrder order, AllocRemoteSyncResult syncResult, String errorCode, String errorMsg){
|
||||
PaySyncRecord paySyncRecord = new PaySyncRecord()
|
||||
TradeSyncRecord tradeSyncRecord = new TradeSyncRecord()
|
||||
.setBizTradeNo(order.getBizAllocNo())
|
||||
.setTradeNo(order.getAllocNo())
|
||||
.setOutTradeNo(order.getOutAllocNo())
|
||||
.setSyncType(TradeTypeEnum.ALLOCATION.getCode())
|
||||
.setType(TradeTypeEnum.ALLOCATION.getCode())
|
||||
.setChannel(order.getChannel())
|
||||
.setSyncInfo(syncResult.getSyncInfo())
|
||||
.setErrorCode(errorCode)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
paySyncRecordService.saveRecord(paySyncRecord);
|
||||
tradeSyncRecordService.saveRecord(tradeSyncRecord);
|
||||
}
|
||||
}
|
||||
|
@@ -2,14 +2,15 @@ package cn.daxpay.single.service.core.payment.callback.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.payment.repair.result.PayRepairResult;
|
||||
import cn.daxpay.single.service.core.payment.repair.service.PayRepairService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.PayAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.PayAdjustService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -32,7 +33,7 @@ public class PayCallbackService {
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final PayRepairService payRepairService;
|
||||
private final PayAdjustService payAdjustService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
@@ -93,11 +94,15 @@ public class PayCallbackService {
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.EXCEPTION).setErrorMsg("支付单不是待支付状态,记录回调记录");
|
||||
return;
|
||||
}
|
||||
// 设置支付成功时间
|
||||
PaymentContextLocal.get().getRepairInfo().setFinishTime(callbackInfo.getFinishTime());
|
||||
// 执行支付完成修复逻辑
|
||||
PayRepairResult repair = payRepairService.repair(payOrder, PayAdjustWayEnum.SUCCESS);
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
// 执行支付成功的调整逻辑
|
||||
PayAdjustParam param = new PayAdjustParam()
|
||||
.setOrder(payOrder)
|
||||
.setOutTradeNo(callbackInfo.getOutTradeNo())
|
||||
.setAdjustWay(PayAdjustWayEnum.SUCCESS)
|
||||
.setSource(TradeAdjustSourceEnum.CALLBACK)
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
String adjustNo = payAdjustService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,9 +120,15 @@ public class PayCallbackService {
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.EXCEPTION).setErrorMsg("支付单状态非法,支付网关状态为失败,但支付单状态为已完成");
|
||||
return;
|
||||
}
|
||||
// 执行支付关闭修复逻辑
|
||||
PayRepairResult repair = payRepairService.repair(payOrder, PayAdjustWayEnum.CLOSE_LOCAL);
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
// 执行支付关闭的调整逻辑
|
||||
PayAdjustParam param = new PayAdjustParam()
|
||||
.setOrder(payOrder)
|
||||
.setOutTradeNo(callbackInfo.getOutTradeNo())
|
||||
.setAdjustWay(PayAdjustWayEnum.CLOSE_LOCAL)
|
||||
.setSource(TradeAdjustSourceEnum.CALLBACK)
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
String adjustNo = payAdjustService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,13 +2,14 @@ package cn.daxpay.single.service.core.payment.callback.service;
|
||||
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.RefundRepairWayEnum;
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.payment.repair.result.RefundRepairResult;
|
||||
import cn.daxpay.single.service.core.payment.repair.service.RefundRepairService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.RefundAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.RefundAdjustService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -28,7 +29,7 @@ import java.util.Objects;
|
||||
public class RefundCallbackService {
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final RefundRepairService reflectionService;
|
||||
private final RefundAdjustService reflectionService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
@@ -60,13 +61,19 @@ public class RefundCallbackService {
|
||||
}
|
||||
|
||||
// 退款成功还是失败
|
||||
RefundAdjustParam param = new RefundAdjustParam()
|
||||
.setOrder(refundOrder)
|
||||
.setOutTradeNo(callbackInfo.getOutTradeNo())
|
||||
.setSource(TradeAdjustSourceEnum.CALLBACK)
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
if (Objects.equals(RefundStatusEnum.SUCCESS.getCode(), callbackInfo.getOutStatus())) {
|
||||
PaymentContextLocal.get().getRepairInfo().setFinishTime(callbackInfo.getFinishTime());
|
||||
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.REFUND_SUCCESS);
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
param.setAdjustWay(RefundAdjustWayEnum.SUCCESS);
|
||||
String adjustNo = reflectionService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
} else {
|
||||
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.REFUND_FAIL);
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
param.setAdjustWay(RefundAdjustWayEnum.FAIL);
|
||||
String adjustNo = reflectionService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
@@ -1,16 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.result;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付修复结果
|
||||
* @author xxm
|
||||
* @since 2024/1/4
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRepairResult {
|
||||
/** 修复号 */
|
||||
private String repairNo;
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.result;
|
||||
|
||||
import cn.daxpay.single.core.code.PayOrderRefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 退款修复结果
|
||||
* @author xxm
|
||||
* @since 2024/1/26
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RefundRepairResult {
|
||||
|
||||
/** 修复号 */
|
||||
private String repairNo;
|
||||
/** 退款修复前状态 */
|
||||
private RefundStatusEnum beforeRefundStatus;
|
||||
/** 退款修复后状态 */
|
||||
private RefundStatusEnum afterRefundStatus;
|
||||
/** 支付修复前状态 */
|
||||
private PayOrderRefundStatusEnum beforePayStatus;
|
||||
/** 支付修复后状态 */
|
||||
private PayOrderRefundStatusEnum afterPayStatus;
|
||||
}
|
@@ -1,125 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.service;
|
||||
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.exception.SystemUnknownErrorException;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.repair.result.PayRepairResult;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.repair.service.PayRepairRecordService;
|
||||
import cn.daxpay.single.service.func.AbsPayAdjustStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 支付修复服务
|
||||
* @author xxm
|
||||
* @since 2023/12/27
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayRepairService {
|
||||
|
||||
private final PayOrderService payOrderService;
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final PayRepairRecordService recordService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
|
||||
/**
|
||||
* 修复支付单
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PayRepairResult repair(PayOrder order, PayAdjustWayEnum repairType){
|
||||
// 添加分布式锁
|
||||
LockInfo lock = lockTemplate.lock("repair:pay:" + order.getId(), 10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
log.warn("当前支付定单正在修复中: {}", order.getId());
|
||||
return new PayRepairResult();
|
||||
}
|
||||
|
||||
// 2.1 初始化修复参数
|
||||
AbsPayAdjustStrategy repairStrategy = PayStrategyFactory.create(order.getChannel(), AbsPayAdjustStrategy.class);
|
||||
repairStrategy.setOrder(order);
|
||||
// 2.2 执行前置处理
|
||||
repairStrategy.doBeforeHandler();
|
||||
|
||||
// 3. 根据不同的类型执行对应的修复逻辑
|
||||
switch (repairType) {
|
||||
case SUCCESS:
|
||||
this.success(order);
|
||||
break;
|
||||
case CLOSE_LOCAL:
|
||||
this.closeLocal(order);
|
||||
break;
|
||||
case CLOSE_GATEWAY:
|
||||
this.closeRemote(order, repairStrategy);
|
||||
break;
|
||||
default:
|
||||
log.error("走到了理论上讲不会走到的分支");
|
||||
throw new SystemUnknownErrorException("走到了理论上讲不会走到的分支");
|
||||
}
|
||||
// 设置修复iD
|
||||
// 发送通知
|
||||
clientNoticeService.registerPayNotice(order);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 变更为已支付
|
||||
* 同步: 将异步支付状态修改为成功
|
||||
* 回调: 将异步支付状态修改为成功
|
||||
*/
|
||||
private void success(PayOrder order) {
|
||||
// 读取支付网关中的完成时间
|
||||
LocalDateTime payTime = PaymentContextLocal.get()
|
||||
.getRepairInfo()
|
||||
.getFinishTime();
|
||||
// 修改订单支付状态为成功
|
||||
order.setStatus(PayStatusEnum.SUCCESS.getCode())
|
||||
.setPayTime(payTime)
|
||||
.setCloseTime(null);
|
||||
tradeFlowRecordService.savePay(order);
|
||||
payOrderService.updateById(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭支付
|
||||
* 同步/对账: 执行支付单所有的支付通道关闭支付逻辑, 不需要调用网关关闭,
|
||||
*/
|
||||
private void closeLocal(PayOrder order) {
|
||||
// 执行策略的关闭方法
|
||||
order.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
// TODO 尝试是否可以使用网关返回的时间
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(order);
|
||||
}
|
||||
/**
|
||||
* 关闭网关交易, 同时也会关闭本地支付
|
||||
* 回调: 执行所有的支付通道关闭支付逻辑
|
||||
*/
|
||||
private void closeRemote(PayOrder payOrder, AbsPayAdjustStrategy strategy) {
|
||||
// 执行策略的关闭方法
|
||||
strategy.doCloseRemoteHandler();
|
||||
payOrder.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
// TODO 尝试是否可以使用网关返回的时间
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(payOrder);
|
||||
}
|
||||
}
|
@@ -1,223 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.repair.service;
|
||||
|
||||
import cn.daxpay.single.core.code.PayOrderRefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.code.RefundRepairWayEnum;
|
||||
import cn.daxpay.single.service.common.context.AdjustLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.repair.result.RefundRepairResult;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
|
||||
import cn.daxpay.single.service.core.record.repair.service.PayRepairRecordService;
|
||||
import cn.daxpay.single.core.util.TradeNoGenerateUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 退款订单修复, 只有存在异步支付的退款订单才存在修复
|
||||
* @author xxm
|
||||
* @since 2024/1/26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RefundRepairService {
|
||||
|
||||
private final PayOrderService payOrderService;
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final PayRepairRecordService recordService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
|
||||
/**
|
||||
* 修复退款单
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public RefundRepairResult repair(RefundOrder refundOrder, RefundRepairWayEnum repairType){
|
||||
// 添加分布式锁
|
||||
LockInfo lock = lockTemplate.lock("repair:refund:" + refundOrder.getId(), 10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
log.warn("当前退款单正在修复中: {}", refundOrder.getId());
|
||||
return new RefundRepairResult();
|
||||
}
|
||||
try {
|
||||
// 获取关联支付单
|
||||
PayOrder payOrder = payOrderQueryService.findById(refundOrder.getOrderId())
|
||||
.orElseThrow(() -> new RuntimeException("支付单不存在"));
|
||||
|
||||
// 根据不同的类型执行对应的修复逻辑
|
||||
RefundRepairResult repairResult = new RefundRepairResult();
|
||||
if (Objects.requireNonNull(repairType) == RefundRepairWayEnum.REFUND_SUCCESS) {
|
||||
repairResult = this.success(refundOrder, payOrder);
|
||||
} else if (repairType == RefundRepairWayEnum.REFUND_FAIL) {
|
||||
repairResult = this.close(refundOrder, payOrder);
|
||||
} else {
|
||||
log.error("走到了理论上讲不会走到的分支");
|
||||
}
|
||||
|
||||
// 设置修复ID并保存修复记录
|
||||
repairResult.setRepairNo(TradeNoGenerateUtil.adjust());
|
||||
// 支付修复记录
|
||||
PayRepairRecord payRepairRecord = this.payRepairRecord(payOrder, repairType, repairResult);
|
||||
// 退款修复记录
|
||||
PayRepairRecord refundRepairRecord = this.refundRepairRecord(refundOrder, repairType, repairResult);
|
||||
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
recordService.saveAllRecord(Arrays.asList(payRepairRecord, refundRepairRecord));
|
||||
return repairResult;
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款成功, 更新退款单和支付单
|
||||
*/
|
||||
private RefundRepairResult success(RefundOrder refundOrder, PayOrder payOrder) {
|
||||
AdjustLocal repairInfo = PaymentContextLocal.get().getRepairInfo();
|
||||
// 订单相关状态
|
||||
PayOrderRefundStatusEnum beforePayStatus = PayOrderRefundStatusEnum.findByCode(payOrder.getRefundStatus());
|
||||
PayOrderRefundStatusEnum afterPayRefundStatus;
|
||||
RefundStatusEnum beforeRefundStatus = RefundStatusEnum.findByCode(refundOrder.getStatus());
|
||||
|
||||
// 判断订单全部退款还是部分退款
|
||||
if (Objects.equals(payOrder.getRefundableBalance(),0)){
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.REFUNDED;
|
||||
} else {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.PARTIAL_REFUND;
|
||||
}
|
||||
// 设置退款为完成状态和完成时间
|
||||
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
|
||||
.setFinishTime(repairInfo.getFinishTime());
|
||||
payOrder.setRefundStatus(afterPayRefundStatus.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
|
||||
// 记录流水
|
||||
tradeFlowRecordService.saveRefund(refundOrder);
|
||||
|
||||
// 发送通知
|
||||
List<String> list = Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode(), RefundStatusEnum.FAIL.getCode());
|
||||
if (list.contains(refundOrder.getStatus())){
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
|
||||
return new RefundRepairResult()
|
||||
.setBeforePayStatus(beforePayStatus)
|
||||
.setAfterPayStatus(afterPayRefundStatus)
|
||||
.setBeforeRefundStatus(beforeRefundStatus)
|
||||
.setAfterRefundStatus(RefundStatusEnum.SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款失败, 关闭退款单并将失败的退款金额归还回订单
|
||||
*/
|
||||
private RefundRepairResult close(RefundOrder refundOrder, PayOrder payOrder) {
|
||||
// 要返回的状态
|
||||
RefundRepairResult repairResult = new RefundRepairResult();
|
||||
|
||||
// 订单修复前状态
|
||||
PayOrderRefundStatusEnum beforePayStatus = PayOrderRefundStatusEnum.findByCode(payOrder.getRefundStatus());
|
||||
RefundStatusEnum beforeRefundStatus = RefundStatusEnum.findByCode(refundOrder.getStatus());
|
||||
repairResult.setBeforePayStatus(beforePayStatus)
|
||||
.setBeforeRefundStatus(beforeRefundStatus);
|
||||
|
||||
// 退款失败返还后的余额
|
||||
int payOrderAmount = refundOrder.getAmount() + payOrder.getRefundableBalance();
|
||||
// 退款失败返还后的余额+可退余额 == 订单金额 支付订单回退为为支付成功状态
|
||||
if (payOrderAmount == payOrder.getAmount()){
|
||||
payOrder.setStatus(PayStatusEnum.SUCCESS.getCode());
|
||||
repairResult.setAfterPayStatus(PayOrderRefundStatusEnum.NO_REFUND);
|
||||
} else {
|
||||
// 回归部分退款状态
|
||||
payOrder.setRefundStatus(PayOrderRefundStatusEnum.PARTIAL_REFUND.getCode());
|
||||
repairResult.setAfterPayStatus(PayOrderRefundStatusEnum.PARTIAL_REFUND);
|
||||
}
|
||||
|
||||
// 更新支付订单相关的可退款金额
|
||||
payOrder.setRefundableBalance(payOrderAmount);
|
||||
refundOrder.setStatus(RefundStatusEnum.CLOSE.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
return repairResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付订单的修复记录
|
||||
* 支付完成 -> 退款
|
||||
* 退款 -> 全部退款
|
||||
* @param repairType 支付订单修复方式状态编码跟退款修复的状态一致,
|
||||
*/
|
||||
private PayRepairRecord payRepairRecord(PayOrder order, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
|
||||
// 修复前的状态
|
||||
String beforeStatus = Optional.ofNullable(repairResult.getBeforePayStatus())
|
||||
.map(PayOrderRefundStatusEnum::getCode).orElse(null);
|
||||
// 修复发起来源
|
||||
String source = PaymentContextLocal.get()
|
||||
.getRepairInfo()
|
||||
.getSource().getCode();
|
||||
return new PayRepairRecord()
|
||||
.setTradeId(order.getId())
|
||||
.setTradeNo(order.getOrderNo())
|
||||
.setRepairNo(repairResult.getRepairNo())
|
||||
.setRepairType(TradeTypeEnum.PAY.getCode())
|
||||
.setRepairSource(source)
|
||||
.setRepairWay(repairType.getCode())
|
||||
.setChannel(order.getChannel())
|
||||
.setBeforeStatus(beforeStatus)
|
||||
.setAfterStatus(repairResult.getAfterPayStatus().getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款订单的修复记录
|
||||
* 退款中 -> 退款成功
|
||||
*/
|
||||
private PayRepairRecord refundRepairRecord(RefundOrder refundOrder, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
|
||||
// 修复后的状态
|
||||
String afterStatus = Optional.ofNullable(repairResult.getAfterRefundStatus()).map(RefundStatusEnum::getCode).orElse(null);
|
||||
// 修复发起来源
|
||||
String source = PaymentContextLocal.get()
|
||||
.getRepairInfo()
|
||||
.getSource().getCode();
|
||||
return new PayRepairRecord()
|
||||
.setTradeId(refundOrder.getId())
|
||||
.setRepairNo(repairResult.getRepairNo())
|
||||
.setTradeNo(refundOrder.getRefundNo())
|
||||
.setChannel(refundOrder.getChannel())
|
||||
.setRepairType(TradeTypeEnum.REFUND.getCode())
|
||||
.setBeforeStatus(repairResult.getBeforeRefundStatus().getCode())
|
||||
.setAfterStatus(afterStatus)
|
||||
.setRepairSource(source)
|
||||
.setRepairWay(repairType.getCode());
|
||||
}
|
||||
}
|
@@ -29,8 +29,8 @@ public class PayRemoteSyncResult {
|
||||
*/
|
||||
private String outOrderNo;
|
||||
|
||||
/** 支付完成时间(通常用于接收异步支付返回的时间) */
|
||||
private LocalDateTime payTime;
|
||||
/** 支付完成时间 */
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
/** 同步时网关返回的对象, 序列化为json字符串 */
|
||||
private String syncInfo;
|
||||
|
@@ -27,7 +27,7 @@ public class RefundRemoteSyncResult {
|
||||
private String syncInfo;
|
||||
|
||||
/**
|
||||
* 外部三方支付网关生成的退款交易, 用与将记录关联起来
|
||||
* 外部三方支付网关生成的退款交易号, 用与将记录关联起来
|
||||
*/
|
||||
private String outRefundNo;
|
||||
|
||||
|
@@ -9,21 +9,21 @@ import cn.daxpay.single.core.code.PaySyncStatusEnum;
|
||||
import cn.daxpay.single.core.exception.*;
|
||||
import cn.daxpay.single.core.param.payment.pay.PaySyncParam;
|
||||
import cn.daxpay.single.core.result.sync.PaySyncResult;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.context.AdjustLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.payment.repair.result.PayRepairResult;
|
||||
import cn.daxpay.single.service.core.payment.repair.service.PayRepairService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.PayAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.PayAdjustService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.PayRemoteSyncResult;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.PaySyncRecordService;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.TradeSyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsPaySyncStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -52,9 +52,9 @@ public class PaySyncService {
|
||||
|
||||
private final PayOrderService payOrderService;
|
||||
|
||||
private final PaySyncRecordService paySyncRecordService;
|
||||
private final TradeSyncRecordService tradeSyncRecordService;
|
||||
|
||||
private final PayRepairService repairService;
|
||||
private final PayAdjustService payAdjustService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
@@ -93,9 +93,9 @@ public class PaySyncService {
|
||||
// 执行操作, 获取支付网关同步的结果
|
||||
PayRemoteSyncResult payRemoteSyncResult = syncPayStrategy.doSyncStatus();
|
||||
// 判断是否同步成功
|
||||
if (Objects.equals(payRemoteSyncResult.getSyncStatus(), PaySyncStatusEnum.FAIL)){
|
||||
if (Objects.equals(payRemoteSyncResult.getSyncStatus(), FAIL)){
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, false, null, payRemoteSyncResult.getErrorMsg());
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, null);
|
||||
throw new OperationFailException(payRemoteSyncResult.getErrorMsg());
|
||||
}
|
||||
// 支付订单的网关订单号是否一致, 不一致进行更新
|
||||
@@ -105,28 +105,20 @@ public class PaySyncService {
|
||||
}
|
||||
// 判断网关状态是否和支付单一致, 同时特定情况下更新网关同步状态
|
||||
boolean statusSync = this.checkAndAdjustSyncStatus(payRemoteSyncResult,payOrder);
|
||||
PayRepairResult repairResult = new PayRepairResult();
|
||||
String adjustNo = null;
|
||||
try {
|
||||
// 状态不一致,执行支付单修复逻辑
|
||||
if (!statusSync){
|
||||
// 如果没有修复触发来源, 设置修复触发来源为同步
|
||||
AdjustLocal repairInfo = PaymentContextLocal.get().getRepairInfo();
|
||||
if (Objects.isNull(repairInfo.getSource())){
|
||||
repairInfo.setSource(TradeAdjustSourceEnum.SYNC);
|
||||
}
|
||||
// 设置支付单完成时间
|
||||
repairInfo.setFinishTime(payRemoteSyncResult.getPayTime());
|
||||
repairResult = this.repairHandler(payRemoteSyncResult, payOrder);
|
||||
adjustNo = this.repairHandler(payRemoteSyncResult, payOrder);
|
||||
}
|
||||
} catch (PayFailureException e) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
payRemoteSyncResult.setSyncStatus(PaySyncStatusEnum.FAIL);
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, false, null, e.getMessage());
|
||||
payRemoteSyncResult.setSyncStatus(FAIL);
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, null);
|
||||
throw e;
|
||||
}
|
||||
|
||||
// 同步成功记录日志
|
||||
this.saveRecord( payOrder, payRemoteSyncResult, !statusSync, repairResult.getRepairNo(), null);
|
||||
this.saveRecord( payOrder, payRemoteSyncResult, adjustNo);
|
||||
return new PaySyncResult().setStatus(payRemoteSyncResult.getSyncStatus().getCode());
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
@@ -153,7 +145,7 @@ public class PaySyncService {
|
||||
// 判断支付单是否支付超时, 如果待支付状态下触发超时
|
||||
if (LocalDateTimeUtil.le(order.getExpiredTime(), LocalDateTime.now())){
|
||||
// 将支付单同步状态状态调整为支付超时, 进行订单的关闭
|
||||
payRemoteSyncResult.setSyncStatus(PaySyncStatusEnum.TIMEOUT);
|
||||
payRemoteSyncResult.setSyncStatus(TIMEOUT);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -171,7 +163,7 @@ public class PaySyncService {
|
||||
|
||||
// 退款状态不做额外处理, 需要通过退款接口进行处理
|
||||
if (!Objects.equals(order.getRefundStatus(),PayOrderRefundStatusEnum.NO_REFUND.getCode())
|
||||
|| syncStatus.equals(PaySyncStatusEnum.REFUND)){
|
||||
|| syncStatus.equals(REFUND)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -179,30 +171,34 @@ public class PaySyncService {
|
||||
|
||||
/**
|
||||
* 根据同步的结果对支付单进行修复处理
|
||||
* @return 调整单号, 如果为空, 说明订单未做调整
|
||||
*/
|
||||
private PayRepairResult repairHandler(PayRemoteSyncResult payRemoteSyncResult, PayOrder payOrder){
|
||||
private String repairHandler(PayRemoteSyncResult payRemoteSyncResult, PayOrder payOrder){
|
||||
PaySyncStatusEnum syncStatusEnum = payRemoteSyncResult.getSyncStatus();
|
||||
PayRepairResult repair = new PayRepairResult();
|
||||
PayAdjustParam param = new PayAdjustParam()
|
||||
.setOrder(payOrder)
|
||||
.setSource(TradeAdjustSourceEnum.SYNC)
|
||||
.setFinishTime(payRemoteSyncResult.getFinishTime());
|
||||
// 对支付网关同步的结果进行处理
|
||||
switch (syncStatusEnum) {
|
||||
// 支付成功 支付宝退款时也是支付成功状态, 除非支付完成
|
||||
case SUCCESS: {
|
||||
repair = repairService.repair(payOrder, PayAdjustWayEnum.SUCCESS);
|
||||
break;
|
||||
param.setAdjustWay(PayAdjustWayEnum.SUCCESS);
|
||||
return payAdjustService.adjust(param);
|
||||
}
|
||||
case REFUND:
|
||||
throw new TradeStatusErrorException("支付订单为退款状态,请通过执行对应的退款订单进行同步,来更新具体为什么类型退款状态");
|
||||
// 交易关闭和未找到, 都对本地支付订单进行关闭, 不需要再调用网关进行关闭
|
||||
case CLOSED:
|
||||
case NOT_FOUND: {
|
||||
repair = repairService.repair(payOrder, PayAdjustWayEnum.CLOSE_LOCAL);
|
||||
break;
|
||||
param.setAdjustWay(PayAdjustWayEnum.CLOSE_LOCAL);
|
||||
return payAdjustService.adjust(param);
|
||||
}
|
||||
// 超时关闭和交易不存在(特殊) 关闭本地支付订单, 同时调用网关进行关闭, 确保后续这个订单不能被支付
|
||||
case TIMEOUT:
|
||||
case NOT_FOUND_UNKNOWN:{
|
||||
repair = repairService.repair(payOrder, PayAdjustWayEnum.CLOSE_GATEWAY);
|
||||
break;
|
||||
param.setAdjustWay(PayAdjustWayEnum.CLOSE_GATEWAY);
|
||||
return payAdjustService.adjust(param);
|
||||
}
|
||||
// 调用出错
|
||||
case FAIL: {
|
||||
@@ -214,7 +210,7 @@ public class PaySyncService {
|
||||
throw new SystemUnknownErrorException("代码有问题");
|
||||
}
|
||||
}
|
||||
return repair;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,24 +218,23 @@ public class PaySyncService {
|
||||
* 保存同步记录
|
||||
* @param payOrder 支付单
|
||||
* @param payRemoteSyncResult 同步结果
|
||||
* @param repair 是否修复
|
||||
* @param repairOrderNo 修复号
|
||||
* @param errorMsg 错误信息
|
||||
*/
|
||||
private void saveRecord(PayOrder payOrder, PayRemoteSyncResult payRemoteSyncResult, boolean repair, String repairOrderNo, String errorMsg){
|
||||
PaySyncRecord paySyncRecord = new PaySyncRecord()
|
||||
private void saveRecord(PayOrder payOrder, PayRemoteSyncResult payRemoteSyncResult, String repairOrderNo){
|
||||
TradeSyncRecord tradeSyncRecord = new TradeSyncRecord()
|
||||
.setBizTradeNo(payOrder.getBizOrderNo())
|
||||
.setTradeNo(payOrder.getOrderNo())
|
||||
.setOutTradeNo(payOrder.getOutOrderNo())
|
||||
.setOutTradeStatus(payRemoteSyncResult.getSyncStatus().getCode())
|
||||
.setSyncType(TradeTypeEnum.PAY.getCode())
|
||||
.setType(TradeTypeEnum.PAY.getCode())
|
||||
.setChannel(payOrder.getChannel())
|
||||
.setSyncInfo(payRemoteSyncResult.getSyncInfo())
|
||||
.setRepair(repair)
|
||||
.setRepairNo(repairOrderNo)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setAdjust(StrUtil.isNotBlank(repairOrderNo))
|
||||
.setAdjustNo(repairOrderNo)
|
||||
.setErrorCode(payRemoteSyncResult.getErrorCode())
|
||||
.setErrorMsg(payRemoteSyncResult.getErrorMsg())
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
paySyncRecordService.saveRecord(paySyncRecord);
|
||||
tradeSyncRecordService.saveRecord(tradeSyncRecord);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,21 +9,21 @@ import cn.daxpay.single.core.exception.PayFailureException;
|
||||
import cn.daxpay.single.core.exception.TradeNotExistException;
|
||||
import cn.daxpay.single.core.param.payment.refund.RefundSyncParam;
|
||||
import cn.daxpay.single.core.result.sync.RefundSyncResult;
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.code.RefundRepairWayEnum;
|
||||
import cn.daxpay.single.service.common.context.AdjustLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.order.refund.service.RefundOrderQueryService;
|
||||
import cn.daxpay.single.service.core.payment.repair.result.RefundRepairResult;
|
||||
import cn.daxpay.single.service.core.payment.repair.service.RefundRepairService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.RefundAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.RefundAdjustService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.RefundRemoteSyncResult;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.PaySyncRecordService;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.TradeSyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsRefundSyncStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -47,9 +47,9 @@ public class RefundSyncService {
|
||||
|
||||
private final RefundOrderQueryService refundOrderQueryService;
|
||||
|
||||
private final PaySyncRecordService paySyncRecordService;
|
||||
private final TradeSyncRecordService tradeSyncRecordService;
|
||||
|
||||
private final RefundRepairService repairService;
|
||||
private final RefundAdjustService repairService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
@@ -90,7 +90,7 @@ public class RefundSyncService {
|
||||
// 判断是否同步成功
|
||||
if (Objects.equals(refundRemoteSyncResult.getSyncStatus(), RefundSyncStatusEnum.FAIL)) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, false, null, refundRemoteSyncResult.getErrorMsg());
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, null);
|
||||
throw new OperationFailException(refundRemoteSyncResult.getErrorMsg());
|
||||
}
|
||||
// 订单的通道交易号是否一致, 不一致进行更新
|
||||
@@ -100,26 +100,21 @@ public class RefundSyncService {
|
||||
}
|
||||
// 判断网关状态是否和支付单一致
|
||||
boolean statusSync = this.checkSyncStatus(refundRemoteSyncResult, refundOrder);
|
||||
RefundRepairResult repairResult = new RefundRepairResult();
|
||||
String adjustNo = null;
|
||||
try {
|
||||
// 状态不一致,执行退款单修复逻辑
|
||||
if (!statusSync) {
|
||||
// 如果没有支付来源, 设置支付来源为同步
|
||||
AdjustLocal repairInfo = PaymentContextLocal.get().getRepairInfo();
|
||||
if (Objects.isNull(repairInfo.getSource())){
|
||||
repairInfo.setSource(TradeAdjustSourceEnum.SYNC);
|
||||
}
|
||||
repairInfo.setFinishTime(refundRemoteSyncResult.getFinishTime());
|
||||
repairResult = this.repairHandler(refundRemoteSyncResult, refundOrder);
|
||||
adjustNo = this.repairHandler(refundRemoteSyncResult, refundOrder);
|
||||
}
|
||||
} catch (PayFailureException e) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
refundRemoteSyncResult.setSyncStatus(RefundSyncStatusEnum.FAIL);
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, false, null, e.getMessage());
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, null);
|
||||
throw e;
|
||||
}
|
||||
// 同步成功记录日志
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, !statusSync, repairResult.getRepairNo(), null);
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, adjustNo);
|
||||
return new RefundSyncResult().setStatus(refundRemoteSyncResult.getSyncStatus().getCode());
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
@@ -155,55 +150,59 @@ public class RefundSyncService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 进行退款订单和支付订单的补偿
|
||||
* 进行退款订单和支付订单的调整
|
||||
*/
|
||||
private RefundRepairResult repairHandler(RefundRemoteSyncResult syncResult, RefundOrder order){
|
||||
private String repairHandler(RefundRemoteSyncResult syncResult, RefundOrder order){
|
||||
RefundSyncStatusEnum syncStatusEnum = syncResult.getSyncStatus();
|
||||
RefundRepairResult repair = new RefundRepairResult();
|
||||
RefundAdjustParam param = new RefundAdjustParam()
|
||||
.setOrder(order)
|
||||
.setOutTradeNo(syncResult.getOutRefundNo())
|
||||
.setSource(TradeAdjustSourceEnum.SYNC)
|
||||
.setFinishTime(syncResult.getFinishTime());
|
||||
|
||||
// 对支付网关同步的结果进行处理
|
||||
switch (syncStatusEnum) {
|
||||
case SUCCESS:
|
||||
repair = repairService.repair(order, RefundRepairWayEnum.REFUND_SUCCESS);
|
||||
break;
|
||||
param.setAdjustWay(RefundAdjustWayEnum.SUCCESS);
|
||||
return repairService.adjust(param);
|
||||
case PROGRESS:
|
||||
// 不进行处理
|
||||
break;
|
||||
case FAIL: {
|
||||
repair = repairService.repair(order, RefundRepairWayEnum.REFUND_FAIL);
|
||||
break;
|
||||
param.setAdjustWay(RefundAdjustWayEnum.FAIL);
|
||||
return repairService.adjust(param);
|
||||
}
|
||||
case NOT_FOUND:
|
||||
repair = repairService.repair(order, RefundRepairWayEnum.REFUND_FAIL);
|
||||
break;
|
||||
param.setAdjustWay(RefundAdjustWayEnum.FAIL);
|
||||
return repairService.adjust(param);
|
||||
default: {
|
||||
throw new BizException("代码有问题");
|
||||
}
|
||||
}
|
||||
return repair;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存同步记录, 使用新事务进行保存
|
||||
* @param refundOrder 支付单
|
||||
* @param syncResult 同步结果
|
||||
* @param repair 是否修复
|
||||
* @param repairOrderNo 修复号
|
||||
* @param errorMsg 错误信息
|
||||
*/
|
||||
private void saveRecord(RefundOrder refundOrder, RefundRemoteSyncResult syncResult, boolean repair, String repairOrderNo, String errorMsg){
|
||||
PaySyncRecord paySyncRecord = new PaySyncRecord()
|
||||
private void saveRecord(RefundOrder refundOrder, RefundRemoteSyncResult syncResult, String repairOrderNo){
|
||||
TradeSyncRecord tradeSyncRecord = new TradeSyncRecord()
|
||||
.setTradeNo(refundOrder.getRefundNo())
|
||||
.setBizTradeNo(refundOrder.getBizRefundNo())
|
||||
.setOutTradeNo(syncResult.getOutRefundNo())
|
||||
.setOutTradeStatus(syncResult.getSyncStatus().getCode())
|
||||
.setSyncType(TradeTypeEnum.REFUND.getCode())
|
||||
.setType(TradeTypeEnum.REFUND.getCode())
|
||||
.setChannel(refundOrder.getChannel())
|
||||
.setSyncInfo(syncResult.getSyncInfo())
|
||||
.setRepair(repair)
|
||||
.setRepairNo(repairOrderNo)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setAdjust(StrUtil.isNotBlank(repairOrderNo))
|
||||
.setAdjustNo(repairOrderNo)
|
||||
.setErrorCode(syncResult.getErrorCode())
|
||||
.setErrorMsg(syncResult.getErrorMsg())
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
paySyncRecordService.saveRecord(paySyncRecord);
|
||||
tradeSyncRecordService.saveRecord(tradeSyncRecord);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ public class PayCallbackRecordService {
|
||||
.setChannel(callbackInfo.getChannel())
|
||||
.setNotifyInfo(JSONUtil.toJsonStr(callbackInfo.getCallbackParam()))
|
||||
.setCallbackType(callbackInfo.getCallbackType().getCode())
|
||||
.setRepairOrderNo(callbackInfo.getRepairNo())
|
||||
.setRepairOrderNo(callbackInfo.getAdjustNo())
|
||||
.setStatus(callbackInfo.getCallbackStatus().getCode())
|
||||
.setErrorMsg(callbackInfo.getErrorMsg());
|
||||
callbackRecordManager.save(payNotifyRecord);
|
||||
|
@@ -1,18 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.repair.convert;
|
||||
|
||||
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
|
||||
import cn.daxpay.single.service.dto.record.repair.PayRepairRecordDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/1/6
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayRepairRecordConvert {
|
||||
PayRepairRecordConvert CONVERT = Mappers.getMapper(PayRepairRecordConvert.class);
|
||||
|
||||
PayRepairRecordDto convert(PayRepairRecord in);
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.repair.dao;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
|
||||
import cn.daxpay.single.service.param.record.PayRepairRecordQuery;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/1/6
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class PayRepairRecordManager extends BaseManager<PayRepairRecordMapper, PayRepairRecord> {
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<PayRepairRecord> page(PageParam pageParam, PayRepairRecordQuery query){
|
||||
Page<PayRepairRecord> mpPage = MpUtil.getMpPage(pageParam, PayRepairRecord.class);
|
||||
QueryWrapper<PayRepairRecord> generator = QueryGenerator.generator(query);
|
||||
return page(mpPage, generator);
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.repair.dao;
|
||||
|
||||
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/1/6
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayRepairRecordMapper extends BaseMapper<PayRepairRecord> {
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.repair.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.annotation.DbTable;
|
||||
import cn.bootx.table.modify.mysql.annotation.DbMySqlIndex;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.code.RefundRepairWayEnum;
|
||||
import cn.daxpay.single.service.core.record.repair.convert.PayRepairRecordConvert;
|
||||
import cn.daxpay.single.service.dto.record.repair.PayRepairRecordDto;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 调整
|
||||
* 支付修复记录 包括支付修复记录和退款修复记录
|
||||
* @author xxm
|
||||
* @since 2024/1/6
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("pay_repair_record")
|
||||
@DbTable(comment = "支付修复记录")
|
||||
public class PayRepairRecord extends MpCreateEntity implements EntityBaseFunction<PayRepairRecordDto> {
|
||||
|
||||
/**
|
||||
* 修复号
|
||||
* 如果一次修复产生的修复记录有多个记录, 使用这个作为关联
|
||||
*/
|
||||
@DbColumn(comment = "修复号", length = 32, isNull = false)
|
||||
private String repairNo;
|
||||
|
||||
/** 支付ID/退款ID */
|
||||
@DbColumn(comment = "本地订单ID", isNull = false)
|
||||
private Long tradeId;
|
||||
|
||||
/**
|
||||
* 本地交易号, 支付号/退款号
|
||||
*/
|
||||
@DbMySqlIndex(comment = "本地交易号索引")
|
||||
@DbColumn(comment = "本地交易号", length = 32, isNull = false)
|
||||
private String tradeNo;
|
||||
|
||||
/**
|
||||
* 修复类型 支付修复/退款修复
|
||||
* @see TradeTypeEnum
|
||||
*/
|
||||
@DbColumn(comment = "修复类型", length = 20, isNull = false)
|
||||
private String repairType;
|
||||
|
||||
/**
|
||||
* 修复来源
|
||||
* @see TradeAdjustSourceEnum
|
||||
*/
|
||||
@DbColumn(comment = "修复来源", length = 20, isNull = false)
|
||||
private String repairSource;
|
||||
|
||||
/**
|
||||
* 修复方式
|
||||
* @see PayAdjustWayEnum
|
||||
* @see RefundRepairWayEnum
|
||||
*/
|
||||
@DbColumn(comment = "修复方式", length = 20, isNull = false)
|
||||
private String repairWay;
|
||||
|
||||
/** 修复的通道 */
|
||||
@DbColumn(comment = "修复的通道", length = 20, isNull = false)
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 修复前状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "修复前状态", length = 20, isNull = false)
|
||||
private String beforeStatus;
|
||||
|
||||
/**
|
||||
* 修复后状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "修复后状态", length = 20, isNull = false)
|
||||
private String afterStatus;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
@Override
|
||||
public PayRepairRecordDto toDto() {
|
||||
return PayRepairRecordConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -26,10 +26,9 @@ public class TradeAdjustRecord extends MpCreateEntity implements EntityBaseFunct
|
||||
|
||||
/**
|
||||
* 调整号
|
||||
* 如果记录有多个, 使用这个作为关联
|
||||
*/
|
||||
@DbColumn(comment = "修复号", length = 32, isNull = false)
|
||||
private String repairNo;
|
||||
@DbColumn(comment = "调整号", length = 32, isNull = false)
|
||||
private String adjustNo;
|
||||
|
||||
/** 交易ID */
|
||||
@DbColumn(comment = "本地订单ID", isNull = false)
|
||||
|
@@ -1,58 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.repair.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.rest.PageResult;
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.daxpay.single.service.core.record.repair.dao.PayRepairRecordManager;
|
||||
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
|
||||
import cn.daxpay.single.service.dto.record.repair.PayRepairRecordDto;
|
||||
import cn.daxpay.single.service.param.record.PayRepairRecordQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/1/6
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayRepairRecordService {
|
||||
private final PayRepairRecordManager repairRecordManager;
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*/
|
||||
public PayRepairRecordDto findById(Long id) {
|
||||
return repairRecordManager.findById(id).map(PayRepairRecord::toDto).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<PayRepairRecordDto> page(PageParam pageParam, PayRepairRecordQuery param){
|
||||
return MpUtil.convert2DtoPageResult(repairRecordManager.page(pageParam,param));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public void saveRecord(PayRepairRecord record){
|
||||
repairRecordManager.save(record);
|
||||
}
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public void saveAllRecord(List<PayRepairRecord> records){
|
||||
repairRecordManager.saveAll(records);
|
||||
}
|
||||
}
|
@@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 交易调整记录
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
|
@@ -1,19 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.sync.convert;
|
||||
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.dto.record.sync.PaySyncRecordDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 支付同步记录同步
|
||||
* @author xxm
|
||||
* @since 2023/7/14
|
||||
*/
|
||||
@Mapper
|
||||
public interface PaySyncRecordConvert {
|
||||
PaySyncRecordConvert CONVERT = Mappers.getMapper(PaySyncRecordConvert.class);
|
||||
|
||||
PaySyncRecordDto convert(PaySyncRecord in);
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package cn.daxpay.single.service.core.record.sync.convert;
|
||||
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.dto.record.sync.SyncRecordDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 支付同步记录同步
|
||||
* @author xxm
|
||||
* @since 2023/7/14
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeSyncRecordConvert {
|
||||
TradeSyncRecordConvert CONVERT = Mappers.getMapper(TradeSyncRecordConvert.class);
|
||||
|
||||
SyncRecordDto convert(TradeSyncRecord in);
|
||||
|
||||
}
|
@@ -4,8 +4,8 @@ import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.param.record.PaySyncRecordQuery;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.param.record.TradeSyncRecordQuery;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -20,14 +20,14 @@ import org.springframework.stereotype.Repository;
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class PaySyncRecordManager extends BaseManager<PaySyncRecordMapper, PaySyncRecord> {
|
||||
public class TradeSyncRecordManager extends BaseManager<TradeSyncRecordMapper, TradeSyncRecord> {
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<PaySyncRecord> page(PageParam pageParam, PaySyncRecordQuery query) {
|
||||
Page<PaySyncRecord> mpPage = MpUtil.getMpPage(pageParam, PaySyncRecord.class);
|
||||
QueryWrapper<PaySyncRecord> generator = QueryGenerator.generator(query);
|
||||
public Page<TradeSyncRecord> page(PageParam pageParam, TradeSyncRecordQuery query) {
|
||||
Page<TradeSyncRecord> mpPage = MpUtil.getMpPage(pageParam, TradeSyncRecord.class);
|
||||
QueryWrapper<TradeSyncRecord> generator = QueryGenerator.generator(query);
|
||||
return page(mpPage, generator);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package cn.daxpay.single.service.core.record.sync.dao;
|
||||
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
* @since 2023/7/14
|
||||
*/
|
||||
@Mapper
|
||||
public interface PaySyncRecordMapper extends BaseMapper<PaySyncRecord> {
|
||||
public interface TradeSyncRecordMapper extends BaseMapper<TradeSyncRecord> {
|
||||
}
|
@@ -11,24 +11,24 @@ import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.core.code.PaySyncStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundSyncStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.core.record.sync.convert.PaySyncRecordConvert;
|
||||
import cn.daxpay.single.service.dto.record.sync.PaySyncRecordDto;
|
||||
import cn.daxpay.single.service.core.record.sync.convert.TradeSyncRecordConvert;
|
||||
import cn.daxpay.single.service.dto.record.sync.SyncRecordDto;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付同步订单
|
||||
* 交易同步记录
|
||||
* @author xxm
|
||||
* @since 2023/7/14
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@DbTable(comment = "支付同步订单")
|
||||
@DbTable(comment = "交易同步记录")
|
||||
@Accessors(chain = true)
|
||||
@TableName("pay_sync_record")
|
||||
public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<PaySyncRecordDto> {
|
||||
@TableName("pay_trade_sync_record")
|
||||
public class TradeSyncRecord extends MpCreateEntity implements EntityBaseFunction<SyncRecordDto> {
|
||||
|
||||
/** 本地交易号 */
|
||||
@DbMySqlIndex(comment = "本地交易号索引")
|
||||
@@ -58,13 +58,13 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
|
||||
* @see TradeTypeEnum
|
||||
*/
|
||||
@DbColumn(comment = "同步类型", length = 20, isNull = false)
|
||||
private String syncType;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 同步的异步通道
|
||||
* 同步通道
|
||||
* @see PayChannelEnum#getCode()
|
||||
*/
|
||||
@DbColumn(comment = "同步的异步通道", length = 20, isNull = false)
|
||||
@DbColumn(comment = "同步通道", length = 20, isNull = false)
|
||||
private String channel;
|
||||
|
||||
/** 网关返回的同步消息 */
|
||||
@@ -73,14 +73,14 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
|
||||
private String syncInfo;
|
||||
|
||||
/**
|
||||
* 支付单如果状态不一致, 是否进行修复
|
||||
* 支付单如果状态不一致, 是否进行调整
|
||||
*/
|
||||
@DbColumn(comment = "是否进行修复", isNull = false)
|
||||
private boolean repair;
|
||||
@DbColumn(comment = "是否进行调整", isNull = false)
|
||||
private boolean adjust;
|
||||
|
||||
/** 修复单号 */
|
||||
@DbColumn(comment = "修复单号", length = 32)
|
||||
private String repairNo;
|
||||
@DbColumn(comment = "调整记录号", length = 32)
|
||||
private String adjustNo;
|
||||
|
||||
/** 错误码 */
|
||||
@DbColumn(comment = "错误码", length = 10)
|
||||
@@ -98,7 +98,7 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
|
||||
* 转换
|
||||
*/
|
||||
@Override
|
||||
public PaySyncRecordDto toDto() {
|
||||
return PaySyncRecordConvert.CONVERT.convert(this);
|
||||
public SyncRecordDto toDto() {
|
||||
return TradeSyncRecordConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -4,10 +4,10 @@ import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.rest.PageResult;
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.daxpay.single.service.core.record.sync.dao.PaySyncRecordManager;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.dto.record.sync.PaySyncRecordDto;
|
||||
import cn.daxpay.single.service.param.record.PaySyncRecordQuery;
|
||||
import cn.daxpay.single.service.core.record.sync.dao.TradeSyncRecordManager;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.dto.record.sync.SyncRecordDto;
|
||||
import cn.daxpay.single.service.param.record.TradeSyncRecordQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -23,30 +23,30 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PaySyncRecordService {
|
||||
private final PaySyncRecordManager orderManager;
|
||||
public class TradeSyncRecordService {
|
||||
private final TradeSyncRecordManager orderManager;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<PaySyncRecordDto> page(PageParam pageParam, PaySyncRecordQuery query) {
|
||||
Page<PaySyncRecord> page = orderManager.page(pageParam, query);
|
||||
public PageResult<SyncRecordDto> page(PageParam pageParam, TradeSyncRecordQuery query) {
|
||||
Page<TradeSyncRecord> page = orderManager.page(pageParam, query);
|
||||
return MpUtil.convert2DtoPageResult(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*/
|
||||
public PaySyncRecordDto findById(Long id) {
|
||||
return orderManager.findById(id).map(PaySyncRecord::toDto).orElseThrow(DataNotExistException::new);
|
||||
public SyncRecordDto findById(Long id) {
|
||||
return orderManager.findById(id).map(TradeSyncRecord::toDto).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录同步记录 同步支付单的不进行记录
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public void saveRecord(PaySyncRecord paySyncRecord){
|
||||
orderManager.save(paySyncRecord);
|
||||
public void saveRecord(TradeSyncRecord tradeSyncRecord){
|
||||
orderManager.save(tradeSyncRecord);
|
||||
}
|
||||
|
||||
}
|
@@ -1,81 +0,0 @@
|
||||
package cn.daxpay.single.service.dto.record.repair;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.dto.BaseDto;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.code.RefundRepairWayEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付修复记录
|
||||
* @author xxm
|
||||
* @since 2024/1/9
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付修复记录")
|
||||
public class PayRepairRecordDto extends BaseDto {
|
||||
|
||||
/**
|
||||
* 修复号
|
||||
* 如果一次修复产生的修复记录有多个记录, 使用这个作为关联
|
||||
*/
|
||||
@Schema(description = "修复号")
|
||||
private String repairNo;
|
||||
|
||||
/** 支付ID/退款ID */
|
||||
@Schema(description = "本地订单ID")
|
||||
private Long tradeId;
|
||||
|
||||
/**
|
||||
* 本地交易号, 支付号/退款号
|
||||
*/
|
||||
@Schema(description = "本地业务号")
|
||||
private String tradeNo;
|
||||
|
||||
/**
|
||||
* 修复方式
|
||||
* @see PayAdjustWayEnum
|
||||
* @see RefundRepairWayEnum
|
||||
*/
|
||||
@Schema(description = "修复方式")
|
||||
private String repairWay;
|
||||
|
||||
/**
|
||||
* 修复类型 支付修复/退款修复
|
||||
* @see TradeTypeEnum
|
||||
*/
|
||||
@Schema(description = "修复类型")
|
||||
private String repairType;
|
||||
|
||||
/**
|
||||
* 修复来源
|
||||
* @see TradeAdjustSourceEnum
|
||||
*/
|
||||
@Schema(description = "修复来源")
|
||||
private String repairSource;
|
||||
|
||||
/** 修复的异步通道 */
|
||||
@Schema(description = "修复的异步通道")
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 修复前状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@Schema(description = "修复前状态")
|
||||
private String beforeStatus;
|
||||
|
||||
/**
|
||||
* 修复后状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@Schema(description = "修复后状态")
|
||||
private String afterStatus;
|
||||
}
|
@@ -21,7 +21,7 @@ import lombok.experimental.Accessors;
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付同步订单")
|
||||
public class PaySyncRecordDto extends BaseDto {
|
||||
public class SyncRecordDto extends BaseDto {
|
||||
|
||||
/** 本地交易号 */
|
||||
@Schema(description = "本地订单ID")
|
@@ -1,77 +0,0 @@
|
||||
package cn.daxpay.single.service.param.record;
|
||||
|
||||
import cn.bootx.platform.common.core.annotation.QueryParam;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.code.RefundRepairWayEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付修复记录查询参数
|
||||
* @author xxm
|
||||
* @since 2024/1/9
|
||||
*/
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付修复记录查询参数")
|
||||
public class PayRepairRecordQuery {
|
||||
|
||||
|
||||
/**
|
||||
* 修复号
|
||||
* 如果一次修复产生的修复记录有多个记录, 使用这个作为关联
|
||||
*/
|
||||
@Schema(description = "修复号")
|
||||
private String repairNo;
|
||||
|
||||
/**
|
||||
* 本地交易号, 支付号/退款号
|
||||
*/
|
||||
@Schema(description = "本地业务号")
|
||||
private String tradeNo;
|
||||
|
||||
/**
|
||||
* 修复类型 支付修复/退款修复
|
||||
* @see TradeTypeEnum
|
||||
*/
|
||||
@Schema(description = "修复类型")
|
||||
private String repairType;
|
||||
|
||||
/**
|
||||
* 修复来源
|
||||
* @see TradeAdjustSourceEnum
|
||||
*/
|
||||
@Schema(description = "修复来源")
|
||||
private String repairSource;
|
||||
|
||||
/**
|
||||
* 修复方式
|
||||
* @see PayAdjustWayEnum
|
||||
* @see RefundRepairWayEnum
|
||||
*/
|
||||
@Schema(description = "修复方式")
|
||||
private String repairWay;
|
||||
|
||||
/** 修复的异步通道 */
|
||||
@Schema(description = "修复的通道")
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 修复前状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@Schema(description = "修复前状态")
|
||||
private String beforeStatus;
|
||||
|
||||
/**
|
||||
* 修复后状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@Schema(description = "修复后状态")
|
||||
private String afterStatus;
|
||||
}
|
@@ -12,15 +12,15 @@ import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付同步记录查询参数
|
||||
* 交易同步记录查询参数
|
||||
* @author xxm
|
||||
* @since 2024/1/9
|
||||
*/
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付同步记录查询参数")
|
||||
public class PaySyncRecordQuery {
|
||||
@Schema(title = "交易同步记录查询参数")
|
||||
public class TradeSyncRecordQuery {
|
||||
|
||||
/** 本地交易号 */
|
||||
@Schema(description = "本地交易号")
|
@@ -1,8 +1,6 @@
|
||||
package cn.daxpay.single.service.task;
|
||||
|
||||
import cn.daxpay.single.core.param.payment.pay.PaySyncParam;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.payment.pay.dao.PayExpiredTimeRepository;
|
||||
import cn.daxpay.single.service.core.payment.sync.service.PaySyncService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
@@ -47,8 +45,6 @@ public class PayExpiredTimeTask implements Job {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
// 设置补偿来源为定时任务
|
||||
PaymentContextLocal.get().getRepairInfo().setSource(TradeAdjustSourceEnum.TASK);
|
||||
// 执行同步操作, 网关同步时会对支付的进行状态的处理
|
||||
PaySyncParam paySyncParam = new PaySyncParam();
|
||||
paySyncParam.setOrderNo(orderNo);
|
||||
|
Reference in New Issue
Block a user