xiongzhu 4 лет назад
Родитель
Сommit
fd467a6324

+ 32 - 0
src/main/java/com/izouma/nineth/domain/AutoWithdrawRecord.java

@@ -0,0 +1,32 @@
+package com.izouma.nineth.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import java.time.LocalDate;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class AutoWithdrawRecord extends BaseEntity {
+
+    @Column(unique = true)
+    private LocalDate date;
+
+    private String remark;
+
+    private long progress;
+
+    private long total;
+
+    private String status;
+
+    private Long currentUserId;
+
+}

+ 12 - 0
src/main/java/com/izouma/nineth/repo/AutoWithdrawRecordRepo.java

@@ -0,0 +1,12 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.AutoWithdrawRecord;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.time.LocalDate;
+import java.util.Optional;
+
+public interface AutoWithdrawRecordRepo extends JpaRepository<AutoWithdrawRecord, Long> {
+
+    Optional<AutoWithdrawRecord> findByDate(LocalDate date);
+}

+ 2 - 0
src/main/java/com/izouma/nineth/repo/UserBalanceRepo.java

@@ -11,5 +11,7 @@ public interface UserBalanceRepo extends JpaRepository<UserBalance, Long>, JpaSp
 
     List<UserBalance> findByBalanceGreaterThan(BigDecimal balance);
 
+    List<UserBalance> findByBalanceGreaterThanOrderByUserId(BigDecimal balance);
+
 
 }

+ 2 - 2
src/main/java/com/izouma/nineth/service/SandPayService.java

@@ -234,13 +234,13 @@ public class SandPayService {
     }
 
 
-    public JSONObject transfer(String name, String bank, BigDecimal amount) {
+    public JSONObject transfer(String id, String name, String bank, BigDecimal amount) {
         JSONObject request = new JSONObject();
         DecimalFormat df = new DecimalFormat("000000000000", DecimalFormatSymbols.getInstance(Locale.US));
         request.put("version", "01");                          //版本号
         request.put("productId", "00000004");                  //产品ID
         request.put("tranTime", DateTimeUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss"));                //交易时间
-        request.put("orderCode", new SnowflakeIdWorker(1, 1).nextId());                       //订单号
+        request.put("orderCode", id);                       //订单号
         request.put("timeOut", DateTimeUtils.format(LocalDateTime.now().plusMinutes(3), "yyyyMMddHHmmss"));  //订单超时时间
         request.put("tranAmt", df.format(amount.multiply(new BigDecimal("100"))));                           //金额
         request.put("currencyCode", "156");                    //币种

+ 90 - 10
src/main/java/com/izouma/nineth/service/UserBalanceService.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.service;
 
 import cn.hutool.core.util.ZipUtil;
 import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSONObject;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.SandPaySettle;
 import com.izouma.nineth.dto.UserBankCard;
@@ -13,12 +14,9 @@ import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.*;
 import com.izouma.nineth.service.storage.StorageService;
 import com.izouma.nineth.utils.DateTimeUtils;
+import com.izouma.nineth.utils.SnowflakeIdWorker;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.ListUtils;
-import org.apache.commons.collections.Predicate;
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
@@ -30,10 +28,8 @@ import org.apache.poi.util.TempFile;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
-import org.springframework.web.bind.annotation.RequestPart;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import javax.transaction.Transactional;
 import java.io.*;
 import java.math.BigDecimal;
@@ -44,8 +40,6 @@ import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
 
 @Service
 @Slf4j
@@ -59,6 +53,9 @@ public class UserBalanceService {
     private final SettleRecordRepo              settleRecordRepo;
     private final StorageService                storageService;
     private final ExportWithdrawRepo            exportWithdrawRepo;
+    private final AutoWithdrawRecordRepo        autoWithdrawRecordRepo;
+    private final SnowflakeIdWorker             snowflakeIdWorker;
+    private final SandPayService                sandPayService;
     private final RedisTemplate<String, Object> redisTemplate;
 
     public void settle(LocalDate start, LocalDate end) {
@@ -205,7 +202,8 @@ public class UserBalanceService {
                 "upload/" + DateTimeUtils.format(LocalDateTime.now(), "yyyyMMddHHmm") + "_" + RandomStringUtils.randomNumeric(8) + ".zip");
 
         ExportWithdraw exportWithdraw = exportWithdrawRepo.save(new ExportWithdraw(url, remark, withdrawList.size(),
-                withdrawList.stream().map(UserWithdraw::getAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO), "处理中"));
+                withdrawList.stream().map(UserWithdraw::getAmount).reduce(BigDecimal::add)
+                        .orElse(BigDecimal.ZERO), "处理中"));
 
         balanceList.parallelStream().forEach(userBalance -> {
             log.info("提现userId={}", userBalance.getUserId());
@@ -244,7 +242,8 @@ public class UserBalanceService {
         List<UserWithdraw> failWithdraw = new ArrayList<>();
         for (SandPaySettle sandPaySettle : failSettleList) {
             List<UserWithdraw> list;
-            if (StringUtils.isNotBlank(sandPaySettle.getRemark()) && Pattern.matches("^\\d+$", sandPaySettle.getRemark().trim())) {
+            if (StringUtils.isNotBlank(sandPaySettle.getRemark()) && Pattern.matches("^\\d+$", sandPaySettle.getRemark()
+                    .trim())) {
                 Long userId = Long.parseLong(sandPaySettle.getRemark().trim());
                 list = withdrawList.stream().filter(i -> i.getUserId().equals(userId))
                         .collect(Collectors.toList());
@@ -277,4 +276,85 @@ public class UserBalanceService {
                     .build());
         });
     }
+
+    @Async
+    public void autoWithdraw(LocalDate date) {
+
+        autoWithdrawRecordRepo.findByDate(date).ifPresent(a -> {
+            throw new BusinessException("今日已经提现过");
+        });
+
+        List<UserBalance> list = userBalanceRepo.findByBalanceGreaterThanOrderByUserId(BigDecimal.ZERO);
+
+        AutoWithdrawRecord record = AutoWithdrawRecord.builder()
+                .date(LocalDate.now())
+                .status("pending")
+                .progress(0)
+                .total(list.size())
+                .build();
+        autoWithdrawRecordRepo.saveAndFlush(record);
+
+        for (UserBalance userBalance : list) {
+            UserBankCard userBankCard = userBankCardRepo.findByUserId(userBalance.getUserId())
+                    .stream().findFirst().orElse(null);
+            if (userBankCard == null) {
+                log.info("自动提现userId={}, amount={}, 未绑卡", userBalance.getBalance(), userBalance.getUserId());
+                record.setProgress(record.getProgress() + 1);
+                record.setCurrentUserId(userBalance.getUserId());
+                autoWithdrawRecordRepo.saveAndFlush(record);
+            } else {
+                log.info("自动提现userId={}, amount={}, name={}, bank={}",
+                        userBalance.getBalance(), userBalance.getUserId(),
+                        userBankCard.getRealName(), userBankCard.getBank());
+
+                String withdrawId = snowflakeIdWorker.nextId() + "";
+
+                BigDecimal amount = userBalance.getBalance();
+                userBalance.setLastBalance(userBalance.getBalance());
+                userBalance.setBalance(BigDecimal.ZERO);
+                userBalanceRepo.saveAndFlush(userBalance);
+
+                balanceRecordRepo.save(BalanceRecord.builder()
+                        .time(LocalDateTime.now())
+                        .userId(userBalance.getUserId())
+                        .amount(amount.negate())
+                        .balance(BigDecimal.ZERO)
+                        .lastBalance(userBalance.getLastBalance())
+                        .type(BalanceType.WITHDRAW)
+                        .build());
+
+                boolean success = false;
+                String msg = null;
+                try {
+                    JSONObject res = sandPayService.transfer(withdrawId, userBankCard.getRealName(), userBankCard.getBank(), amount);
+                    if ("0000".equals(res.getString("respCode"))) {
+                        success = true;
+                    } else {
+                        msg = res.getString("respDesc");
+                    }
+                } catch (Exception e) {
+                    msg = e.getMessage();
+                }
+
+                if (!success) {
+                    userBalance.setLastBalance(userBalance.getBalance());
+                    userBalance.setBalance(userBalance.getBalance().add(amount));
+                    userBalanceRepo.saveAndFlush(userBalance);
+
+                    balanceRecordRepo.save(BalanceRecord.builder()
+                            .time(LocalDateTime.now())
+                            .userId(userBalance.getUserId())
+                            .amount(amount)
+                            .balance(userBalance.getBalance())
+                            .lastBalance(userBalance.getLastBalance())
+                            .type(BalanceType.RETURN)
+                            .withdrawId(withdrawId)
+                            .remark(msg)
+                            .build());
+                }
+
+            }
+        }
+
+    }
 }

+ 33 - 0
src/main/java/com/izouma/nineth/web/AutoWithdrawController.java

@@ -0,0 +1,33 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.service.UserBalanceService;
+import com.izouma.nineth.utils.DateTimeUtils;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.Duration;
+import java.time.LocalDate;
+
+@RestController
+public class AutoWithdrawController extends BaseController {
+
+    private UserBalanceService            userBalanceService;
+    private RedisTemplate<String, Object> redisTemplate;
+
+    @PostMapping("/autoWithdraw")
+    public void autoWithdraw() {
+
+        LocalDate date = LocalDate.now();
+
+        Boolean success = redisTemplate.opsForValue()
+                .setIfAbsent("autoWithdraw::" + DateTimeUtils.format(date, "yyyyMMdd"),
+                        1, Duration.ofHours(24));
+        if (Boolean.FALSE.equals(success)) {
+            throw new BusinessException("redis锁定");
+        }
+
+        userBalanceService.autoWithdraw(date);
+    }
+}