Quellcode durchsuchen

fix: 提现申请改为原子条件扣减,杜绝并发超提与负数金额

- 金额增加正数校验,负数不再能绕过检查
- 余额校验与扣减合并为一条原子 UPDATE(available_balance >= amount 条件),
  并发双提现不会把可提现余额扣成负数
- 站点账户不存在时给出明确异常而非 NPE

Co-Authored-By: Claude <noreply@anthropic.com>
skyline vor 3 Wochen
Ursprung
Commit
f549d96e45

+ 12 - 3
car-wash-service/src/main/java/com/kym/service/impl/StationAccountServiceImpl.java

@@ -68,14 +68,23 @@ public class StationAccountServiceImpl extends MyBaseServiceImpl<StationAccountM
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void applyWithdrawn(WithdrawnQueryParam params) {
+        // 金额正数校验,防止负数绕过余额检查反向增加余额
+        if (params.getAmount() == null || params.getAmount() <= 0) {
+            throw new BusinessException("提现金额必须大于0");
+        }
         var stationAccount = getStationAccount(params.getStationId());
-        if (stationAccount.getAvailableBalance() == null || stationAccount.getAvailableBalance() < params.getAmount()) {
-            throw new BusinessException("提现金额超出可提现金额!");
+        if (stationAccount == null) {
+            throw new BusinessException("站点账户不存在");
         }
-        lambdaUpdate()
+        // 原子条件扣减:余额不足或并发提现时影响行数为 0,不会把可提现余额扣成负数
+        boolean updated = lambdaUpdate()
                 .setSql("available_balance = available_balance - {0}, withdrawn_frozen_amount = withdrawn_frozen_amount + {0}", params.getAmount())
                 .eq(StationAccount::getStationId, params.getStationId())
+                .ge(StationAccount::getAvailableBalance, params.getAmount())
                 .update();
+        if (!updated) {
+            throw new BusinessException("提现金额超出可提现金额!");
+        }
 
         var withdrawnRecord = new WithdrawnRecord()
                 .setStationId(params.getStationId())