fix(tenantwithdraworder): 修复提现失败时冻结金额未退还问题

新增 handleWithdrawRefund 逻辑,当状态为 REJECTED/CANCELED/FAILED 时自动返还冻结金额至可提现余额并生成对应流水。
This commit is contained in:
2026-01-06 20:07:30 +08:00
parent 04755188d6
commit 716cde6ea0

View File

@@ -75,38 +75,128 @@ public class KeyboardTenantWithdrawOrderServiceImpl implements KeyboardTenantWit
KeyboardTenantWithdrawOrderDO updateObj = BeanUtils.toBean(updateReqVO, KeyboardTenantWithdrawOrderDO.class); KeyboardTenantWithdrawOrderDO updateObj = BeanUtils.toBean(updateReqVO, KeyboardTenantWithdrawOrderDO.class);
tenantWithdrawOrderMapper.updateById(updateObj); tenantWithdrawOrderMapper.updateById(updateObj);
// 如果提现状态更新为成功PAID则扣除提现用户的冻结金额并创建流水记录
String newStatus = updateReqVO.getStatus(); String newStatus = updateReqVO.getStatus();
if ("PAID".equals(newStatus) && !"PAID".equals(existingOrder.getStatus())) { String oldStatus = existingOrder.getStatus();
// 获取提现用户的余额记录
TenantBalanceDO balance = tenantBalanceMapper.selectById(existingOrder.getTenantId());
if (balance != null) {
// 扣除冻结金额
BigDecimal frozenAmt = balance.getFrozenAmt() != null ? balance.getFrozenAmt() : BigDecimal.ZERO;
BigDecimal withdrawAmount = existingOrder.getAmount();
BigDecimal newFrozenAmt = frozenAmt.subtract(withdrawAmount);
// 确保冻结金额不为负数
if (newFrozenAmt.compareTo(BigDecimal.ZERO) < 0) {
newFrozenAmt = BigDecimal.ZERO;
}
balance.setFrozenAmt(newFrozenAmt);
tenantBalanceMapper.updateById(balance);
// 创建提现成功的流水记录 // 如果提现状态更新为成功PAID则扣除提现用户的冻结金额并创建流水记录
TenantBalanceTransactionDO transaction = TenantBalanceTransactionDO.builder() if ("PAID".equals(newStatus) && !"PAID".equals(oldStatus)) {
.bizNo(existingOrder.getBizNo()) handleWithdrawSuccess(existingOrder);
.points(withdrawAmount.negate()) // 提现金额(负数表示支出)
.balance(balance.getWithdrawableBalance() != null ? balance.getWithdrawableBalance() : BigDecimal.ZERO) // 当前可提现余额
.tenantId(existingOrder.getTenantId())
.type("WITHDRAW_SUCCESS")
.description("提现成功")
.orderId(existingOrder.getWithdrawNo())
.operatorId(TenantContextHolder.getTenantId())
.createdAt(LocalDateTime.now())
.build();
tenantBalanceTransactionMapper.insert(transaction);
}
} }
// 如果提现状态更新为已拒绝、已取消、打款失败,则返还冻结金额到可提现余额并创建流水记录
else if (isRefundStatus(newStatus) && !isRefundStatus(oldStatus)) {
handleWithdrawRefund(existingOrder, newStatus, updateReqVO.getReason());
}
}
/**
* 判断是否为需要退还冻结金额的状态
*/
private boolean isRefundStatus(String status) {
return "REJECTED".equals(status) || "CANCELED".equals(status) || "FAILED".equals(status);
}
/**
* 处理提现成功:扣除冻结金额并记录流水
*/
private void handleWithdrawSuccess(KeyboardTenantWithdrawOrderDO order) {
TenantBalanceDO balance = tenantBalanceMapper.selectById(order.getTenantId());
if (balance == null) {
return;
}
// 扣除冻结金额
BigDecimal frozenAmt = balance.getFrozenAmt() != null ? balance.getFrozenAmt() : BigDecimal.ZERO;
BigDecimal withdrawAmount = order.getAmount();
BigDecimal newFrozenAmt = frozenAmt.subtract(withdrawAmount);
if (newFrozenAmt.compareTo(BigDecimal.ZERO) < 0) {
newFrozenAmt = BigDecimal.ZERO;
}
balance.setFrozenAmt(newFrozenAmt);
tenantBalanceMapper.updateById(balance);
// 创建提现成功的流水记录
TenantBalanceTransactionDO transaction = TenantBalanceTransactionDO.builder()
.bizNo(order.getBizNo())
.points(withdrawAmount.negate()) // 提现金额(负数表示支出)
.balance(balance.getWithdrawableBalance() != null ? balance.getWithdrawableBalance() : BigDecimal.ZERO)
.tenantId(order.getTenantId())
.type("WITHDRAW_SUCCESS")
.description("提现成功")
.orderId(order.getWithdrawNo())
.operatorId(TenantContextHolder.getTenantId())
.createdAt(LocalDateTime.now())
.build();
tenantBalanceTransactionMapper.insert(transaction);
}
/**
* 处理提现退还:返还冻结金额到可提现余额并记录流水
*
* @param order 提现订单
* @param newStatus 新状态
* @param reason 拒绝/失败/取消原因
*/
private void handleWithdrawRefund(KeyboardTenantWithdrawOrderDO order, String newStatus, String reason) {
TenantBalanceDO balance = tenantBalanceMapper.selectById(order.getTenantId());
if (balance == null) {
return;
}
BigDecimal withdrawAmount = order.getAmount();
// 扣除冻结金额
BigDecimal frozenAmt = balance.getFrozenAmt() != null ? balance.getFrozenAmt() : BigDecimal.ZERO;
BigDecimal newFrozenAmt = frozenAmt.subtract(withdrawAmount);
if (newFrozenAmt.compareTo(BigDecimal.ZERO) < 0) {
newFrozenAmt = BigDecimal.ZERO;
}
balance.setFrozenAmt(newFrozenAmt);
// 返还到可提现余额
BigDecimal withdrawableBalance = balance.getWithdrawableBalance() != null ? balance.getWithdrawableBalance() : BigDecimal.ZERO;
BigDecimal newWithdrawableBalance = withdrawableBalance.add(withdrawAmount);
balance.setWithdrawableBalance(newWithdrawableBalance);
tenantBalanceMapper.updateById(balance);
// 根据状态确定流水类型和描述
String type;
String description;
switch (newStatus) {
case "REJECTED":
type = "WITHDRAW_REJECTED";
description = "提现被拒绝,金额已退还";
break;
case "CANCELED":
type = "WITHDRAW_CANCELED";
description = "提现已取消,金额已退还";
break;
case "FAILED":
type = "WITHDRAW_FAILED";
description = "提现打款失败,金额已退还";
break;
default:
type = "WITHDRAW_REFUND";
description = "提现退还";
}
// 备注:优先使用传入的原因,如果没有则使用默认描述
String remark = (reason != null && !reason.trim().isEmpty()) ? reason : description;
// 创建退还流水记录
TenantBalanceTransactionDO transaction = TenantBalanceTransactionDO.builder()
.bizNo(order.getBizNo())
.points(withdrawAmount) // 退还金额(正数表示收入)
.balance(newWithdrawableBalance) // 退还后的可提现余额
.tenantId(order.getTenantId())
.type(type)
.description(description)
.remark(remark)
.orderId(order.getWithdrawNo())
.operatorId(TenantContextHolder.getTenantId())
.createdAt(LocalDateTime.now())
.build();
tenantBalanceTransactionMapper.insert(transaction);
} }
@Override @Override