xuqiang 1 rok pred
rodič
commit
cd20759952

+ 8 - 0
src/main/java/com/ydtech/modules/admin/service/impl/SysUserAccountServiceImpl.java

@@ -39,6 +39,7 @@ import com.ydtech.modules.ttqf.entity.vo.UserWithdrawal;
 import com.ydtech.modules.ttqf.service.TtqfService;
 import com.ydtech.modules.ttqf.xxx.InitializeInternalWithdrawalId;
 import com.ydtech.modules.ttqf.xxx.RoundRobinService;
+import com.ydtech.modules.ttqf.xxx.VirtualWithdrawal;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
@@ -296,6 +297,10 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
     @Override
     @Transactional
     public HttpResult<Object> inert(SysUserAccountVo sysUserAccountVo) {
+        if (sysSwitchConfigService.isEnabled(SwitchConfig.VIRTUAL_WITHDRAWAL.getCode())){
+            SpringUtil.getBean(VirtualWithdrawal.class).virtualWithdrawal("1212", new BigDecimal("100"));
+            return HttpResult.ok();
+        }
         String userId = BaseController.getUser().getId();
         if (isManagement(userId) && sysSwitchConfigService.getBalanceExtractStatus()) {
             //  个代走线上付款
@@ -416,6 +421,9 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
             sysAmountAuditingHistoryService.save(sysAmountAuditingHistory);
             sysAmountAuditingHistoryService.save(sysAmountAuditingHistoryTwo);
         }
+        if (sysSwitchConfigService.isEnabled(SwitchConfig.VIRTUAL_WITHDRAWAL.getCode())){
+            SpringUtil.getBean(VirtualWithdrawal.class).virtualWithdrawal(userId, amount);
+        }
         return HttpResult.ok("提现成功,等待审核");
     }
 

+ 8 - 0
src/main/java/com/ydtech/modules/ttqf/dao/PartTtqfRecordMapper.java

@@ -3,7 +3,15 @@ package com.ydtech.modules.ttqf.dao;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ydtech.modules.ttqf.entity.PartTtqfRecord;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.math.BigDecimal;
 
 @Mapper
 public interface PartTtqfRecordMapper extends BaseMapper<PartTtqfRecord> {
+
+
+    @Select("select sum(amount) from pay_ttqf_record where virtual_user_id=#{userId} and is_status=1")
+    BigDecimal verifyWithdrawalAmount(String userId);
+
 }

+ 35 - 4
src/main/java/com/ydtech/modules/ttqf/entity/PartTtqfRecord.java

@@ -1,17 +1,17 @@
 package com.ydtech.modules.ttqf.entity;
 
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ydtech.modules.base.model.BaseEntity;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 @Data
 @TableName("pay_ttqf_record")
-public class PartTtqfRecord extends BaseEntity {
+public class PartTtqfRecord {
 
 
     @TableId(type = IdType.ASSIGN_ID)
@@ -19,6 +19,8 @@ public class PartTtqfRecord extends BaseEntity {
 
     private String userId;
 
+    private String virtualUserId;
+
     private String bankCard;
 
     private BigDecimal accumulatedAmount;
@@ -27,5 +29,34 @@ public class PartTtqfRecord extends BaseEntity {
 
     private BigDecimal amount;
 
+    private int isStatus;
+
+    private String message;
+
+    /**
+     * 创建者
+     */
+    @TableField(value = "create_by",fill = FieldFill.INSERT)
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(value = "create_time",fill = FieldFill.INSERT)
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    @TableField(value = "update_by",fill = FieldFill.INSERT_UPDATE)
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
 
 }

+ 97 - 30
src/main/java/com/ydtech/modules/ttqf/xxx/VirtualWithdrawal.java

@@ -1,63 +1,130 @@
 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.ydtech.modules.admin.constants.SwitchConfig;
+import com.ydtech.core.page.HttpResult;
 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.ttqf.dao.PartTtqfRecordMapper;
 import com.ydtech.modules.ttqf.entity.PartTtqfRecord;
 import com.ydtech.modules.ttqf.entity.vo.UserWithdrawal;
 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.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
-
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
 
 @Component
 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
     private SysUserBankCardService sysUserBankCardService;
     @Autowired
     private TtqfService ttqfService;
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+    @Autowired
+    private PartTtqfRecordMapper partTtqfRecordMapper;
+    @Autowired
+    private RoundRobinService roundRobinService;
+    @Autowired
+    private InitializeInternalWithdrawalId initializeInternalWithdrawalId;
 
+    // 虚拟提现
     @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;
+    }
 }