fix: release transfer locks and allow agent self transfer

This commit is contained in:
ZuoZuo 2026-05-01 17:29:05 +08:00
parent d9d67b8839
commit fc7d248171
3 changed files with 65 additions and 60 deletions

View File

@ -89,20 +89,20 @@ public class UserBankTransferGoldCmdExe {
boolean freight = freightBalanceService.existsBalance(cmd.getAcceptUserId()); boolean freight = freightBalanceService.existsBalance(cmd.getAcceptUserId());
ResponseAssert.isTrue(WalletErrorCode.TARGET_USER_NOT_RECHARGE_AGENCY, freight); ResponseAssert.isTrue(WalletErrorCode.TARGET_USER_NOT_RECHARGE_AGENCY, freight);
ResponseAssert.isTrue(WalletErrorCode.NOT_TRANSFER_YOURSELF, !Objects.equals(cmd.getAcceptUserId(), cmd.requiredReqUserId()));
// 上锁 // 上锁
String key = "UBWTransferGold:" + cmd.requiredReqUserId(); String key = "UBWTransferGold:" + cmd.requiredReqUserId();
ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60)); ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60));
BigDecimal balance = userBankBalanceService.getBalance(cmd.requiredReqUserId()) try {
.getAccurateBalance(); BigDecimal balance = userBankBalanceService.getBalance(cmd.requiredReqUserId())
.getAccurateBalance();
ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE, ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE,
ArithmeticUtils.gte(balance, cmd.getAmount())); ArithmeticUtils.gte(balance, cmd.getAmount()));
// 获得区域兑换比例金币比例 // 获得区域兑换比例金币比例
Double goldRatio = getExchangeGoldRatio(cmd); Double goldRatio = getExchangeGoldRatio(cmd);
BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN); BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN);
@ -112,39 +112,41 @@ public class UserBankTransferGoldCmdExe {
long result = goldQuantity.divide(new BigDecimal(10000), RoundingMode.DOWN).setScale(0, RoundingMode.DOWN).longValue(); long result = goldQuantity.divide(new BigDecimal(10000), RoundingMode.DOWN).setScale(0, RoundingMode.DOWN).longValue();
ResponseAssert.isTrue(FreightErrorCode.NOT_THRESHOLD, result >= Optional.ofNullable(freightBalance.getDeliveryThreshold()).orElse(0)); ResponseAssert.isTrue(FreightErrorCode.NOT_THRESHOLD, result >= Optional.ofNullable(freightBalance.getDeliveryThreshold()).orElse(0));
// 扣钱 // 扣钱
BankBalanceDTO decrUserBankBalanceDTO = userBankBalanceService.decr(cmd.requiredReqUserId(), BankBalanceDTO decrUserBankBalanceDTO = userBankBalanceService.decr(cmd.requiredReqUserId(),
PennyAmount.ofDollar(cmd.getAmount())); PennyAmount.ofDollar(cmd.getAmount()));
ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, decrUserBankBalanceDTO); ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, decrUserBankBalanceDTO);
Long bankRunWaterId = IdWorkerUtils.getId(); Long bankRunWaterId = IdWorkerUtils.getId();
// 银行卡流水 // 银行卡流水
userBankRunningWaterService.add( userBankRunningWaterService.add(
new UserBankRunningWater() new UserBankRunningWater()
.setId(bankRunWaterId) .setId(bankRunWaterId)
.setUserId(cmd.requiredReqUserId()) .setUserId(cmd.requiredReqUserId())
.setSysOrigin(cmd.requireReqSysOrigin()) .setSysOrigin(cmd.requireReqSysOrigin())
.setType(ReceiptType.EXPENDITURE.getType()) .setType(ReceiptType.EXPENDITURE.getType())
.setAmount(cmd.getAmount()) .setAmount(cmd.getAmount())
.setEvent(UserBankWaterEvent.TRANSFER_GOLD.name()) .setEvent(UserBankWaterEvent.TRANSFER_GOLD.name())
.setEventDescribe(UserBankWaterEvent.TRANSFER_GOLD.getDescribe()) .setEventDescribe(UserBankWaterEvent.TRANSFER_GOLD.getDescribe())
.setRemark("Withdrawal transfer") .setRemark("Withdrawal transfer")
.setTrackId(Objects.toString(cmd.getAcceptUserId())) .setTrackId(Objects.toString(cmd.getAcceptUserId()))
.setBalance(decrUserBankBalanceDTO.getAccurateBalance()) .setBalance(decrUserBankBalanceDTO.getAccurateBalance())
.setCreateTime(TimestampUtils.now()) .setCreateTime(TimestampUtils.now())
.setUpdateTime(TimestampUtils.now()) .setUpdateTime(TimestampUtils.now())
.setCreateUser(cmd.getReqUserId()) .setCreateUser(cmd.getReqUserId())
.setCreateUserOrigin(OpUserType.APP.getType()) .setCreateUserOrigin(OpUserType.APP.getType())
); );
// 发送金额 // 发送金额
sendGold(cmd, freight, goldQuantity, bankRunWaterId, "转账金币"); sendGold(cmd, freight, goldQuantity, bankRunWaterId, "转账金币");
redisService.unlock(key); return new UserBankWithdrawResultCO()
return new UserBankWithdrawResultCO() .setBankBalance(decrUserBankBalanceDTO.getAccurateBalance())
.setBankBalance(decrUserBankBalanceDTO.getAccurateBalance()) .setWithdrawAmount(Objects.toString(cmd.getAmount()));
.setWithdrawAmount(Objects.toString(cmd.getAmount())); } finally {
redisService.unlock(key);
}
} }
private void sendGold(UserBankWithdrawTransferCmd cmd, boolean freight, BigDecimal goldQuantity, private void sendGold(UserBankWithdrawTransferCmd cmd, boolean freight, BigDecimal goldQuantity,

View File

@ -44,10 +44,12 @@ public class UserBankSearchUserProfileQryExe {
return null; return null;
} }
if (isTransfer(cmd)) { boolean transfer = isTransfer(cmd);
if (Objects.equals(cmd.getReqUserId(), userProfile.getId())) { boolean sameUser = Objects.equals(cmd.getReqUserId(), userProfile.getId());
return null; boolean freightAgent = cmd.typeEqAgent()
} && Boolean.TRUE.equals(freightBalanceService.checkFreightAgent(userProfile.getId()));
if (transfer && sameUser && !freightAgent) {
return null;
} }
if (cmd.typeEqBD()) { if (cmd.typeEqBD()) {
@ -67,12 +69,11 @@ public class UserBankSearchUserProfileQryExe {
} }
if (cmd.typeEqAgent()) { if (cmd.typeEqAgent()) {
Boolean freightAgent = freightBalanceService.checkFreightAgent(userProfile.getId());
if (freightAgent) { if (freightAgent) {
return userProfile; return userProfile;
} }
if (isTransfer(cmd)) { if (transfer) {
return null; return null;
} }
return Objects.equals( return Objects.equals(

View File

@ -81,19 +81,19 @@ public class SalaryTransferGoldCmdExe {
boolean freight = freightBalanceService.existsBalance(cmd.getAcceptUserId()); boolean freight = freightBalanceService.existsBalance(cmd.getAcceptUserId());
ResponseAssert.isTrue(WalletErrorCode.TARGET_USER_NOT_RECHARGE_AGENCY, freight); ResponseAssert.isTrue(WalletErrorCode.TARGET_USER_NOT_RECHARGE_AGENCY, freight);
ResponseAssert.isTrue(WalletErrorCode.NOT_TRANSFER_YOURSELF, !Objects.equals(cmd.getAcceptUserId(), cmd.requiredReqUserId()));
// 上锁 // 上锁
String key = "USTransferGold:" + cmd.requiredReqUserId(); String key = "USTransferGold:" + cmd.requiredReqUserId();
ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60)); ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60));
BigDecimal balance = salaryAccountGateway.getAvailableBalance(cmd.getReqUserId(), SalaryType.of(cmd.getSalaryType())).getDollarAmount(); try {
BigDecimal balance = salaryAccountGateway.getAvailableBalance(cmd.getReqUserId(), SalaryType.of(cmd.getSalaryType())).getDollarAmount();
ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE, ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE,
ArithmeticUtils.gte(balance, cmd.getAmount())); ArithmeticUtils.gte(balance, cmd.getAmount()));
// 获得区域兑换比例金币比例 // 获得区域兑换比例金币比例
Double goldRatio = getExchangeGoldRatio(cmd); Double goldRatio = getExchangeGoldRatio(cmd);
Long bankRunWaterId = IdWorkerUtils.getId(); Long bankRunWaterId = IdWorkerUtils.getId();
BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN); BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN);
@ -104,19 +104,21 @@ public class SalaryTransferGoldCmdExe {
long result = goldQuantity.divide(new BigDecimal(10000), RoundingMode.DOWN).setScale(0, RoundingMode.DOWN).longValue(); long result = goldQuantity.divide(new BigDecimal(10000), RoundingMode.DOWN).setScale(0, RoundingMode.DOWN).longValue();
ResponseAssert.isTrue(FreightErrorCode.NOT_THRESHOLD, result >= Optional.ofNullable(freightBalance.getDeliveryThreshold()).orElse(0)); ResponseAssert.isTrue(FreightErrorCode.NOT_THRESHOLD, result >= Optional.ofNullable(freightBalance.getDeliveryThreshold()).orElse(0));
// 扣钱 // 扣钱
cmd.setReqTraceId(String.valueOf(bankRunWaterId)); cmd.setReqTraceId(String.valueOf(bankRunWaterId));
SalaryReceipt receipt = salaryAccountConvertor.toTransferReceipt(cmd); SalaryReceipt receipt = salaryAccountConvertor.toTransferReceipt(cmd);
SalaryReceiptRes salaryReceiptRes = salaryAccountGateway.changeBalance(receipt); SalaryReceiptRes salaryReceiptRes = salaryAccountGateway.changeBalance(receipt);
ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, salaryReceiptRes); ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, salaryReceiptRes);
// 发送金额 // 发送金额
sendGold(cmd, freight, goldQuantity, bankRunWaterId, "转账金币"); sendGold(cmd, freight, goldQuantity, bankRunWaterId, "转账金币");
redisService.unlock(key); return new UserBankWithdrawResultCO()
return new UserBankWithdrawResultCO() .setBankBalance(salaryReceiptRes.getAvailableBalance().getDollarAmount())
.setBankBalance(salaryReceiptRes.getAvailableBalance().getDollarAmount()) .setWithdrawAmount(Objects.toString(cmd.getAmount()));
.setWithdrawAmount(Objects.toString(cmd.getAmount())); } finally {
redisService.unlock(key);
}
} }
private void sendGold(SalaryWithdrawCmd cmd, boolean freight, BigDecimal goldQuantity, private void sendGold(SalaryWithdrawCmd cmd, boolean freight, BigDecimal goldQuantity,