diff --git a/play-admin/src/main/java/com/starry/admin/modules/withdraw/service/impl/WithdrawalServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/withdraw/service/impl/WithdrawalServiceImpl.java index 674e60c..47ac30c 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/withdraw/service/impl/WithdrawalServiceImpl.java +++ b/play-admin/src/main/java/com/starry/admin/modules/withdraw/service/impl/WithdrawalServiceImpl.java @@ -65,6 +65,23 @@ public class WithdrawalServiceImpl extends ServiceImpl lines = earningsService.findWithdrawable(clerkId, amount, now); if (lines.isEmpty()) throw new CustomException("可提现余额不足"); + // Reserve lines FIRST with temp ID (fail fast before creating request) + String tempWithdrawalId = "TEMP_" + IdUtils.getUuid(); + int reservedCount = 0; + for (EarningsLineEntity line : lines) { + boolean updated = earningsService.update(Wrappers.lambdaUpdate(EarningsLineEntity.class) + .eq(EarningsLineEntity::getId, line.getId()) + .eq(EarningsLineEntity::getStatus, line.getStatus()) // Verify status unchanged + .set(EarningsLineEntity::getStatus, "withdrawing") + .set(EarningsLineEntity::getWithdrawalId, tempWithdrawalId)); + if (!updated) { + // Another request already took this line + throw new CustomException("部分收益已被其他提现请求锁定,请重试"); + } + reservedCount++; + } + + // Only NOW create the request (after successful reservation) LocalDateTime confirmedAt = payeeProfile.getLastConfirmedAt(); String snapshotJson = buildPayeeSnapshot(payeeProfile, confirmedAt); @@ -80,20 +97,17 @@ public class WithdrawalServiceImpl extends ServiceImpl