|
|
@@ -300,6 +300,72 @@ public class WalletService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 增加摊位余额
|
|
|
+ *
|
|
|
+ * @param storeId 摊位ID
|
|
|
+ * @param amount 增加金额
|
|
|
+ * @param billing 账单信息
|
|
|
+ */
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void addStallBalance(Long storeId, BigDecimal amount, UserBilling billing) {
|
|
|
+ // 1. 参数校验
|
|
|
+ if (storeId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
|
|
|
+ }
|
|
|
+ String lockKey = "wallet:stall:lock:" + storeId;
|
|
|
+ RLock lock = redissonClient.getLock(lockKey);
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 尝试获取锁
|
|
|
+ if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
|
|
|
+ boolean releaseInFinally = true;
|
|
|
+ try {
|
|
|
+ // 2. 获取摊位钱包
|
|
|
+ UserWallet stallWallet = userWalletService.selectByStoreId(storeId);
|
|
|
+ if (stallWallet == null) {
|
|
|
+ throw new ServiceException("摊位钱包不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 更新余额
|
|
|
+ BigDecimal newBalance = stallWallet.getBalanceWallet().add(amount);
|
|
|
+
|
|
|
+ // 4. 乐观锁更新钱包
|
|
|
+ LambdaUpdateWrapper<UserWallet> updateQuery = new LambdaUpdateWrapper<>();
|
|
|
+ updateQuery.eq(UserWallet::getStoreId, storeId)
|
|
|
+ .eq(UserWallet::getVersion, stallWallet.getVersion());
|
|
|
+
|
|
|
+ stallWallet.setBalanceWallet(newBalance);
|
|
|
+ stallWallet.setVersion(stallWallet.getVersion() + 1);
|
|
|
+
|
|
|
+ boolean updateSuccess = userWalletService.update(stallWallet, updateQuery);
|
|
|
+ createUserBill(billing, stallWallet.getBalanceWallet());
|
|
|
+ if (!updateSuccess) {
|
|
|
+ throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
|
|
|
+ }
|
|
|
+ releaseInFinally = false;
|
|
|
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
|
|
+ @Override
|
|
|
+ public void afterCommit() {
|
|
|
+ if (lock.isHeldByCurrentThread()) {
|
|
|
+ lock.unlock();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ if (releaseInFinally && lock.isHeldByCurrentThread()) {
|
|
|
+ lock.unlock();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
|
|
|
+ }
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ throw new ServiceException(MessageUtils.message("no.operation.interrupted.try.again"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 增加余额
|
|
|
*
|