|
@@ -1,63 +1,130 @@
|
|
|
package com.ydtech.modules.ttqf.xxx;
|
|
package com.ydtech.modules.ttqf.xxx;
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-import cn.hutool.extra.spring.SpringUtil;
|
|
|
|
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
-import com.ydtech.modules.admin.constants.SwitchConfig;
|
|
|
|
|
|
|
+import com.ydtech.core.page.HttpResult;
|
|
|
import com.ydtech.modules.admin.model.po.SysUserBankCard;
|
|
import com.ydtech.modules.admin.model.po.SysUserBankCard;
|
|
|
-import com.ydtech.modules.admin.service.SysSwitchConfigService;
|
|
|
|
|
import com.ydtech.modules.admin.service.SysUserBankCardService;
|
|
import com.ydtech.modules.admin.service.SysUserBankCardService;
|
|
|
import com.ydtech.modules.ttqf.dao.PartTtqfRecordMapper;
|
|
import com.ydtech.modules.ttqf.dao.PartTtqfRecordMapper;
|
|
|
import com.ydtech.modules.ttqf.entity.PartTtqfRecord;
|
|
import com.ydtech.modules.ttqf.entity.PartTtqfRecord;
|
|
|
import com.ydtech.modules.ttqf.entity.vo.UserWithdrawal;
|
|
import com.ydtech.modules.ttqf.entity.vo.UserWithdrawal;
|
|
|
import com.ydtech.modules.ttqf.service.TtqfService;
|
|
import com.ydtech.modules.ttqf.service.TtqfService;
|
|
|
|
|
+import com.ydtech.utils.StringUtils;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.stereotype.Component;
|
|
|
-
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Date;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Objects;
|
|
|
|
|
|
|
|
@Component
|
|
@Component
|
|
|
public class VirtualWithdrawal {
|
|
public class VirtualWithdrawal {
|
|
|
|
|
|
|
|
- @Autowired
|
|
|
|
|
- private SysSwitchConfigService sysSwitchConfigService;
|
|
|
|
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(VirtualWithdrawal.class);
|
|
|
|
|
+
|
|
|
|
|
+ private static final BigDecimal MIN_WITHDRAWAL_AMOUNT = new BigDecimal("40000");
|
|
|
|
|
+ private static final BigDecimal COMMISSION = new BigDecimal("0.075");
|
|
|
|
|
+
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private SysUserBankCardService sysUserBankCardService;
|
|
private SysUserBankCardService sysUserBankCardService;
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private TtqfService ttqfService;
|
|
private TtqfService ttqfService;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private RedisTemplate<String, String> redisTemplate;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private PartTtqfRecordMapper partTtqfRecordMapper;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private RoundRobinService roundRobinService;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private InitializeInternalWithdrawalId initializeInternalWithdrawalId;
|
|
|
|
|
|
|
|
|
|
+ // 虚拟提现
|
|
|
@Async
|
|
@Async
|
|
|
- // 虚拟提现 virtualWithdrawal
|
|
|
|
|
- public void virtualWithdrawal(String userId, BigDecimal amount,String bankCard) {
|
|
|
|
|
|
|
+ public void virtualWithdrawal(String userId, BigDecimal amount) {
|
|
|
|
|
+ PartTtqfRecord record = new PartTtqfRecord();
|
|
|
|
|
+ record.setCreateTime(new Date());
|
|
|
|
|
|
|
|
- if (sysSwitchConfigService.isEnabled(SwitchConfig.VIRTUAL_WITHDRAWAL.getCode())){
|
|
|
|
|
- LambdaQueryWrapper<SysUserBankCard> queryWrapper = new LambdaQueryWrapper<>(SysUserBankCard.class);
|
|
|
|
|
- queryWrapper.eq(SysUserBankCard::getUserId, userId);
|
|
|
|
|
- queryWrapper.eq(SysUserBankCard::getIsDefault, 1);
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ initializeInternalWithdrawalId.initialize();
|
|
|
|
|
|
|
|
- SysUserBankCard one = sysUserBankCardService.getOne(queryWrapper);
|
|
|
|
|
- virtualWithdrawal( userId, amount, one.getBankNumber());
|
|
|
|
|
- }
|
|
|
|
|
- SpringUtil.getBean(InitializeInternalWithdrawalId.class).initialize();
|
|
|
|
|
|
|
+ List<String> list = new ArrayList<>();
|
|
|
|
|
+ List<String> redisList = redisTemplate.opsForList().range(RoundRobinService.LIST_KEY, 0, -1);
|
|
|
|
|
+ if (CollectionUtil.isEmpty(redisList)) {
|
|
|
|
|
+ redisList = new ArrayList<>(0);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- PartTtqfRecord record = new PartTtqfRecord();
|
|
|
|
|
- record.setUserId(userId);
|
|
|
|
|
- record.setBankCard(bankCard);
|
|
|
|
|
- record.setFeeAmount(BigDecimal.ZERO);
|
|
|
|
|
- record.setAmount(amount);
|
|
|
|
|
- SpringUtil.getBean(PartTtqfRecordMapper.class).insert(record);
|
|
|
|
|
|
|
+ String virtualUserId = getVirtualUserId(amount, list, redisList);
|
|
|
|
|
+ record.setVirtualUserId(virtualUserId);
|
|
|
|
|
|
|
|
- //调取 ttqf 平台提现到虚拟账户
|
|
|
|
|
- String id = SpringUtil.getBean(RoundRobinService.class).getNextWithLua();
|
|
|
|
|
- UserWithdrawal withdrawal = new UserWithdrawal();
|
|
|
|
|
- withdrawal.setUserId(id);
|
|
|
|
|
- withdrawal.setAmount(amount);
|
|
|
|
|
- withdrawal.setBankNumber(bankCard);
|
|
|
|
|
- ttqfService.userCashOut(withdrawal);
|
|
|
|
|
|
|
+ String bankNumber = "";
|
|
|
|
|
+ if (StringUtils.isNotEmpty(virtualUserId)) {
|
|
|
|
|
+ LambdaQueryWrapper<SysUserBankCard> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ queryWrapper.eq(SysUserBankCard::getUserId, virtualUserId);
|
|
|
|
|
+ queryWrapper.eq(SysUserBankCard::getIsDefault, 1);
|
|
|
|
|
+ SysUserBankCard one = sysUserBankCardService.getOne(queryWrapper);
|
|
|
|
|
+ if (Objects.isNull(one)) {
|
|
|
|
|
+ record.setMessage("请先绑定银行卡");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ bankNumber = one.getBankNumber();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ record.setUserId(userId);
|
|
|
|
|
+ record.setBankCard(bankNumber);
|
|
|
|
|
+ record.setFeeAmount(BigDecimal.ZERO);
|
|
|
|
|
+ record.setAmount(amount);
|
|
|
|
|
|
|
|
|
|
+ if (StringUtils.isNotEmpty(virtualUserId) && StringUtils.isNotEmpty(bankNumber)) {
|
|
|
|
|
+ UserWithdrawal withdrawal = new UserWithdrawal();
|
|
|
|
|
+ withdrawal.setUserId(virtualUserId);
|
|
|
|
|
+ withdrawal.setAmount(amount);
|
|
|
|
|
+ withdrawal.setBankNumber(bankNumber);
|
|
|
|
|
+ HttpResult httpResult = ttqfService.userCashOut(withdrawal);
|
|
|
|
|
+ if (httpResult.getCode() == 200) {
|
|
|
|
|
+ record.setIsStatus(1);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ record.setMessage(httpResult.getMsg());
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ record.setMessage("虚拟用户userId=" + virtualUserId + ",银行卡号=" + bankNumber);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("虚拟提现发生异常", e);
|
|
|
|
|
+ record.setMessage(e.getMessage());
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ partTtqfRecordMapper.insert(record);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public String getVirtualUserId(BigDecimal amount, List<String> list, List<String> redisList) {
|
|
|
|
|
+ int attemptCount = 0;
|
|
|
|
|
+ final int maxAttempts = redisList.size() * 2;
|
|
|
|
|
+
|
|
|
|
|
+ while (attemptCount++ < maxAttempts) {
|
|
|
|
|
+ String virtualUserId = roundRobinService.getNextWithLua();
|
|
|
|
|
+ list.add(virtualUserId);
|
|
|
|
|
+ if (!verifyWithdrawalAmount(virtualUserId, amount)) {
|
|
|
|
|
+ return virtualUserId;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (list.size() >= redisList.size()) {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public boolean verifyWithdrawalAmount(String userId, BigDecimal amount) {
|
|
|
|
|
+ BigDecimal balance = partTtqfRecordMapper.verifyWithdrawalAmount(userId);
|
|
|
|
|
+ if (balance == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal totalNeed = amount.multiply(BigDecimal.ONE.add(COMMISSION));
|
|
|
|
|
+ return totalNeed.compareTo(MIN_WITHDRAWAL_AMOUNT.subtract(balance)) > 0;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|