feat 优化支付相关订单和记录的查询条件

This commit is contained in:
bootx
2024-01-15 22:44:26 +08:00
parent 621a7639db
commit ca10f1b1f8
18 changed files with 154 additions and 87 deletions

View File

@@ -32,11 +32,8 @@ public class PaySyncResult extends PayCommonResult{
@Schema(description = "是否进行了修复")
private boolean repair;
@Schema(description = "支付单修复前状态")
private String beforeStatus;
@Schema(description = "支付单修复后状态")
private String afterStatus;
@Schema(description = "支付单修复ID")
private Long repairId;
@Schema(description = "失败原因")
private String errorMsg;

View File

@@ -12,6 +12,8 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class RepairResult {
/** 修复记录ID */
private Long id;
/** 修复前状态 */
private PayStatusEnum beforeStatus;
/** 修复后状态 */

View File

@@ -78,8 +78,8 @@ public class PayRepairService {
repairResult.setRepairStatus(repairResult.getBeforeStatus());
break;
}
this.saveRecord(order, repairParam, repairResult);
return repairResult;
PayRepairRecord payRepairRecord = this.saveRecord(order, repairParam, repairResult);
return repairResult.setId(payRepairRecord.getId());
}
/**
@@ -149,7 +149,7 @@ public class PayRepairService {
/**
* 保存记录
*/
private void saveRecord(PayOrder order, PayRepairParam repairParam, RepairResult repairResult){
private PayRepairRecord saveRecord(PayOrder order, PayRepairParam repairParam, RepairResult repairResult){
// 修复后的状态
String afterStatus = Optional.ofNullable(repairResult.getRepairStatus()).map(PayStatusEnum::getCode).orElse(null);
@@ -163,5 +163,6 @@ public class PayRepairService {
.setRepairSource(repairParam.getRepairSource().getCode())
.setRepairType(repairParam.getRepairType().getCode());
recordService.saveRecord(payRepairRecord);
return payRepairRecord;
}
}

View File

@@ -12,6 +12,7 @@ import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.payment.repair.param.PayRepairParam;
import cn.bootx.platform.daxpay.service.core.payment.repair.result.RepairResult;
import cn.bootx.platform.daxpay.service.core.payment.repair.service.PayRepairService;
import cn.bootx.platform.daxpay.service.core.payment.sync.factory.PaySyncStrategyFactory;
import cn.bootx.platform.daxpay.service.core.payment.sync.result.GatewaySyncResult;
@@ -91,42 +92,37 @@ public class PaySyncService {
// 获取同步策略类
AbsPaySyncStrategy syncPayStrategy = PaySyncStrategyFactory.create(payOrder.getAsyncChannel());
syncPayStrategy.initPayParam(payOrder);
// 记录支付单同步前后的状态
String beforeStatus = payOrder.getStatus();
String afterStatus = null;
// 执行同步操作, 获取支付网关同步的结果
GatewaySyncResult syncResult = syncPayStrategy.doSyncStatus();
// 判断是否同步成功
if (Objects.equals(syncResult.getSyncStatus(), PaySyncStatusEnum.FAIL)){
// 同步失败, 返回失败响应, 同时记录失败的日志
this.saveRecord(payOrder, syncResult, true, beforeStatus, null, syncResult.getErrorMsg());
this.saveRecord(payOrder, syncResult, false, null, syncResult.getErrorMsg());
return new PaySyncResult().setErrorMsg(syncResult.getErrorMsg());
}
// 判断网关状态是否和支付单一致, 同时更新网关同步状态
boolean statusSync = this.checkAndAdjustSyncStatus(syncResult,payOrder);
RepairResult repairResult = new RepairResult();
try {
// 状态不一致,执行支付单修复逻辑
if (!statusSync){
this.resultHandler(syncResult, payOrder);
afterStatus = payOrder.getStatus();
repairResult = this.resultHandler(syncResult, payOrder);
}
} catch (PayFailureException e) {
// 同步失败, 返回失败响应, 同时记录失败的日志
syncResult.setSyncStatus(PaySyncStatusEnum.FAIL);
this.saveRecord(payOrder, syncResult, false, beforeStatus, null, e.getMessage());
this.saveRecord(payOrder, syncResult, false, null, e.getMessage());
return new PaySyncResult().setErrorMsg(e.getMessage());
}
// 同步成功记录日志
this.saveRecord( payOrder, syncResult, !statusSync, beforeStatus, afterStatus, null);
this.saveRecord( payOrder, syncResult, !statusSync, repairResult.getId(), null);
return new PaySyncResult()
.setGatewayStatus(syncResult.getSyncStatus().getCode())
.setSuccess(true)
.setRepair(!statusSync)
.setBeforeStatus(beforeStatus)
.setAfterStatus(afterStatus);
.setRepairId(repairResult.getId());
} finally {
lockTemplate.releaseLock(lock);
}
@@ -178,41 +174,42 @@ public class PaySyncService {
/**
* 根据同步的结果对支付单进行处理
*/
private void resultHandler(GatewaySyncResult syncResult, PayOrder payOrder){
private RepairResult resultHandler(GatewaySyncResult syncResult, PayOrder payOrder){
PaySyncStatusEnum syncStatusEnum = syncResult.getSyncStatus();
PayRepairParam repairParam = new PayRepairParam().setRepairSource(PayRepairSourceEnum.SYNC);
RepairResult repair = new RepairResult();
// 对支付网关同步的结果进行处理
switch (syncStatusEnum) {
// 支付成功 支付宝退款时也是支付成功状态, 除非支付完成
case PAY_SUCCESS: {
repairParam.setRepairType(PayRepairTypeEnum.SUCCESS);
repairService.repair(payOrder,repairParam);
repair = repairService.repair(payOrder, repairParam);
break;
}
// 待支付, 将订单状态重新设置为待支付
case PAY_WAIT: {
repairParam.setRepairType(PayRepairTypeEnum.WAIT);
repairService.repair(payOrder,repairParam);
repair = repairService.repair(payOrder,repairParam);
break;
}
// 交易关闭和未找到, 都对本地支付订单进行关闭, 不需要再调用网关进行关闭
case CLOSED:
case NOT_FOUND: {
repairParam.setRepairType(PayRepairTypeEnum.CLOSE_LOCAL);
repairService.repair(payOrder, repairParam);
repair = repairService.repair(payOrder, repairParam);
break;
}
// 超时关闭和交易不存在(特殊) 关闭本地支付订单, 同时调用网关进行关闭, 确保后续这个订单不能被支付
case TIMEOUT:
case NOT_FOUND_UNKNOWN:{
repairParam.setRepairType(PayRepairTypeEnum.CLOSE_GATEWAY);
repairService.repair(payOrder, repairParam);
repair = repairService.repair(payOrder, repairParam);
break;
}
// 交易退款 TODO 未实现
case REFUND: {
repairParam.setRepairType(PayRepairTypeEnum.REFUND);
repairService.repair(payOrder, repairParam);
repair = repairService.repair(payOrder, repairParam);
break;
}
// 调用出错
@@ -225,6 +222,7 @@ public class PaySyncService {
throw new BizException("代码有问题");
}
}
return repair;
}
@@ -233,11 +231,9 @@ public class PaySyncService {
* @param payOrder 支付单
* @param syncResult 同步结果
* @param repair 是否修复
* @param beforeStatus 修复前的状态
* @param repairStatus 修复后的状态
* @param errorMsg 错误信息
*/
private void saveRecord(PayOrder payOrder,GatewaySyncResult syncResult, boolean repair, String beforeStatus, String repairStatus, String errorMsg){
private void saveRecord(PayOrder payOrder,GatewaySyncResult syncResult, boolean repair, Long repairOrderId, String errorMsg){
PaySyncRecord paySyncRecord = new PaySyncRecord()
.setPaymentId(payOrder.getId())
.setBusinessNo(payOrder.getBusinessNo())
@@ -245,8 +241,7 @@ public class PaySyncService {
.setSyncInfo(syncResult.getSyncInfo())
.setGatewayStatus(syncResult.getSyncStatus().getCode())
.setRepairOrder(repair)
.setBeforeStatus(beforeStatus)
.setAfterStatus(repairStatus)
.setRepairOrderId(repairOrderId)
.setErrorMsg(errorMsg)
.setClientIp(PaymentContextLocal.get().getRequest().getClientIp())
.setReqId(PaymentContextLocal.get().getRequest().getReqId());

View File

@@ -11,6 +11,7 @@ import cn.bootx.table.modify.annotation.DbTable;
import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType;
import cn.bootx.table.modify.mysql.constants.MySqlFieldTypeEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@@ -51,6 +52,10 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
@DbColumn(comment = "回调处理状态")
private String status;
@Schema(description = "支付单修复ID")
private Long repairOrderId;
/** 提示信息 */
@DbColumn(comment = "提示信息")
private String msg;

View File

@@ -1,11 +1,12 @@
package cn.bootx.platform.daxpay.service.core.record.close.dao;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
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.bootx.platform.daxpay.service.core.record.close.entity.PayCloseRecord;
import cn.bootx.platform.daxpay.service.param.record.PayCloseRecordQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -26,8 +27,7 @@ public class PayCloseRecordManager extends BaseManager<PayCloseRecordMapper, Pay
*/
public Page<PayCloseRecord> page(PageParam pageParam, PayCloseRecordQuery param){
Page<PayCloseRecord> mpPage = MpUtil.getMpPage(pageParam, PayCloseRecord.class);
return lambdaQuery()
.orderByDesc(MpIdEntity::getId)
.page(mpPage);
QueryWrapper<PayCloseRecord> generator = QueryGenerator.generator(param);
return page(mpPage, generator);
}
}

View File

@@ -1,11 +1,12 @@
package cn.bootx.platform.daxpay.service.core.record.repair.dao;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
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.bootx.platform.daxpay.service.core.record.repair.entity.PayRepairRecord;
import cn.bootx.platform.daxpay.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;
@@ -24,10 +25,9 @@ public class PayRepairRecordManager extends BaseManager<PayRepairRecordMapper, P
/**
* 分页
*/
public Page<PayRepairRecord> page(PageParam pageParam, PayRepairRecordQuery param){
public Page<PayRepairRecord> page(PageParam pageParam, PayRepairRecordQuery query){
Page<PayRepairRecord> mpPage = MpUtil.getMpPage(pageParam, PayRepairRecord.class);
return lambdaQuery()
.orderByDesc(MpIdEntity::getId)
.page(mpPage);
QueryWrapper<PayRepairRecord> generator = QueryGenerator.generator(query);
return page(mpPage, generator);
}
}

View File

@@ -1,18 +1,17 @@
package cn.bootx.platform.daxpay.service.core.record.sync.dao;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
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.bootx.platform.daxpay.service.core.record.sync.entity.PaySyncRecord;
import cn.bootx.platform.daxpay.service.param.record.PaySyncRecordQuery;
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;
import java.util.Objects;
/**
*
* @author xxm
@@ -26,13 +25,10 @@ public class PaySyncRecordManager extends BaseManager<PaySyncRecordMapper, PaySy
/**
* 分页
*/
public Page<PaySyncRecord> page(PageParam pageParam, PaySyncRecordQuery param) {
public Page<PaySyncRecord> page(PageParam pageParam, PaySyncRecordQuery query) {
Page<PaySyncRecord> mpPage = MpUtil.getMpPage(pageParam, PaySyncRecord.class);
return lambdaQuery().orderByDesc(MpIdEntity::getId)
.like(Objects.nonNull(param.getPaymentId()), PaySyncRecord::getPaymentId, param.getPaymentId())
.eq(Objects.nonNull(param.getAsyncChannel()), PaySyncRecord::getAsyncChannel, param.getAsyncChannel())
.eq(Objects.nonNull(param.getStatus()), PaySyncRecord::getGatewayStatus, param.getStatus())
.page(mpPage);
QueryWrapper<PaySyncRecord> generator = QueryGenerator.generator(query);
return page(mpPage, generator);
}
}

View File

@@ -42,9 +42,9 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
@DbColumn(comment = "同步通道")
private String asyncChannel;
/** 通知消息 */
/** 网关返回的同步消息 */
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
@DbColumn(comment = "通知消息")
@DbColumn(comment = "同步消息")
private String syncInfo;
/**
@@ -60,12 +60,8 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
@DbColumn(comment = "是否进行修复")
private boolean repairOrder;
/** 支付单修复前状态 */
@DbColumn(comment = "支付单修复前状态")
private String beforeStatus;
/** 支付单修复后状态 */
@DbColumn(comment = "支付单修复后状态")
private String afterStatus;
@DbColumn(comment = "支付单修复ID")
private Long repairOrderId;
@DbColumn(comment = "错误消息")
private String errorMsg;

View File

@@ -27,7 +27,7 @@ public class PayRefundOrderDto extends BaseDto {
@Schema(description = "关联的业务id")
private String businessNo;
@Schema(description = "款付单")
@Schema(description = "付号")
private Long paymentId;
@Schema(description = "异步方式关联退款请求号(部分退款情况)")

View File

@@ -43,6 +43,9 @@ public class PayCallbackRecordDto extends BaseDto {
@Schema(description = "回调处理状态")
private String status;
@Schema(description = "支付单修复ID")
private Long repairOrderId;
/** 提示信息 */
@Schema(description = "提示信息")
private String msg;

View File

@@ -22,53 +22,49 @@ import lombok.experimental.Accessors;
public class PaySyncRecordDto extends BaseDto {
/** 支付记录id */
@Schema(description ="支付记录id")
@Schema(description = "支付记录id")
private Long paymentId;
/** 业务号 */
@Schema(description ="业务号")
@Schema(description = "业务号")
private String businessNo;
/**
* 同步通道
* @see PayChannelEnum#getCode()
*/
@Schema(description ="同步通道")
@Schema(description = "同步通道")
private String asyncChannel;
/** 通知消息 */
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
@Schema(description ="通知消息")
@Schema(description = "通知消息")
private String syncInfo;
/**
* 网关返回状态
* @see PaySyncStatusEnum
*/
@Schema(description ="网关返回状态")
@Schema(description = "网关返回状态")
private String gatewayStatus;
/**
* 支付单如果状态不一致, 是否进行修复
*/
@Schema(description ="是否进行修复")
@Schema(description = "是否进行修复")
private boolean repairOrder;
/** 支付单修复前状态 */
@Schema(description ="支付单修复前状态")
private String beforeStatus;
/** 支付单修复后状态 */
@Schema(description ="支付单修复后状态")
private String afterStatus;
@Schema(description = "支付单修复ID")
private Long repairOrderId;
@Schema(description ="错误消息")
@Schema(description = "错误消息")
private String errorMsg;
/** 客户端IP */
@Schema(description ="客户端IP")
@Schema(description = "客户端IP")
private String clientIp;
/** 请求链路ID */
@Schema(description ="请求链路ID")
@Schema(description = "请求链路ID")
private String reqId;
}

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.param.order;
import cn.bootx.platform.common.core.annotation.QueryParam;
import cn.bootx.platform.common.core.rest.param.QueryOrder;
import cn.bootx.platform.daxpay.code.PayRefundStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -19,6 +20,9 @@ import lombok.experimental.Accessors;
@Schema(title = "支付退款查询参数")
public class PayRefundOrderQuery extends QueryOrder {
@Schema(description = "退款号")
private Long id;
@Schema(description = "支付号")
private Long paymentId;
@@ -32,4 +36,10 @@ public class PayRefundOrderQuery extends QueryOrder {
@Schema(description = "标题")
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
private String title;
/**
* @see PayRefundStatusEnum
*/
@Schema(description = "退款状态")
private String status;
}

View File

@@ -39,4 +39,7 @@ public class PayCallbackRecordQuery extends QueryOrder {
*/
@Schema(description = "回调处理状态")
private String status;
@Schema(description = "请求链路ID")
private String reqId;
}

View File

@@ -1,7 +1,10 @@
package cn.bootx.platform.daxpay.service.param.record;
import cn.bootx.platform.common.core.rest.param.QueryOrder;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
@@ -9,8 +12,25 @@ import lombok.experimental.Accessors;
* @author xxm
* @since 2024/1/9
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "支付关闭记录")
public class PayCloseRecordQuery {
public class PayCloseRecordQuery extends QueryOrder {
@Schema(description ="支付记录id")
private Long paymentId;
@Schema(description ="业务号")
private String businessNo;
/**
* 关闭的异步支付通道, 可以为空
* @see PayChannelEnum#getCode()
*/
@Schema(description ="关闭的异步支付通道")
private String asyncChannel;
@Schema(description = "请求链路ID")
private String reqId;
}

View File

@@ -1,5 +1,9 @@
package cn.bootx.platform.daxpay.service.param.record;
import cn.bootx.platform.common.core.annotation.QueryParam;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -9,9 +13,52 @@ import lombok.experimental.Accessors;
* @author xxm
* @since 2024/1/9
*/
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Data
@Accessors(chain = true)
@Schema(title = "支付修复记录查询参数")
public class PayRepairRecordQuery {
/** 支付ID */
@Schema(description = "支付ID")
private Long paymentId;
/** 业务号 */
@Schema(description = "业务号")
private String businessNo;
/**
* 修复来源
* @see PayRepairSourceEnum
*/
@Schema(description = "修复来源")
private String repairSource;
/**
* 修复类型
* @see PayRepairTypeEnum
*/
@Schema(description = "修复类型")
private String repairType;
/** 修复的异步通道 */
@Schema(description = "修复的异步通道")
private String asyncChannel;
/**
* 修复前状态
* @see PayStatusEnum
*/
@Schema(description = "修复前状态")
private String beforeStatus;
/**
* 修复后状态
* @see PayStatusEnum
*/
@Schema(description = "修复后状态")
private String afterStatus;
@Schema(description = "请求链路ID")
private String reqId;
}

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.daxpay.service.param.record;
import cn.bootx.platform.common.core.annotation.QueryParam;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PaySyncStatusEnum;
import cn.bootx.table.modify.annotation.DbColumn;
@@ -7,13 +8,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 支付同步记录查询参数
* @author xxm
* @since 2024/1/9
*/
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Data
@Accessors(chain = true)
@Schema(title = "支付同步记录查询参数")
@@ -30,26 +30,21 @@ public class PaySyncRecordQuery {
@Schema(description = "支付通道")
private String asyncChannel;
/** 通知消息 */
@Schema(description = "同步消息")
private String syncInfo;
@Schema(description = "请求链路ID")
private String reqId;
/**
* 同步状态
* @see PaySyncStatusEnum
*/
@Schema(description = "同步状态")
private String status;
private String gatewayStatus;
/**
* 支付单如果状态不一致, 是否修复成功
*/
@DbColumn(comment = "是否进行修复")
private boolean repairOrder;
/** 同步时间 */
@Schema(description = "同步时间")
private LocalDateTime syncTime;
private Boolean repairOrder;
/** 客户端IP */
@Schema(description = "客户端IP")