新增 transfer gold 接口
This commit is contained in:
parent
6b78840f5e
commit
324b8dc2d5
@ -619,6 +619,11 @@ public enum GoldOrigin {
|
||||
*/
|
||||
BANK_GOLD_COIN_EXCHANGE("[Bank]Gold coin exchange"),
|
||||
|
||||
/**
|
||||
* 转账金币.
|
||||
*/
|
||||
BANK_GOLD_COIN_TRANSFER("[Bank]Gold coin transfer"),
|
||||
|
||||
/**
|
||||
* 幸运礼物.
|
||||
*/
|
||||
|
||||
@ -15,6 +15,11 @@ public enum UserBankWaterEvent {
|
||||
*/
|
||||
TRANSFER("Transfer"),
|
||||
|
||||
/**
|
||||
* 转账金币.
|
||||
*/
|
||||
TRANSFER_GOLD("Transfer"),
|
||||
|
||||
/**
|
||||
* 接收转账.
|
||||
*/
|
||||
|
||||
@ -123,6 +123,20 @@ public class BankRestController extends BaseController {
|
||||
return userBankService.transfer(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转账到金币.
|
||||
*
|
||||
* @eo.name 转账到金币.
|
||||
* @eo.url /transferGold
|
||||
* @eo.method post
|
||||
* @eo.request-type json
|
||||
*/
|
||||
@PostMapping("/transferGold")
|
||||
public UserBankWithdrawResultCO transferGold(
|
||||
@RequestBody @Validated UserBankWithdrawTransferCmd cmd) {
|
||||
return userBankService.transferGold(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 钻石转账.
|
||||
*
|
||||
|
||||
@ -0,0 +1,195 @@
|
||||
package com.red.circle.wallet.app.command.bank;
|
||||
|
||||
import com.red.circle.common.business.core.enums.OpUserType;
|
||||
import com.red.circle.common.business.core.enums.ReceiptType;
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.component.redis.service.RedisService;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||
import com.red.circle.framework.core.response.ResponseErrorCode;
|
||||
import com.red.circle.order.inner.endpoint.UserFreightRechargeRecordClient;
|
||||
import com.red.circle.order.inner.endpoint.UserRechargeCountClient;
|
||||
import com.red.circle.other.inner.endpoint.team.target.TeamMemberClient;
|
||||
import com.red.circle.other.inner.endpoint.team.target.UserBillDiamondBalanceClient;
|
||||
import com.red.circle.other.inner.endpoint.user.region.UserRegionClient;
|
||||
import com.red.circle.other.inner.endpoint.user.user.UserSvipClient;
|
||||
import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.num.ArithmeticUtils;
|
||||
import com.red.circle.tool.core.sequence.IdWorkerUtils;
|
||||
import com.red.circle.tool.core.tuple.PennyAmount;
|
||||
import com.red.circle.wallet.app.dto.clientobject.UserBankWithdrawResultCO;
|
||||
import com.red.circle.wallet.app.dto.cmd.UserBankExchangeGoldCmd;
|
||||
import com.red.circle.wallet.app.dto.cmd.UserBankWithdrawTransferCmd;
|
||||
import com.red.circle.wallet.domain.gateway.WalletGoldGateway;
|
||||
import com.red.circle.wallet.domain.wallet.WalletReceipt;
|
||||
import com.red.circle.wallet.infra.database.cache.service.UserPayAuthCacheService;
|
||||
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankRunningWater;
|
||||
import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceService;
|
||||
import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankRunningWaterService;
|
||||
import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankWithdrawGoldApplyService;
|
||||
import com.red.circle.wallet.infra.database.rds.entity.freight.FreightBalanceRunningWater;
|
||||
import com.red.circle.wallet.infra.database.rds.service.auth.PayAuthService;
|
||||
import com.red.circle.wallet.infra.database.rds.service.diamond.SalaryDiamondBalanceService;
|
||||
import com.red.circle.wallet.infra.database.rds.service.diamond.SalaryDiamondRunningWaterService;
|
||||
import com.red.circle.wallet.infra.database.rds.service.freight.FreightBalanceRunningWaterService;
|
||||
import com.red.circle.wallet.infra.database.rds.service.freight.FreightBalanceService;
|
||||
import com.red.circle.wallet.inner.error.WalletErrorCode;
|
||||
import com.red.circle.wallet.inner.model.dto.BankBalanceDTO;
|
||||
import com.red.circle.wallet.inner.model.enums.FreightBalanceOrigin;
|
||||
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||
import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户银行转账到金币命令执行器
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class UserBankTransferGoldCmdExe {
|
||||
|
||||
private final RedisService redisService;
|
||||
private final UserBankBalanceService userBankBalanceService;
|
||||
private final UserBankRunningWaterService userBankRunningWaterService;
|
||||
private final WalletGoldGateway walletGoldGateway;
|
||||
private final FreightBalanceService freightBalanceService;
|
||||
private final UserRegionClient userRegionClient;
|
||||
private final FreightBalanceRunningWaterService freightBalanceRunningWaterService;
|
||||
|
||||
/**
|
||||
* 执行转账到金币操作
|
||||
*
|
||||
* @param cmd 转账命令
|
||||
* @return 转账结果
|
||||
*/
|
||||
public UserBankWithdrawResultCO execute(UserBankWithdrawTransferCmd cmd) {
|
||||
ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
|
||||
ArithmeticUtils.gtZero(cmd.getAmount()));
|
||||
|
||||
// 上锁
|
||||
String key = "UBWTransferGold:" + cmd.requiredReqUserId();
|
||||
ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60));
|
||||
|
||||
BigDecimal balance = userBankBalanceService.getBalance(cmd.requiredReqUserId())
|
||||
.getAccurateBalance();
|
||||
|
||||
ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE,
|
||||
ArithmeticUtils.gte(balance, cmd.getAmount()));
|
||||
|
||||
// 扣钱
|
||||
BankBalanceDTO decrUserBankBalanceDTO = userBankBalanceService.decr(cmd.requiredReqUserId(),
|
||||
PennyAmount.ofDollar(cmd.getAmount()));
|
||||
ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, decrUserBankBalanceDTO);
|
||||
|
||||
Long bankRunWaterId = IdWorkerUtils.getId();
|
||||
|
||||
// 银行卡流水
|
||||
userBankRunningWaterService.add(
|
||||
new UserBankRunningWater()
|
||||
.setId(bankRunWaterId)
|
||||
.setUserId(cmd.requiredReqUserId())
|
||||
.setSysOrigin(cmd.requireReqSysOrigin())
|
||||
.setType(ReceiptType.EXPENDITURE.getType())
|
||||
.setAmount(cmd.getAmount())
|
||||
.setEvent(UserBankWaterEvent.TRANSFER_GOLD.name())
|
||||
.setEventDescribe(UserBankWaterEvent.TRANSFER_GOLD.getDescribe())
|
||||
.setRemark("Withdrawal transfer")
|
||||
.setTrackId(Objects.toString(cmd.getAcceptUserId()))
|
||||
.setBalance(decrUserBankBalanceDTO.getAccurateBalance())
|
||||
.setCreateTime(TimestampUtils.now())
|
||||
.setUpdateTime(TimestampUtils.now())
|
||||
.setCreateUser(cmd.getReqUserId())
|
||||
.setCreateUserOrigin(OpUserType.APP.getType())
|
||||
);
|
||||
|
||||
boolean freight = freightBalanceService.existsBalance(cmd.getAcceptUserId());
|
||||
|
||||
// 获得区域兑换比例金币比例
|
||||
Double goldRatio = getExchangeGoldRatio(cmd);
|
||||
BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN);
|
||||
// 发送金额
|
||||
sendGold(cmd, freight, goldQuantity, bankRunWaterId, "转账金币");
|
||||
|
||||
redisService.unlock(key);
|
||||
return new UserBankWithdrawResultCO()
|
||||
.setBankBalance(decrUserBankBalanceDTO.getAccurateBalance())
|
||||
.setWithdrawAmount(Objects.toString(cmd.getAmount()));
|
||||
}
|
||||
|
||||
private void sendGold(UserBankWithdrawTransferCmd cmd, boolean freight, BigDecimal goldQuantity,
|
||||
Long bankRunWaterId, String remark) {
|
||||
if (freight) {
|
||||
// 货运代理入账
|
||||
ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE,
|
||||
freightBalanceService
|
||||
.incrCandyBalance(SysOriginPlatformEnum.valueOf(cmd.getReqSysOrigin().getOrigin()),
|
||||
cmd.getAcceptUserId(), goldQuantity));
|
||||
|
||||
// 插入流水
|
||||
BigDecimal freightBalance = freightBalanceService.getAvailableBalance(cmd.getAcceptUserId());
|
||||
freightBalanceRunningWaterService.save(new FreightBalanceRunningWater()
|
||||
.setSysOrigin(cmd.getReqSysOrigin().getOrigin())
|
||||
.setUserId(cmd.getReqUserId())
|
||||
.setAcceptUserId(cmd.getAcceptUserId())
|
||||
.setType(ReceiptType.INCOME.getType())
|
||||
.setQuantity(goldQuantity)
|
||||
.setUsdQuantity(cmd.getAmount())
|
||||
.setBalance(freightBalance)
|
||||
.setOrigin(FreightBalanceOrigin.PURCHASE.name())
|
||||
.setRemark(remark)
|
||||
.withCreateUser(cmd.getReqUserId()));
|
||||
return;
|
||||
}
|
||||
|
||||
// 金币入账
|
||||
walletGoldGateway.changeBalance(new WalletReceipt()
|
||||
.setReqTraceId(cmd.getReqTraceId())
|
||||
.setReceiptType(ReceiptType.INCOME)
|
||||
.setUserId(cmd.getAcceptUserId())
|
||||
.setSysOrigin(cmd.getReqSysOrigin().getOrigin())
|
||||
.setEventType(Objects.toString(GoldOrigin.BANK_GOLD_COIN_TRANSFER))
|
||||
.setEventDesc(GoldOrigin.BANK_GOLD_COIN_TRANSFER.getDesc())
|
||||
.setEventId(Objects.toString(bankRunWaterId))
|
||||
.setAmount(PennyAmount.ofDollar(goldQuantity.longValue()))
|
||||
.setOpUserType(OpUserType.APP)
|
||||
.setCreateTime(cmd.getReqTime())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得1$兑换多少金币比例, 基于区域+用户输入的美元.
|
||||
*
|
||||
* @return 1美元可获得的金币数量.
|
||||
*/
|
||||
private Double getExchangeGoldRatio(UserBankWithdrawTransferCmd cmd) {
|
||||
|
||||
boolean freight = freightBalanceService.existsBalance(cmd.getReqUserId());
|
||||
|
||||
List<SysExchangeGoldTipDTO> exchangeGolds = ResponseAssert.requiredSuccess(
|
||||
userRegionClient.listRegionExchangeGoldTip(cmd.getReqUserId(), freight));
|
||||
ResponseAssert.notEmpty(CommonErrorCode.CONFIGURATION_ERROR, exchangeGolds);
|
||||
|
||||
exchangeGolds = exchangeGolds.stream().filter(gold ->
|
||||
cmd.getAmount().compareTo(BigDecimal.valueOf(gold.getStart())) >= 0 &&
|
||||
cmd.getAmount().compareTo(BigDecimal.valueOf(gold.getEnd())) <= 0)
|
||||
.collect(Collectors.toList());
|
||||
ResponseAssert.notEmpty(CommonErrorCode.CONFIGURATION_ERROR, exchangeGolds);
|
||||
|
||||
SysExchangeGoldTipDTO exchangeGold = exchangeGolds.get(0);
|
||||
ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, exchangeGold);
|
||||
ResponseAssert.isFalse(CommonErrorCode.CONFIGURATION_ERROR,
|
||||
Objects.isNull(exchangeGold.getValue()) || exchangeGold.getValue() <= 0);
|
||||
|
||||
return exchangeGold.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
@ -48,6 +48,7 @@ public class UserBankServiceImpl implements UserBankService {
|
||||
private final UserBankCheckWithdrawQryExe userBankCheckWithdrawQueryExe;
|
||||
private final UserBankExchangeGoldTipQryExe userBankExchangeGoldTipQryExe;
|
||||
private final UserBankWithdrawTransferCmdExe userBankWithdrawTransferCmdExe;
|
||||
private final UserBankTransferGoldCmdExe userBankTransferGoldCmdExe;
|
||||
private final UserBankDiamondWithdrawTransferCmdExe userBankDiamondWithdrawTransferCmdExe;
|
||||
private final UserBankSearchUserProfileQryExe userBankSearchUserProfileQryExe;
|
||||
private final UserBankCheckExchangeGoldQryExe userBankCheckExchangeGoldQryExe;
|
||||
@ -83,6 +84,11 @@ public class UserBankServiceImpl implements UserBankService {
|
||||
return userBankWithdrawTransferCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserBankWithdrawResultCO transferGold(UserBankWithdrawTransferCmd cmd) {
|
||||
return userBankTransferGoldCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserBankWithdrawResultCO diamondTransfer(UserBankWithdrawTransferCmd cmd) {
|
||||
return userBankDiamondWithdrawTransferCmdExe.execute(cmd);
|
||||
|
||||
@ -54,6 +54,11 @@ public interface UserBankService {
|
||||
*/
|
||||
UserBankWithdrawResultCO transfer(UserBankWithdrawTransferCmd cmd);
|
||||
|
||||
/**
|
||||
* 转账到金币.
|
||||
*/
|
||||
UserBankWithdrawResultCO transferGold(UserBankWithdrawTransferCmd cmd);
|
||||
|
||||
/**
|
||||
* 钻石转账.
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user