| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- 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.annotations.RedisLock;
- import com.izouma.nineth.domain.*;
- import com.izouma.nineth.domain.nftdomain.DomainAsk;
- import com.izouma.nineth.dto.SandPaySettle;
- import com.izouma.nineth.dto.UserBankCard;
- import com.izouma.nineth.dto.UserWithdraw;
- import com.izouma.nineth.enums.*;
- 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.lang3.RandomStringUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
- import org.apache.poi.ss.usermodel.Row;
- import org.apache.poi.ss.usermodel.Sheet;
- import org.apache.poi.ss.usermodel.Workbook;
- import org.apache.poi.ss.usermodel.WorkbookFactory;
- import org.apache.poi.util.TempFile;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Lazy;
- import org.springframework.core.env.Environment;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import org.springframework.web.multipart.MultipartFile;
- import javax.transaction.Transactional;
- import java.io.*;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- import java.time.temporal.ChronoUnit;
- import java.util.*;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ForkJoinPool;
- import java.util.regex.Pattern;
- import java.util.stream.Collectors;
- @Service
- @Slf4j
- public class UserBalanceService {
- @Autowired
- private UserBalanceRepo userBalanceRepo;
- @Autowired
- private BalanceRecordRepo balanceRecordRepo;
- @Autowired
- private OrderRepo orderRepo;
- @Autowired
- private AssetRepo assetRepo;
- @Autowired
- private UserBankCardRepo userBankCardRepo;
- @Autowired
- private SettleRecordRepo settleRecordRepo;
- @Autowired
- private StorageService storageService;
- @Autowired
- private ExportWithdrawRepo exportWithdrawRepo;
- @Autowired
- private AutoWithdrawRecordRepo autoWithdrawRecordRepo;
- @Autowired
- private SnowflakeIdWorker snowflakeIdWorker;
- @Autowired
- private SandPayService sandPayService;
- @Autowired
- private RedisTemplate<String, Object> redisTemplate;
- @Autowired
- private RechargeOrderRepo rechargeOrderRepo;
- @Autowired
- private SysConfigService sysConfigService;
- @Autowired
- private Environment env;
- @Lazy
- @Autowired
- private AirDropService airDropService;
- @Autowired
- private UserRepo userRepo;
- public void settle(LocalDate start, LocalDate end) {
- for (long i = 0; i <= ChronoUnit.DAYS.between(start, end); i++) {
- LocalDate date = start.plusDays(i);
- if (settleRecordRepo.findByDate(date).isPresent()) {
- throw new BusinessException(DateTimeUtils.format(date, "yyyy-MM-dd") + "已经结算过");
- }
- }
- for (long i = 0; i <= ChronoUnit.DAYS.between(start, end); i++) {
- LocalDate date = start.plusDays(i);
- settle(date);
- }
- }
- public void settle(LocalDate date) {
- if (settleRecordRepo.findByDate(date).isPresent()) {
- throw new BusinessException(DateTimeUtils.format(date, "yyyy-MM-dd") + "已经结算过");
- }
- List<Order> orders = orderRepo.findByCreatedAtBetweenAndSourceAndStatusIn(date.atStartOfDay(),
- date.atTime(23, 59, 59, 9999), CollectionSource.TRANSFER,
- Arrays.asList(OrderStatus.PROCESSING, OrderStatus.FINISH));
- List<Asset> assets = assetRepo.findAllById(orders.stream().map(Order::getAssetId).collect(Collectors.toSet()));
- BigDecimal totalAmount = BigDecimal.ZERO;
- BigDecimal royaltiesAmount = BigDecimal.ZERO;
- BigDecimal serviceChargeAmount = BigDecimal.ZERO;
- List<UserBalance> balanceList = new ArrayList<>();
- List<BalanceRecord> recordList = new ArrayList<>();
- int c = 0;
- for (Order order : orders) {
- log.info("结算订单 {}/{}, orderId={}", ++c, orders.size(), order.getId());
- BalanceRecord record = balanceRecordRepo.findByOrderIdAndType(order.getId(), BalanceType.SELL);
- if (record != null) {
- continue;
- }
- Asset asset = assets.stream().filter(i -> i.getId().equals(order.getAssetId()))
- .findFirst()
- .orElseThrow(new BusinessException("藏品不存在"));
- UserBalance userBalance = balanceList.stream().filter(b -> b.getUserId().equals(asset.getUserId()))
- .findFirst().orElse(null);
- if (userBalance == null) {
- userBalance = userBalanceRepo.findById(asset.getUserId())
- .orElse(new UserBalance(asset
- .getUserId(), BigDecimal.ZERO, BigDecimal.ZERO,
- false, null, null));
- balanceList.add(userBalance);
- }
- BigDecimal amount = order.getTotalPrice()
- .subtract(order.getGasPrice())
- .multiply(BigDecimal
- .valueOf(100 - order.getRoyalties() - order.getServiceCharge()))
- .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
- totalAmount = totalAmount.add(order.getTotalPrice());
- royaltiesAmount = royaltiesAmount.add(order.getTotalPrice()
- .subtract(order.getGasPrice())
- .multiply(BigDecimal.valueOf(order.getRoyalties()))
- .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
- serviceChargeAmount = serviceChargeAmount.add(order.getTotalPrice()
- .subtract(order.getGasPrice())
- .multiply(BigDecimal.valueOf(order.getServiceCharge()))
- .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(amount));
- recordList.add(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(asset.getUserId())
- .orderId(order.getId())
- .amount(amount)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.SELL)
- .build());
- }
- userBalanceRepo.saveAll(balanceList);
- balanceRecordRepo.saveAll(recordList);
- settleRecordRepo.save(new SettleRecord(date, orders.size(), totalAmount, royaltiesAmount, serviceChargeAmount));
- }
- @Async
- @Transactional
- public ExportWithdraw exportWithdrawAsync(String remark) throws IOException, InvalidFormatException {
- return exportWithdraw(remark);
- }
- @Transactional
- public ExportWithdraw exportWithdraw(String remark) throws IOException, InvalidFormatException {
- List<UserBalance> balanceList = userBalanceRepo.findByBalanceGreaterThan(BigDecimal.ZERO);
- List<UserBankCard> userBankCardList = balanceList.isEmpty() ? new ArrayList<>() :
- userBankCardRepo.findByUserIdIn(balanceList.stream().map(UserBalance::getUserId)
- .collect(Collectors.toSet()));
- List<UserWithdraw> withdrawList = new ArrayList<>();
- Iterator<UserBalance> it = balanceList.iterator();
- UserBalance ub;
- while (it.hasNext()) {
- ub = it.next();
- Long userId = ub.getUserId();
- log.info("查询提现银行卡userId={}", ub.getUserId());
- UserBankCard ubc = userBankCardList.stream().filter(u -> u.getUserId().equals(userId))
- .findFirst().orElse(null);
- if (ubc != null) {
- withdrawList.add(new UserWithdraw(userId, ubc.getRealName(), ubc.getBankNo(), ub.getBalance()));
- } else {
- it.remove();
- }
- }
- File tmpDir = TempFile.createTempDirectory("export_" + RandomStringUtils.randomAlphabetic(8));
- File file1 = new File(tmpDir, DateTimeUtils.format(LocalDate.now(), "yyyyMMdd") + "结算.xlsx");
- File file2 = new File(tmpDir, DateTimeUtils.format(LocalDate.now(), "yyyyMMdd") + "结算导入.xls");
- EasyExcel.write(file1, UserWithdraw.class)
- .sheet("sheet").doWrite(withdrawList);
- InputStream inputStream = getClass().getResourceAsStream("/批量付款到对私银行账户模板.xls");
- Workbook workbook = WorkbookFactory.create(inputStream);
- Sheet sheet = workbook.getSheetAt(0);
- for (int i = 0; i < withdrawList.size(); i++) {
- Row row = Optional.ofNullable(sheet.getRow(i + 1)).orElse(sheet.createRow(i + 1));
- Optional.ofNullable(row.getCell(1))
- .orElse(row.createCell(1))
- .setCellValue(withdrawList.get(i).getName());
- Optional.ofNullable(row.getCell(2))
- .orElse(row.createCell(2))
- .setCellValue(withdrawList.get(i).getBankNo());
- Optional.ofNullable(row.getCell(3))
- .orElse(row.createCell(3))
- .setCellValue(withdrawList.get(i).getAmount().doubleValue());
- Optional.ofNullable(row.getCell(4))
- .orElse(row.createCell(4))
- .setCellValue(withdrawList.get(i).getUserId());
- }
- inputStream.close();
- FileOutputStream os = new FileOutputStream(file2);
- workbook.write(os);
- workbook.close();
- File zipFile = ZipUtil.zip(tmpDir);
- String url = storageService.uploadFromInputStream(new FileInputStream(zipFile),
- "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), "处理中"));
- balanceList.parallelStream().forEach(userBalance -> {
- log.info("提现userId={}", userBalance.getUserId());
- 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());
- });
- tmpDir.delete();
- zipFile.delete();
- return exportWithdraw;
- }
- @Transactional
- public void importFail(MultipartFile withdrawFile, MultipartFile settleFile) throws IOException {
- List<SandPaySettle> failSettleList = EasyExcel.read(settleFile.getInputStream())
- .head(SandPaySettle.class).sheet()
- .doReadSync();
- failSettleList = failSettleList.stream()
- .filter(s -> "失败".equals(s.getStatus().trim()))
- .collect(Collectors.toList());
- List<UserWithdraw> withdrawList = EasyExcel.read(withdrawFile.getInputStream())
- .head(UserWithdraw.class).sheet()
- .doReadSync();
- List<UserWithdraw> failWithdraw = new ArrayList<>();
- for (SandPaySettle sandPaySettle : failSettleList) {
- List<UserWithdraw> list;
- 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());
- } else {
- list = withdrawList.stream().filter(i -> i.getBankNo().equals(sandPaySettle.getBankNo())
- && i.getName().equals(sandPaySettle.getName())
- && i.getAmount().compareTo(sandPaySettle.getAmount()) == 0)
- .collect(Collectors.toList());
- }
- if (list.size() != 1) {
- throw new BusinessException("不唯一:" + sandPaySettle.getName() + "," + sandPaySettle.getBankNo());
- } else {
- failWithdraw.add(list.get(0));
- }
- }
- failWithdraw.parallelStream().forEach(withdraw -> {
- UserBalance userBalance = userBalanceRepo.findById(withdraw.getUserId())
- .orElse(new UserBalance(withdraw
- .getUserId(), BigDecimal.ZERO, BigDecimal.ZERO,
- false, null, null));
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(withdraw.getAmount()));
- userBalanceRepo.saveAndFlush(userBalance);
- balanceRecordRepo.save(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(userBalance.getUserId())
- .amount(withdraw.getAmount())
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.RETURN)
- .build());
- });
- }
- @Async
- public void autoWithdraw(LocalDate date) throws ExecutionException, InterruptedException {
- ForkJoinPool customThreadPool = new ForkJoinPool(5);
- customThreadPool.submit(() -> {
- autoWithdrawRecordRepo.findByDate(date).ifPresent(a -> {
- throw new BusinessException("今日已经提现过");
- });
- List<UserBalance> list = userBalanceRepo
- .findByLockedFalseAndBalanceGreaterThanOrderByUserId(BigDecimal.ZERO);
- AutoWithdrawRecord record = AutoWithdrawRecord.builder()
- .date(LocalDate.now())
- .status("pending")
- .progress(0)
- .total(list.size())
- .build();
- autoWithdrawRecordRepo.saveAndFlush(record);
- list.parallelStream().forEach(userBalance -> {
- 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.getUserId(), userBalance.getBalance(),
- userBankCard.getRealName(), userBankCard.getBankNo());
- 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)
- .withdrawId(withdrawId)
- .build());
- boolean success = false;
- String msg = null;
- try {
- JSONObject res = sandPayService.transfer(withdrawId, userBankCard.getRealName(), userBankCard
- .getBankNo(), amount, userBankCard.getPhone());
- 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());
- }
- record.setProgress(record.getProgress() + 1);
- record.setCurrentUserId(userBalance.getUserId());
- autoWithdrawRecordRepo.saveAndFlush(record);
- if (!success) {
- userBalance.setLocked(true);
- userBalance.setLockReason(msg);
- userBalance.setLockTime(LocalDateTime.now());
- userBalanceRepo.saveAndFlush(userBalance);
- }
- }
- });
- record.setStatus("finish");
- autoWithdrawRecordRepo.saveAndFlush(record);
- }).get();
- }
- public void revert() throws ExecutionException, InterruptedException {
- ForkJoinPool customThreadPool = new ForkJoinPool(200);
- customThreadPool.submit(() -> {
- LocalDate now = LocalDate.now();
- userBalanceRepo.findAll().parallelStream().forEach(userBalance -> {
- List<BalanceRecord> balanceRecords = balanceRecordRepo
- .findByUserIdOrderByCreatedAt(userBalance.getUserId());
- List<BalanceRecord> todayRecords = balanceRecords.stream()
- .filter(b -> b.getCreatedAt().toLocalDate()
- .equals(now))
- .collect(Collectors.toList());
- List<BalanceRecord> oldRecords = balanceRecords.stream()
- .filter(b -> !b.getCreatedAt().toLocalDate().equals(now))
- .sorted(Comparator.comparing(BaseEntity::getCreatedAt))
- .collect(Collectors.toList());
- if (oldRecords.size() == 0) {
- userBalanceRepo.delete(userBalance);
- } else {
- BalanceRecord record = oldRecords.get(oldRecords.size() - 1);
- userBalance.setBalance(record.getBalance());
- userBalance.setLastBalance(record.getLastBalance());
- userBalanceRepo.save(userBalance);
- }
- balanceRecordRepo.deleteAll(todayRecords);
- });
- }).get();
- }
- @RedisLock("#userId")
- public BalanceRecord balancePay(Long userId, BigDecimal amount, Long orderId, String remark) {
- UserBalance userBalance = userBalanceRepo.findById(userId).orElseThrow(new BusinessException("余额不足"));
- if (userBalance.getBalance().compareTo(amount) < 0) {
- throw new BusinessException("余额不足");
- }
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().subtract(amount));
- userBalanceRepo.save(userBalance);
- return balanceRecordRepo.save(BalanceRecord.builder()
- .userId(userId)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.PAY)
- .amount(amount.negate())
- .time(LocalDateTime.now())
- .orderId(orderId)
- .remark(remark)
- .build());
- }
- @RedisLock("#userId")
- public void recharge(Long orderId, PayMethod payMethod, String transactionId) {
- log.info("recharge orderId={}, transactionId={}, payMethod={}",
- orderId, transactionId, payMethod);
- RechargeOrder rechargeOrder = rechargeOrderRepo.findById(orderId).orElseThrow(new BusinessException("充值订单不存在"));
- Long userId = rechargeOrder.getUserId();
- if (OrderStatus.NOT_PAID == rechargeOrder.getStatus()) {
- BigDecimal amount = rechargeOrder.getAmount();
- UserBalance userBalance = userBalanceRepo.findById(userId).orElse(UserBalance.builder()
- .userId(userId)
- .balance(BigDecimal.ZERO)
- .lastBalance(BigDecimal.ZERO)
- .build());
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(amount));
- userBalanceRepo.save(userBalance);
- balanceRecordRepo.save(BalanceRecord.builder()
- .userId(userId)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.RECHARGE)
- .amount(amount)
- .time(LocalDateTime.now())
- .orderId(orderId)
- .payMethod(payMethod)
- .build());
- rechargeOrder.setStatus(OrderStatus.FINISH);
- rechargeOrderRepo.save(rechargeOrder);
- } else if (OrderStatus.FINISH == rechargeOrder.getStatus()) {
- log.info("recharge orderId={} has been finished", orderId);
- } else {
- throw new BusinessException("充值订单状态异常");
- }
- LocalDate now = LocalDate.now();
- LocalDate start = LocalDate.of(2023, 1, 19);
- LocalDate end = LocalDate.of(2023, 1, 29);
- if (now.isBefore(end) & now.isAfter(start)) {
- try {
- Long checkResult = checkRechargeSum(rechargeOrder.getAmount());
- if (checkResult > 0) {
- airDrop(rechargeOrder.getId(), rechargeOrder.getUserId(), checkResult);
- }
- } catch (Exception e) {
- log.info("空投藏品出错:rechargeOrderId" + rechargeOrder.getId());
- }
- }
- }
- public void airDrop(Long orderId, Long userId, Long checkResult) {
- Long collectionId = Long.valueOf(sysConfigService.getString("recharge_collectionId"));
- User user = userRepo.findById(userId).orElseThrow(new BusinessException("暂无该用户"));
- airDropService.create(AirDrop.builder()
- .name("春节充值空投福卡")
- .remark("rechargeOrder:" + orderId)
- .type(AirDropType.asset)
- .userIds(Collections.singletonList(userId))
- .collectionId(collectionId)
- .targets(Collections
- .singletonList(new DropTarget(user.getId(), user.getPhone(), user
- .getNickname(), Math.toIntExact(checkResult))))
- .auto(true)
- .companyId(1L)
- .build());
- }
- public Long checkRechargeSum(BigDecimal recharge) {
- BigDecimal targetNum = BigDecimal.valueOf(5000L);
- return recharge.divide(targetNum, 0, RoundingMode.DOWN).longValue();
- }
- public BalanceRecord preWithdraw(Long userId, BigDecimal amount) {
- UserBalance userBalance = userBalanceRepo.findById(userId).orElseThrow(new BusinessException("余额不足"));
- if (amount.compareTo(userBalance.getBalance()) > 0) {
- throw new BusinessException("余额不足");
- }
- BigDecimal minWithdrawAmount = sysConfigService.getBigDecimal("min_withdraw_amount");
- if (amount.compareTo(minWithdrawAmount) < 0) {
- throw new BusinessException("最小提现金额为" + minWithdrawAmount);
- }
- UserBankCard userBankCard = userBankCardRepo.findByUserId(userBalance.getUserId())
- .stream().findFirst().orElseThrow(new BusinessException("请先绑定银行卡"));
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().subtract(amount));
- userBalanceRepo.saveAndFlush(userBalance);
- return balanceRecordRepo.save(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(userBalance.getUserId())
- .amount(amount.negate())
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.WITHDRAW)
- .build());
- }
- @RedisLock(value = "'modifyBalance::'+#userId", behavior = RedisLock.Behavior.WAIT)
- public void modifyBalance(Long userId, BigDecimal amount, BalanceType type,
- String reason, boolean lock, String withdrawId) {
- UserBalance userBalance = userBalanceRepo.findById(userId).orElse(new UserBalance(userId));
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(amount));
- if (lock) {
- userBalance.setLockTime(LocalDateTime.now());
- userBalance.setLocked(true);
- userBalance.setLockReason(reason);
- }
- userBalanceRepo.saveAndFlush(userBalance);
- balanceRecordRepo.save(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(userId)
- .amount(amount)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(type)
- .remark(reason)
- .withdrawId(withdrawId)
- .build());
- }
- public void realtimeSettleOrder(Order order) {
- if (!sysConfigService.getBoolean("realtime_settle_order")) {
- return;
- }
- BalanceRecord record = balanceRecordRepo.findByOrderIdAndType(order.getId(), BalanceType.SELL);
- if (record != null) {
- log.info("此订单已结算 orderId={}", order.getId());
- return;
- }
- log.info("结算订单 orderId={}", order.getId());
- Asset asset = assetRepo.findById(order.getAssetId()).orElse(null);
- UserBalance userBalance = userBalanceRepo.findById(asset.getUserId())
- .orElse(new UserBalance(asset.getUserId()));
- BigDecimal amount = order.getTotalPrice()
- .subtract(order.getGasPrice())
- .multiply(BigDecimal.valueOf(100 - order.getRoyalties() - order.getServiceCharge()))
- .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(amount));
- userBalanceRepo.save(userBalance);
- balanceRecordRepo.save(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(asset.getUserId())
- .orderId(order.getId())
- .amount(amount)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.SELL)
- .build());
- }
- public void realtimeSettleOrder(DomainAsk domainAsk) {
- if (!sysConfigService.getBoolean("realtime_settle_order")) {
- return;
- }
- BalanceRecord record = balanceRecordRepo.findByOrderIdAndType(domainAsk.getId(), BalanceType.ASK);
- if (record != null) {
- log.info("此订单已结算 domainAskId={}", domainAsk.getId());
- return;
- }
- log.info("结算订单 domainAskId={}", domainAsk.getId());
- Asset asset = assetRepo.findById(domainAsk.getAssetId()).orElse(null);
- UserBalance userBalance = userBalanceRepo.findById(asset.getUserId())
- .orElse(new UserBalance(asset.getUserId()));
- BigDecimal amount = domainAsk.getPrice()
- // .subtract(BigDecimal.valueOf(1))
- .multiply(BigDecimal
- .valueOf(100 - domainAsk.getRoyalties() - domainAsk.getServiceCharge()))
- .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(amount));
- userBalanceRepo.save(userBalance);
- balanceRecordRepo.save(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(asset.getUserId())
- .orderId(domainAsk.getId())
- .amount(amount)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(BalanceType.ASK)
- .build());
- }
- public void addBalance(Long userId, BigDecimal amount, Long orderId, BalanceType type) {
- //用户冲余额
- UserBalance userBalance = userBalanceRepo.findByUserId(userId)
- .orElse(UserBalance.builder()
- .balance(BigDecimal.ZERO)
- .lastBalance(BigDecimal.ZERO)
- .userId(userId)
- .build());
- userBalance.setLastBalance(userBalance.getBalance());
- userBalance.setBalance(userBalance.getBalance().add(amount));
- userBalanceRepo.save(userBalance);
- log.info("拍卖冲用户余额{},¥{}", userId, amount);
- balanceRecordRepo.save(BalanceRecord.builder()
- .time(LocalDateTime.now())
- .userId(userId)
- .orderId(orderId)
- .amount(amount)
- .balance(userBalance.getBalance())
- .lastBalance(userBalance.getLastBalance())
- .type(type)
- .build());
- }
- public boolean checkBalance(Long userId, BigDecimal balance) {
- UserBalance userBalance = userBalanceRepo.findById(userId).orElse(new UserBalance(userId));
- return userBalance.getBalance().compareTo(balance) >= 0;
- }
- }
|