|
@@ -17,6 +17,7 @@ import org.dromara.common.core.exception.ServiceException;
|
|
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
import org.dromara.common.satoken.utils.LoginHelper;
|
|
import org.dromara.common.satoken.utils.LoginHelper;
|
|
|
|
|
+import org.dromara.main.config.WithdrawConfig;
|
|
|
import org.dromara.main.domain.CompanyAccountFlow;
|
|
import org.dromara.main.domain.CompanyAccountFlow;
|
|
|
import org.dromara.main.domain.PaymentConfig;
|
|
import org.dromara.main.domain.PaymentConfig;
|
|
|
import org.dromara.main.domain.Withdraw;
|
|
import org.dromara.main.domain.Withdraw;
|
|
@@ -37,6 +38,8 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
@@ -57,6 +60,7 @@ public class WithdrawServiceImpl implements IWithdrawService {
|
|
|
private final ISysTenantService tenantService;
|
|
private final ISysTenantService tenantService;
|
|
|
private final SysTenantMapper sysTenantMapper;
|
|
private final SysTenantMapper sysTenantMapper;
|
|
|
private final IPaymentConfigService paymentConfigService;
|
|
private final IPaymentConfigService paymentConfigService;
|
|
|
|
|
+ private final WithdrawConfig withdrawConfig;
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public WithdrawVo queryById(Long id) {
|
|
public WithdrawVo queryById(Long id) {
|
|
@@ -126,6 +130,14 @@ public class WithdrawServiceImpl implements IWithdrawService {
|
|
|
insertFlow(company.getId(), 2, amount, 1, availableBalance, availableBalance.subtract(amount), 5, withdraw.getId(), withdraw.getWithdrawNo(), "申请提现:" + withdraw.getWithdrawNo());
|
|
insertFlow(company.getId(), 2, amount, 1, availableBalance, availableBalance.subtract(amount), 5, withdraw.getId(), withdraw.getWithdrawNo(), "申请提现:" + withdraw.getWithdrawNo());
|
|
|
insertFlow(company.getId(), 1, amount, 3, withdrawingBalance, withdrawingBalance.add(amount), 5, withdraw.getId(), withdraw.getWithdrawNo(), "申请提现(冻结):" + withdraw.getWithdrawNo());
|
|
insertFlow(company.getId(), 1, amount, 3, withdrawingBalance, withdrawingBalance.add(amount), 5, withdraw.getId(), withdraw.getWithdrawNo(), "申请提现(冻结):" + withdraw.getWithdrawNo());
|
|
|
|
|
|
|
|
|
|
+ if (withdrawConfig.isAutoAudit() && shouldAutoAudit(company.getId(), amount)) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ auditAndTransfer(withdraw.getId(), "系统自动审核通过");
|
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
|
+ // 自动审核失败时保留待审核状态,转人工处理
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return withdraw.getId();
|
|
return withdraw.getId();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -147,8 +159,7 @@ public class WithdrawServiceImpl implements IWithdrawService {
|
|
|
withdrawMapper.updateById(withdraw);
|
|
withdrawMapper.updateById(withdraw);
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 联调阶段先跳过支付宝打款,直接模拟成功流水号,后续余额与状态流转保持不变。
|
|
|
|
|
- String tradeNo = generateMockTradeNo(withdraw);
|
|
|
|
|
|
|
+ String tradeNo = transferToAlipay(withdraw);
|
|
|
|
|
|
|
|
SysTenant tenant = sysTenantMapper.selectById(withdraw.getCompanyId());
|
|
SysTenant tenant = sysTenantMapper.selectById(withdraw.getCompanyId());
|
|
|
if (tenant == null) {
|
|
if (tenant == null) {
|
|
@@ -355,6 +366,48 @@ public class WithdrawServiceImpl implements IWithdrawService {
|
|
|
availableBalance.add(withdraw.getWithdrawAmount()), 7, withdraw.getId(), withdraw.getWithdrawNo(), remark);
|
|
availableBalance.add(withdraw.getWithdrawAmount()), 7, withdraw.getId(), withdraw.getWithdrawNo(), remark);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private boolean shouldAutoAudit(Long companyId, BigDecimal amount) {
|
|
|
|
|
+ WithdrawConfig.AutoAuditRule rule = withdrawConfig.getAutoAuditRule();
|
|
|
|
|
+ if (rule == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (amount.compareTo(defaultAmount(rule.getMaxAmount())) > 0) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ DailyLimit dailyLimit = checkDailyLimit(companyId);
|
|
|
|
|
+ Integer maxDailyCount = rule.getMaxDailyCount() == null ? 0 : rule.getMaxDailyCount();
|
|
|
|
|
+ if (maxDailyCount > 0 && dailyLimit.getCount() >= maxDailyCount) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ BigDecimal maxDailyAmount = defaultAmount(rule.getMaxDailyAmount());
|
|
|
|
|
+ BigDecimal totalAmount = dailyLimit.getAmount().add(amount);
|
|
|
|
|
+ return maxDailyAmount.compareTo(BigDecimal.ZERO) <= 0 || totalAmount.compareTo(maxDailyAmount) <= 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private DailyLimit checkDailyLimit(Long companyId) {
|
|
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
|
|
+ Date startOfDay = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
+ Date endOfDay = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
+
|
|
|
|
|
+ List<Withdraw> todayWithdraws = withdrawMapper.selectList(
|
|
|
|
|
+ Wrappers.<Withdraw>lambdaQuery()
|
|
|
|
|
+ .eq(Withdraw::getCompanyId, companyId)
|
|
|
|
|
+ .ge(Withdraw::getCreateTime, startOfDay)
|
|
|
|
|
+ .lt(Withdraw::getCreateTime, endOfDay)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ int count = todayWithdraws.size();
|
|
|
|
|
+ BigDecimal totalAmount = todayWithdraws.stream()
|
|
|
|
|
+ .map(Withdraw::getWithdrawAmount)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+
|
|
|
|
|
+ return new DailyLimit(count, totalAmount);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private String transferToAlipay(Withdraw withdraw) throws Exception {
|
|
private String transferToAlipay(Withdraw withdraw) throws Exception {
|
|
|
PaymentConfig config = paymentConfigService.getEnabledTransferConfig();
|
|
PaymentConfig config = paymentConfigService.getEnabledTransferConfig();
|
|
|
if (config == null) {
|
|
if (config == null) {
|
|
@@ -429,11 +482,25 @@ public class WithdrawServiceImpl implements IWithdrawService {
|
|
|
return "WD" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(4);
|
|
return "WD" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(4);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private String generateMockTradeNo(Withdraw withdraw) {
|
|
|
|
|
- return "MOCK_" + withdraw.getWithdrawNo();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private String defaultIfBlank(String value, String defaultValue) {
|
|
private String defaultIfBlank(String value, String defaultValue) {
|
|
|
return value == null || value.isBlank() ? defaultValue : value;
|
|
return value == null || value.isBlank() ? defaultValue : value;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ private static class DailyLimit {
|
|
|
|
|
+ private final int count;
|
|
|
|
|
+ private final BigDecimal amount;
|
|
|
|
|
+
|
|
|
|
|
+ private DailyLimit(int count, BigDecimal amount) {
|
|
|
|
|
+ this.count = count;
|
|
|
|
|
+ this.amount = amount;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public int getCount() {
|
|
|
|
|
+ return count;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public BigDecimal getAmount() {
|
|
|
|
|
+ return amount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|