feat 支付记录各种数据完整性调整

This commit is contained in:
bootx
2024-01-28 22:52:31 +08:00
parent 03b7a4da9c
commit 9c7d49c400
23 changed files with 112 additions and 273 deletions

View File

@@ -86,8 +86,11 @@
- [x] 优化支付修复时的触发来源的获取 - [x] 优化支付修复时的触发来源的获取
- [x] 优化支付回调处理, 处理各种错误 - [x] 优化支付回调处理, 处理各种错误
- [x] 调整支付修复策略, 拆分为支付和退款修复两大类 - [x] 调整支付修复策略, 拆分为支付和退款修复两大类
- 2024-01-27: - 2024-01-28:
- 01-25支付宝对账单下载异常排查 - [x] 支付宝对账单下载异常排查-支付宝每日都会生成对账单, 哪怕为空, 也会生成
- [x] 订单修复记录前端显示调整
- 2044-01-29:
- [ ] 支付通道对出现疑似退款的订单进行报错提醒通过退款同步进行补偿
- [ ] 增加退款同步策略, 对退款中的状态的退款订单进行处理 - [ ] 增加退款同步策略, 对退款中的状态的退款订单进行处理
- **任务池** - **任务池**
- [ ] 微信退款状态不一致补偿 - [ ] 微信退款状态不一致补偿
@@ -97,7 +100,6 @@
- [ ] 支持转账操作, 通过支付通道专有参数进行实现, 转账时只能单个通道进行操作 - [ ] 支持转账操作, 通过支付通道专有参数进行实现, 转账时只能单个通道进行操作
- [ ] 支付成功回调后, 如果订单已超时, 则进入待退款订单中,提示进行退款,或者自动退款 - [ ] 支付成功回调后, 如果订单已超时, 则进入待退款订单中,提示进行退款,或者自动退款
- [ ] 退款状态同步逻辑 - [ ] 退款状态同步逻辑
- [x] 退款回调的处理
- [ ] 支付状态同步处理考虑退款情况 - [ ] 支付状态同步处理考虑退款情况
- [ ] 增加回调机制(通知客户端) - [ ] 增加回调机制(通知客户端)
- [ ] 增加消息通知机制(通知客户端) - [ ] 增加消息通知机制(通知客户端)

View File

@@ -0,0 +1,20 @@
package cn.bootx.platform.daxpay.service.code;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 支付修复时的支付/退款类型
* @author xxm
* @since 2024/1/28
*/
@Getter
@AllArgsConstructor
public enum PayRepairPayTypeEnum {
PAY("pay","支付"),
REFUND("refund","退款");
private final String code;
private final String name;
}

View File

@@ -4,13 +4,13 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* 支付修复类型 * 支付修复方式
* @author xxm * @author xxm
* @since 2023/12/28 * @since 2023/12/28
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum PayRepairTypeEnum { public enum PayRepairWayEnum {
SUCCESS("success","支付成功"), SUCCESS("success","支付成功"),
CLOSE_LOCAL("close_local","关闭本地支付"), CLOSE_LOCAL("close_local","关闭本地支付"),

View File

@@ -4,13 +4,13 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* 退款修复类型枚举 * 退款修复方式枚举
* @author xxm * @author xxm
* @since 2024/1/26 * @since 2024/1/26
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum RefundRepairTypeEnum { public enum RefundRepairWayEnum {
SUCCESS("success","退款成功"), SUCCESS("success","退款成功"),
FAIL("fail","退款失败"); FAIL("fail","退款失败");

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.daxpay.service.common.context; package cn.bootx.platform.daxpay.service.common.context;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@@ -14,8 +15,10 @@ import java.time.LocalDateTime;
@Accessors(chain = true) @Accessors(chain = true)
public class RepairLocal { public class RepairLocal {
/** 触发来源 */ /**
private String source; * 触发来源
*/
private PayRepairSourceEnum source;
/** 支付完成/退款时间 */ /** 支付完成/退款时间 */
private LocalDateTime finishTime; private LocalDateTime finishTime;

View File

@@ -1,9 +1,7 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.convert; package cn.bootx.platform.daxpay.service.core.channel.wechat.convert;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayOrder;
import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayConfigDto; import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayConfigDto;
import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayOrderDto;
import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayConfigParam; import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayConfigParam;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@@ -23,6 +21,4 @@ public interface WeChatConvert {
WeChatPayConfigDto convert(WeChatPayConfig in); WeChatPayConfigDto convert(WeChatPayConfig in);
WeChatPayOrderDto convert(WeChatPayOrder in);
} }

View File

@@ -1,27 +0,0 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayOrder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/**
* 微信支付记录
*
* @author xxm
* @since 2021/6/21
*/
@Deprecated
@Slf4j
@Repository
@RequiredArgsConstructor
public class WeChatPayOrderManager extends BaseManager<WeChatPayOrderMapper, WeChatPayOrder> {
public Optional<WeChatPayOrder> findByPaymentId(Long paymentId) {
return findByField(WeChatPayOrder::getPaymentId, paymentId);
}
}

View File

@@ -1,11 +0,0 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.dao;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Deprecated
@Mapper
public interface WeChatPayOrderMapper extends BaseMapper<WeChatPayOrder> {
}

View File

@@ -1,40 +0,0 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.entity;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.daxpay.service.common.entity.BasePayOrder;
import cn.bootx.platform.daxpay.service.core.channel.wechat.convert.WeChatConvert;
import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayOrderDto;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author xxm
* @since 2021/6/21
*/
@Deprecated
@EqualsAndHashCode(callSuper = true)
@Data
@DbTable(comment = "微信支付记录")
@Accessors(chain = true)
@TableName("pay_wechat_pay_order")
public class WeChatPayOrder extends BasePayOrder implements EntityBaseFunction<WeChatPayOrderDto> {
/** 微信交易号 */
@DbColumn(comment = "交易号")
private String tradeNo;
/** 所使用的支付方式 */
@DbColumn(comment = "支付方式")
private String payWay;
@Override
public WeChatPayOrderDto toDto() {
return WeChatConvert.CONVERT.convert(this);
}
}

View File

@@ -1,85 +0,0 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.service;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WeChatPayOrderManager;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Optional;
/**
* 微信支付记录单
*
* @author xxm
* @since 2021/6/21
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Deprecated
public class WeChatPayOrderService {
private final WeChatPayOrderManager weChatPayOrderManager;
/**
* 异步支付成功, 更新支付记录成功状态, 并创建微信支付记录
*/
public void updateAsyncSuccess(PayOrder payOrder, int amount) {
this.createWeChatOrder(payOrder, amount);
}
/**
* 并创建微信支付记录
*/
private void createWeChatOrder(PayOrder payOrder, int amount) {
String tradeNo = PaymentContextLocal.get()
.getAsyncPayInfo()
.getGatewayOrderNo();
// 创建微信支付记录
WeChatPayOrder wechatPayOrder = new WeChatPayOrder();
wechatPayOrder.setTradeNo(tradeNo)
.setPayWay(PaymentContextLocal.get().getAsyncPayInfo().getPayWay())
.setPaymentId(payOrder.getId())
.setAmount(amount)
.setRefundableBalance(amount)
.setBusinessNo(payOrder.getBusinessNo())
.setStatus(PayStatusEnum.SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
weChatPayOrderManager.save(wechatPayOrder);
}
/**
* 取消状态
*/
public void updateClose(Long paymentId) {
Optional<WeChatPayOrder> weChatPaymentOptional = weChatPayOrderManager.findByPaymentId(paymentId);
weChatPaymentOptional.ifPresent(weChatPayment -> {
weChatPayment.setStatus(PayStatusEnum.CLOSE.getCode());
weChatPayOrderManager.updateById(weChatPayment);
});
}
/**
* 更新退款
*/
public void updateRefund(Long paymentId, int amount) {
Optional<WeChatPayOrder> weChatPayment = weChatPayOrderManager.findByPaymentId(paymentId);
weChatPayment.ifPresent(payment -> {
int refundableBalance = payment.getRefundableBalance() - amount;
payment.setRefundableBalance(refundableBalance);
if (refundableBalance == 0) {
payment.setStatus(PayStatusEnum.REFUNDED.getCode());
}
else {
payment.setStatus(PayStatusEnum.PARTIAL_REFUND.getCode());
}
weChatPayOrderManager.updateById(payment);
});
}
}

View File

@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.service.core.payment.callback.service;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil; import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum; import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.context.CallbackLocal; import cn.bootx.platform.daxpay.service.common.context.CallbackLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
@@ -94,7 +94,7 @@ public class PayCallbackService {
return; return;
} }
// 执行支付完成修复逻辑 // 执行支付完成修复逻辑
PayRepairResult repair = payRepairService.repair(payOrder, PayRepairTypeEnum.SUCCESS); PayRepairResult repair = payRepairService.repair(payOrder, PayRepairWayEnum.SUCCESS);
callbackInfo.setPayRepairId(repair.getRepairId()); callbackInfo.setPayRepairId(repair.getRepairId());
} }
@@ -114,7 +114,7 @@ public class PayCallbackService {
return; return;
} }
// 执行支付关闭修复逻辑 // 执行支付关闭修复逻辑
PayRepairResult repair = payRepairService.repair(payOrder, PayRepairTypeEnum.CLOSE_LOCAL); PayRepairResult repair = payRepairService.repair(payOrder, PayRepairWayEnum.CLOSE_LOCAL);
callbackInfo.setPayRepairId(repair.getRepairId()); callbackInfo.setPayRepairId(repair.getRepairId());
} }

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.service.core.payment.callback.service;
import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.platform.daxpay.code.PayRefundStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum; import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.context.CallbackLocal; import cn.bootx.platform.daxpay.service.common.context.CallbackLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager; import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager;
@@ -60,10 +60,10 @@ public class PayRefundCallbackService {
// 退款成功还是失败 // 退款成功还是失败
if (Objects.equals(PayRefundStatusEnum.SUCCESS.getCode(), callbackInfo.getGatewayStatus())) { if (Objects.equals(PayRefundStatusEnum.SUCCESS.getCode(), callbackInfo.getGatewayStatus())) {
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairTypeEnum.SUCCESS); RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.SUCCESS);
callbackInfo.setPayRepairId(repair.getRepairId()); callbackInfo.setPayRepairId(repair.getRepairId());
} else { } else {
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairTypeEnum.FAIL); RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.FAIL);
callbackInfo.setPayRepairId(repair.getRepairId()); callbackInfo.setPayRepairId(repair.getRepairId());
} }

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.service.core.payment.repair.param; package cn.bootx.platform.daxpay.service.core.payment.repair.param;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@@ -15,5 +15,5 @@ import lombok.experimental.Accessors;
public class PayRepairParam { public class PayRepairParam {
@Schema(description = "修复类型") @Schema(description = "修复类型")
private PayRepairTypeEnum repairType; private PayRepairWayEnum repairType;
} }

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.service;
import cn.bootx.platform.common.core.function.CollectorsFunction; import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
@@ -47,7 +47,7 @@ public class PayRepairService {
* 修复支付单 * 修复支付单
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public PayRepairResult repair(PayOrder order, PayRepairTypeEnum repairType){ public PayRepairResult repair(PayOrder order, PayRepairWayEnum repairType){
// 1. 获取支付单管理的通道支付订单 // 1. 获取支付单管理的通道支付订单
Map<String, PayChannelOrder> channelOrderMap = channelOrderManager.findAllByPaymentId(order.getId()) Map<String, PayChannelOrder> channelOrderMap = channelOrderManager.findAllByPaymentId(order.getId())
.stream() .stream()
@@ -146,13 +146,13 @@ public class PayRepairService {
/** /**
* 保存记录 * 保存记录
*/ */
private void saveRecord(PayOrder order, PayRepairTypeEnum recordType, PayRepairResult repairResult){ private void saveRecord(PayOrder order, PayRepairWayEnum recordType, PayRepairResult repairResult){
// 修复后的状态 // 修复后的状态
String afterStatus = Optional.ofNullable(repairResult.getAfterPayStatus()).map(PayStatusEnum::getCode).orElse(null); String afterStatus = Optional.ofNullable(repairResult.getAfterPayStatus()).map(PayStatusEnum::getCode).orElse(null);
// 修复发起来源 // 修复发起来源
String source = PaymentContextLocal.get() String source = PaymentContextLocal.get()
.getRepairInfo() .getRepairInfo()
.getSource(); .getSource().getCode();
PayRepairRecord payRepairRecord = new PayRepairRecord() PayRepairRecord payRepairRecord = new PayRepairRecord()
.setRepairId(repairResult.getRepairId()) .setRepairId(repairResult.getRepairId())
.setOrderId(order.getId()) .setOrderId(order.getId())
@@ -161,7 +161,7 @@ public class PayRepairService {
.setBeforeStatus(repairResult.getBeforeStatus().getCode()) .setBeforeStatus(repairResult.getBeforeStatus().getCode())
.setAfterStatus(afterStatus) .setAfterStatus(afterStatus)
.setRepairSource(source) .setRepairSource(source)
.setRepairType(recordType.getCode()); .setRepairWay(recordType.getCode());
payRepairRecord.setId(repairResult.getRepairId()); payRepairRecord.setId(repairResult.getRepairId());
recordService.saveRecord(payRepairRecord); recordService.saveRecord(payRepairRecord);
} }

View File

@@ -3,7 +3,8 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.service;
import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.platform.daxpay.code.PayRefundStatusEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairPayTypeEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
@@ -50,7 +51,7 @@ public class RefundRepairService {
* 修复支付单 * 修复支付单
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public RefundRepairResult repair(PayRefundOrder refundOrder, RefundRepairTypeEnum repairType){ public RefundRepairResult repair(PayRefundOrder refundOrder, RefundRepairWayEnum repairType){
// 获取关联支付单 // 获取关联支付单
PayOrder payOrder = payOrderManager.findById(refundOrder.getPaymentId()) PayOrder payOrder = payOrderManager.findById(refundOrder.getPaymentId())
@@ -64,9 +65,9 @@ public class RefundRepairService {
// 根据不同的类型执行对应的修复逻辑 // 根据不同的类型执行对应的修复逻辑
RefundRepairResult repairResult = new RefundRepairResult(); RefundRepairResult repairResult = new RefundRepairResult();
if (Objects.requireNonNull(repairType) == RefundRepairTypeEnum.SUCCESS) { if (Objects.requireNonNull(repairType) == RefundRepairWayEnum.SUCCESS) {
repairResult = this.success(refundOrder,payOrder,refundChannelOrder,payChannelOrder); repairResult = this.success(refundOrder,payOrder,refundChannelOrder,payChannelOrder);
} else if (repairType == RefundRepairTypeEnum.FAIL) { } else if (repairType == RefundRepairWayEnum.FAIL) {
repairResult = this.closeLocal(refundOrder,payOrder,refundChannelOrder,payChannelOrder); repairResult = this.closeLocal(refundOrder,payOrder,refundChannelOrder,payChannelOrder);
} else { } else {
log.error("走到了理论上讲不会走到的分支"); log.error("走到了理论上讲不会走到的分支");
@@ -175,39 +176,41 @@ public class RefundRepairService {
/** /**
* 支付订单的修复记录 * 支付订单的修复记录
*/ */
private PayRepairRecord payRepairRecord(PayOrder order, RefundRepairTypeEnum repairType, RefundRepairResult repairResult){ private PayRepairRecord payRepairRecord(PayOrder order, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
// 修复后的状态 // 修复后的状态
String afterStatus = Optional.ofNullable(repairResult.getBeforePayStatus()).map(PayStatusEnum::getCode).orElse(null); String afterStatus = Optional.ofNullable(repairResult.getBeforePayStatus()).map(PayStatusEnum::getCode).orElse(null);
// 修复发起来源 // 修复发起来源
String source = PaymentContextLocal.get() String source = PaymentContextLocal.get()
.getRepairInfo() .getRepairInfo()
.getSource(); .getSource().getCode();
return new PayRepairRecord() return new PayRepairRecord()
.setOrderId(order.getId()) .setOrderId(order.getId())
.setRepairType(PayRepairPayTypeEnum.PAY.getCode())
.setAsyncChannel(order.getAsyncChannel()) .setAsyncChannel(order.getAsyncChannel())
.setOrderNo(order.getBusinessNo()) .setOrderNo(order.getBusinessNo())
.setBeforeStatus(repairResult.getAfterPayStatus().getCode()) .setBeforeStatus(repairResult.getAfterPayStatus().getCode())
.setAfterStatus(afterStatus) .setAfterStatus(afterStatus)
.setRepairSource(source) .setRepairSource(source)
.setRepairType(repairType.getCode()); .setRepairWay(repairType.getCode());
} }
/** /**
* 退款订单的修复记录 * 退款订单的修复记录
*/ */
private PayRepairRecord refundRepairRecord(PayRefundOrder refundOrder, RefundRepairTypeEnum repairType, RefundRepairResult repairResult){ private PayRepairRecord refundRepairRecord(PayRefundOrder refundOrder, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
// 修复后的状态 // 修复后的状态
String afterStatus = Optional.ofNullable(repairResult.getAfterRefundStatus()).map(PayRefundStatusEnum::getCode).orElse(null); String afterStatus = Optional.ofNullable(repairResult.getAfterRefundStatus()).map(PayRefundStatusEnum::getCode).orElse(null);
// 修复发起来源 // 修复发起来源
String source = PaymentContextLocal.get() String source = PaymentContextLocal.get()
.getRepairInfo() .getRepairInfo()
.getSource(); .getSource().getCode();
return new PayRepairRecord() return new PayRepairRecord()
.setOrderId(refundOrder.getId()) .setOrderId(refundOrder.getId())
.setOrderNo(refundOrder.getRefundNo()) .setOrderNo(refundOrder.getRefundNo())
.setRepairType(PayRepairPayTypeEnum.REFUND.getCode())
.setBeforeStatus(repairResult.getBeforeRefundStatus().getCode()) .setBeforeStatus(repairResult.getBeforeRefundStatus().getCode())
.setAfterStatus(afterStatus) .setAfterStatus(afterStatus)
.setRepairSource(source) .setRepairSource(source)
.setRepairType(repairType.getCode()); .setRepairWay(repairType.getCode());
} }
} }

View File

@@ -9,7 +9,7 @@ import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.pay.PaySyncParam; import cn.bootx.platform.daxpay.param.pay.PaySyncParam;
import cn.bootx.platform.daxpay.result.pay.PaySyncResult; import cn.bootx.platform.daxpay.result.pay.PaySyncResult;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum; import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.context.RepairLocal; import cn.bootx.platform.daxpay.service.common.context.RepairLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
@@ -21,7 +21,6 @@ import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncR
import cn.bootx.platform.daxpay.service.core.record.sync.entity.PaySyncRecord; import cn.bootx.platform.daxpay.service.core.record.sync.entity.PaySyncRecord;
import cn.bootx.platform.daxpay.service.core.record.sync.service.PaySyncRecordService; import cn.bootx.platform.daxpay.service.core.record.sync.service.PaySyncRecordService;
import cn.bootx.platform.daxpay.service.func.AbsPaySyncStrategy; import cn.bootx.platform.daxpay.service.func.AbsPaySyncStrategy;
import cn.hutool.core.util.StrUtil;
import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate; import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -179,33 +178,32 @@ public class PaySyncService {
PaySyncStatusEnum syncStatusEnum = syncResult.getSyncStatus(); PaySyncStatusEnum syncStatusEnum = syncResult.getSyncStatus();
// 如果没有支付来源, 设置支付来源为同步 // 如果没有支付来源, 设置支付来源为同步
RepairLocal repairInfo = PaymentContextLocal.get().getRepairInfo(); RepairLocal repairInfo = PaymentContextLocal.get().getRepairInfo();
if (Objects.isNull(repairInfo.getSource())){
if (StrUtil.isBlank(repairInfo.getSource())){ repairInfo.setSource(PayRepairSourceEnum.SYNC);
repairInfo.setSource(PayRepairSourceEnum.SYNC.getCode());
} }
PayRepairResult repair = new PayRepairResult(); PayRepairResult repair = new PayRepairResult();
// 对支付网关同步的结果进行处理 // 对支付网关同步的结果进行处理
switch (syncStatusEnum) { switch (syncStatusEnum) {
// 支付成功 支付宝退款时也是支付成功状态, 除非支付完成 // 支付成功 支付宝退款时也是支付成功状态, 除非支付完成
case PAY_SUCCESS: { case PAY_SUCCESS: {
repair = repairService.repair(payOrder, PayRepairTypeEnum.SUCCESS); repair = repairService.repair(payOrder, PayRepairWayEnum.SUCCESS);
break; break;
} }
// 待支付, 将订单状态重新设置为待支付 // 待支付, 将订单状态重新设置为待支付
case PAY_WAIT: { case PAY_WAIT: {
repair = repairService.repair(payOrder,PayRepairTypeEnum.WAIT_PAY); repair = repairService.repair(payOrder, PayRepairWayEnum.WAIT_PAY);
break; break;
} }
// 交易关闭和未找到, 都对本地支付订单进行关闭, 不需要再调用网关进行关闭 // 交易关闭和未找到, 都对本地支付订单进行关闭, 不需要再调用网关进行关闭
case CLOSED: case CLOSED:
case NOT_FOUND: { case NOT_FOUND: {
repair = repairService.repair(payOrder, PayRepairTypeEnum.CLOSE_LOCAL); repair = repairService.repair(payOrder, PayRepairWayEnum.CLOSE_LOCAL);
break; break;
} }
// 超时关闭和交易不存在(特殊) 关闭本地支付订单, 同时调用网关进行关闭, 确保后续这个订单不能被支付 // 超时关闭和交易不存在(特殊) 关闭本地支付订单, 同时调用网关进行关闭, 确保后续这个订单不能被支付
case TIMEOUT: case TIMEOUT:
case NOT_FOUND_UNKNOWN:{ case NOT_FOUND_UNKNOWN:{
repair = repairService.repair(payOrder, PayRepairTypeEnum.CLOSE_GATEWAY); repair = repairService.repair(payOrder, PayRepairWayEnum.CLOSE_GATEWAY);
break; break;
} }
// 调用出错 // 调用出错

View File

@@ -17,8 +17,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/** /**
* 回调通知 * 回调通知
* @author xxm * @author xxm
@@ -51,7 +49,7 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
* @see PayCallbackTypeEnum * @see PayCallbackTypeEnum
*/ */
@DbColumn(comment = "回调类型") @DbColumn(comment = "回调类型")
private String type; private String callbackType;
/** 通知消息内容 */ /** 通知消息内容 */
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT) @DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
@@ -59,7 +57,6 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
private String notifyInfo; private String notifyInfo;
/** /**
*
* @see PayCallbackStatusEnum * @see PayCallbackStatusEnum
*/ */
@DbColumn(comment = "回调处理状态") @DbColumn(comment = "回调处理状态")
@@ -73,10 +70,6 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
@DbColumn(comment = "提示信息") @DbColumn(comment = "提示信息")
private String msg; private String msg;
/** 回调时间 */
@DbColumn(comment = "回调时间")
private LocalDateTime notifyTime;
/** /**
* 转换 * 转换
*/ */

View File

@@ -3,9 +3,10 @@ package cn.bootx.platform.daxpay.service.core.record.repair.entity;
import cn.bootx.platform.common.core.function.EntityBaseFunction; import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairPayTypeEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum; import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum;
import cn.bootx.platform.daxpay.service.core.record.repair.convert.PayRepairRecordConvert; import cn.bootx.platform.daxpay.service.core.record.repair.convert.PayRepairRecordConvert;
import cn.bootx.platform.daxpay.service.dto.record.repair.PayRepairRecordDto; import cn.bootx.platform.daxpay.service.dto.record.repair.PayRepairRecordDto;
import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbColumn;
@@ -28,6 +29,7 @@ import lombok.experimental.Accessors;
public class PayRepairRecord extends MpCreateEntity implements EntityBaseFunction<PayRepairRecordDto> { public class PayRepairRecord extends MpCreateEntity implements EntityBaseFunction<PayRepairRecordDto> {
/** /**
* 修复ID
* 如果一次修复产生的修复记录只有一条, 则该字段为与ID一致 * 如果一次修复产生的修复记录只有一条, 则该字段为与ID一致
* 如果一次修复产生的修复记录有多个, 则使用这个ID作为关联 * 如果一次修复产生的修复记录有多个, 则使用这个ID作为关联
*/ */
@@ -35,18 +37,21 @@ public class PayRepairRecord extends MpCreateEntity implements EntityBaseFunctio
private Long repairId; private Long repairId;
/** 支付ID/退款ID */ /** 支付ID/退款ID */
@DbColumn(comment = "业务ID") @DbColumn(comment = "本地订单ID")
private Long orderId; private Long orderId;
/** /**
* 业务号, 支付业务号/退款号 * 本地业务号, 支付业务号/退款号
*/ */
@DbColumn(comment = "业务号") @DbColumn(comment = "本地业务号")
private String orderNo; private String orderNo;
/** 类型 支付修复/退款修复 */ /**
@DbColumn(comment = "类型") * 修复类型 支付修复/退款修复
private String type; * @see PayRepairPayTypeEnum
*/
@DbColumn(comment = "修复类型")
private String repairType;
/** /**
* 修复来源 * 修复来源
@@ -56,12 +61,12 @@ public class PayRepairRecord extends MpCreateEntity implements EntityBaseFunctio
private String repairSource; private String repairSource;
/** /**
* 修复类型 * 修复方式
* @see PayRepairTypeEnum * @see PayRepairWayEnum
* @see RefundRepairTypeEnum * @see RefundRepairWayEnum
*/ */
@DbColumn(comment = "修复类型") @DbColumn(comment = "修复方式")
private String repairType; private String repairWay;
/** 修复的异步通道 */ /** 修复的异步通道 */
@DbColumn(comment = "修复的异步通道") @DbColumn(comment = "修复的异步通道")

View File

@@ -1,27 +0,0 @@
package cn.bootx.platform.daxpay.service.dto.channel.wechat;
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author xxm
* @since 2021/6/21
*/
@Deprecated
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "微信支付记录")
public class WeChatPayOrderDto extends PayOrderDto implements Serializable {
private static final long serialVersionUID = -2400358210732595795L;
@Schema(description = "微信交易号")
private String tradeNo;
}

View File

@@ -3,13 +3,12 @@ package cn.bootx.platform.daxpay.service.dto.record.callback;
import cn.bootx.platform.common.core.rest.dto.BaseDto; import cn.bootx.platform.common.core.rest.dto.BaseDto;
import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum; import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayCallbackTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/** /**
* 支付回调记录 * 支付回调记录
* @author xxm * @author xxm
@@ -21,10 +20,11 @@ import java.time.LocalDateTime;
@Schema(title = "回调记录") @Schema(title = "回调记录")
public class PayCallbackRecordDto extends BaseDto { public class PayCallbackRecordDto extends BaseDto {
/** 支付记录id */ @Schema(description = "本地订单ID")
@Schema(description = "支付记录id") private Long orderId;
private Long paymentId;
@Schema(description = "支付网关订单号")
private String gatewayOrderNo;
/** /**
* 支付通道 * 支付通道
* @see PayChannelEnum#getCode() * @see PayChannelEnum#getCode()
@@ -32,6 +32,13 @@ public class PayCallbackRecordDto extends BaseDto {
@Schema(description = "支付通道") @Schema(description = "支付通道")
private String payChannel; private String payChannel;
/**
* 回调类型
* @see PayCallbackTypeEnum
*/
@Schema(description = "回调类型")
private String callbackType;
/** 通知消息 */ /** 通知消息 */
@Schema(description = "通知消息") @Schema(description = "通知消息")
private String notifyInfo; private String notifyInfo;
@@ -50,7 +57,4 @@ public class PayCallbackRecordDto extends BaseDto {
@Schema(description = "提示信息") @Schema(description = "提示信息")
private String msg; private String msg;
/** 回调时间 */
@Schema(description = "回调时间")
private LocalDateTime notifyTime;
} }

View File

@@ -3,7 +3,8 @@ package cn.bootx.platform.daxpay.service.dto.record.repair;
import cn.bootx.platform.common.core.rest.dto.BaseDto; import cn.bootx.platform.common.core.rest.dto.BaseDto;
import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum; import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum;
import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbColumn;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -37,8 +38,8 @@ public class PayRepairRecordDto extends BaseDto {
private String orderNo; private String orderNo;
/** 类型 支付修复/退款修复 */ /** 类型 支付修复/退款修复 */
@Schema(description = "类型") @Schema(description = "修复类型")
private String type; private String repairType;
/** /**
* 修复来源 * 修复来源
@@ -49,10 +50,11 @@ public class PayRepairRecordDto extends BaseDto {
/** /**
* 修复类型 * 修复类型
* @see PayRepairTypeEnum * @see PayRepairWayEnum
* @see RefundRepairWayEnum
*/ */
@Schema(description = "修复类型") @Schema(description = "修复类型")
private String repairType; private String repairWay;
/** 修复的异步通道 */ /** 修复的异步通道 */
@DbColumn(comment = "修复的异步通道") @DbColumn(comment = "修复的异步通道")

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.func;
import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum; import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayCallbackTypeEnum; import cn.bootx.platform.daxpay.service.code.PayCallbackTypeEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.common.context.CallbackLocal; import cn.bootx.platform.daxpay.service.common.context.CallbackLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.payment.callback.service.PayCallbackService; import cn.bootx.platform.daxpay.service.core.payment.callback.service.PayCallbackService;
@@ -12,7 +13,6 @@ import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Map; import java.util.Map;
/** /**
@@ -34,6 +34,7 @@ public abstract class AbsCallbackStrategy implements PayStrategy {
* 回调处理入口 * 回调处理入口
*/ */
public String callback(Map<String, String> params) { public String callback(Map<String, String> params) {
// 将参数写入到上下文中
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo(); CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
callbackInfo.getCallbackParam().putAll(params); callbackInfo.getCallbackParam().putAll(params);
// 验证消息 // 验证消息
@@ -43,6 +44,8 @@ public abstract class AbsCallbackStrategy implements PayStrategy {
this.saveCallbackRecord(); this.saveCallbackRecord();
return null; return null;
} }
// 提前设置订单修复的来源
PaymentContextLocal.get().getRepairInfo().setSource(PayRepairSourceEnum.CALLBACK);
// 判断回调类型 // 判断回调类型
PayCallbackTypeEnum callbackType = this.getCallbackType(); PayCallbackTypeEnum callbackType = this.getCallbackType();
@@ -94,9 +97,9 @@ public abstract class AbsCallbackStrategy implements PayStrategy {
PayCallbackRecord payNotifyRecord = new PayCallbackRecord() PayCallbackRecord payNotifyRecord = new PayCallbackRecord()
.setPayChannel(this.getChannel().getCode()) .setPayChannel(this.getChannel().getCode())
.setNotifyInfo(JSONUtil.toJsonStr(callbackInfo.getCallbackParam())) .setNotifyInfo(JSONUtil.toJsonStr(callbackInfo.getCallbackParam()))
.setNotifyTime(LocalDateTime.now())
.setOrderId(callbackInfo.getOrderId()) .setOrderId(callbackInfo.getOrderId())
.setGatewayOrderNo(callbackInfo.getGatewayOrderNo()) .setGatewayOrderNo(callbackInfo.getGatewayOrderNo())
.setCallbackType(this.getCallbackType().getCode())
.setRepairOrderId(callbackInfo.getPayRepairId()) .setRepairOrderId(callbackInfo.getPayRepairId())
.setStatus(callbackInfo.getCallbackStatus().getCode()) .setStatus(callbackInfo.getCallbackStatus().getCode())
.setMsg(callbackInfo.getMsg()); .setMsg(callbackInfo.getMsg());

View File

@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.service.param.record;
import cn.bootx.platform.common.core.annotation.QueryParam; import cn.bootx.platform.common.core.annotation.QueryParam;
import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum; import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@@ -36,7 +36,7 @@ public class PayRepairRecordQuery {
/** /**
* 修复类型 * 修复类型
* @see PayRepairTypeEnum * @see PayRepairWayEnum
*/ */
@Schema(description = "修复类型") @Schema(description = "修复类型")
private String repairType; private String repairType;