Merge branch 'main' of http://8.155.172.147:3001/sion/monisuo
This commit is contained in:
@@ -24,7 +24,10 @@
|
|||||||
"Bash(git check-ignore:*)",
|
"Bash(git check-ignore:*)",
|
||||||
"Bash(git commit:*)",
|
"Bash(git commit:*)",
|
||||||
"Bash(git push:*)",
|
"Bash(git push:*)",
|
||||||
"Bash(git restore:*)"
|
"Bash(git restore:*)",
|
||||||
|
"Bash(ssh root@8.155.172.147 \"tail -100 /www/wwwroot/logs/app.log\")",
|
||||||
|
"Bash(mvn compile:*)",
|
||||||
|
"Bash(git checkout:*)"
|
||||||
],
|
],
|
||||||
"additionalDirectories": [
|
"additionalDirectories": [
|
||||||
"/Users/sion/Desktop/projects/monisuo/monisuo-admin/.git"
|
"/Users/sion/Desktop/projects/monisuo/monisuo-admin/.git"
|
||||||
|
|||||||
@@ -48,42 +48,6 @@ public class TokenFilter implements Filter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:钱包接口(用户充值前需要看到钱包地址)
|
|
||||||
if (uri.equals("/api/wallet/default")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取Token
|
|
||||||
String token = httpRequest.getHeader("Authorization");
|
|
||||||
if (token != null && token.startsWith("Bearer ")) {
|
|
||||||
token = token.substring(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token == null || token.isEmpty()) {
|
|
||||||
writeUnauthorized(httpResponse, "请先登录");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证Token
|
|
||||||
if (!JwtUtil.isValid(token)) {
|
|
||||||
writeUnauthorized(httpResponse, "Token已过期,请重新登录");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置用户上下文
|
|
||||||
UserContext context = new UserContext();
|
|
||||||
context.setUserId(JwtUtil.getUserId(token));
|
|
||||||
context.setUsername(JwtUtil.getUsername(token));
|
|
||||||
context.setType(JwtUtil.getType(token));
|
|
||||||
UserContext.set(context);
|
|
||||||
|
|
||||||
try {
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
} finally {
|
|
||||||
UserContext.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取Token
|
// 获取Token
|
||||||
String token = httpRequest.getHeader("Authorization");
|
String token = httpRequest.getHeader("Authorization");
|
||||||
if (token != null && token.startsWith("Bearer ")) {
|
if (token != null && token.startsWith("Bearer ")) {
|
||||||
|
|||||||
@@ -1,3 +1,112 @@
|
|||||||
|
package com.it.rattan.monisuo.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.it.rattan.monisuo.entity.AccountFund;
|
||||||
|
import com.it.rattan.monisuo.entity.ColdWallet;
|
||||||
|
import com.it.rattan.monisuo.entity.OrderFund;
|
||||||
|
import com.it.rattan.monisuo.entity.User;
|
||||||
|
import com.it.rattan.monisuo.mapper.AccountFundMapper;
|
||||||
|
import com.it.rattan.monisuo.mapper.OrderFundMapper;
|
||||||
|
import com.it.rattan.monisuo.mapper.UserMapper;
|
||||||
|
import com.it.rattan.monisuo.util.OrderNoUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充提服务
|
||||||
|
*
|
||||||
|
* 状态定义:
|
||||||
|
* 充值: 1=待付款, 2=待确认, 3=已完成, 4=已驳回, 5=已取消
|
||||||
|
* 提现: 1=待审批, 2=已完成, 3=已驳回, 4=已取消
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FundService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrderFundMapper orderFundMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AccountFundMapper accountFundMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AssetService assetService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ColdWalletService coldWalletService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请充值 - 关联默认冷钱包
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Map<String, Object> deposit(Long userId, BigDecimal amount, String remark) {
|
||||||
|
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
throw new RuntimeException("充值金额必须大于0");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = userMapper.selectById(userId);
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取默认冷钱包
|
||||||
|
ColdWallet wallet = coldWalletService.getDefaultWallet();
|
||||||
|
if (wallet == null) {
|
||||||
|
throw new RuntimeException("系统暂未配置充值地址");
|
||||||
|
}
|
||||||
|
|
||||||
|
OrderFund order = new OrderFund();
|
||||||
|
order.setOrderNo(OrderNoUtil.fundOrderNo());
|
||||||
|
order.setUserId(userId);
|
||||||
|
order.setUsername(user.getUsername());
|
||||||
|
order.setType(1); // 充值
|
||||||
|
order.setAmount(amount);
|
||||||
|
order.setStatus(1); // 待付款
|
||||||
|
order.setWalletId(wallet.getId());
|
||||||
|
order.setWalletAddress(wallet.getAddress());
|
||||||
|
order.setRemark(remark);
|
||||||
|
order.setCreateTime(LocalDateTime.now());
|
||||||
|
orderFundMapper.insert(order);
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("orderNo", order.getOrderNo());
|
||||||
|
result.put("amount", amount);
|
||||||
|
result.put("status", order.getStatus());
|
||||||
|
result.put("walletAddress", wallet.getAddress());
|
||||||
|
result.put("walletNetwork", wallet.getNetwork());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户确认已打款
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void confirmPay(Long userId, String orderNo) {
|
||||||
|
LambdaQueryWrapper<OrderFund> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(OrderFund::getUserId, userId)
|
||||||
|
.eq(OrderFund::getOrderNo, orderNo)
|
||||||
|
.eq(OrderFund::getType, 1) // 仅充值订单
|
||||||
|
.eq(OrderFund::getStatus, 1); // 仅待付款可确认
|
||||||
|
|
||||||
|
OrderFund order = orderFundMapper.selectOne(wrapper);
|
||||||
|
if (order == null) {
|
||||||
|
throw new RuntimeException("订单不存在或状态不可操作");
|
||||||
|
}
|
||||||
|
|
||||||
|
order.setStatus(2); // 待确认
|
||||||
|
order.setPayTime(LocalDateTime.now());
|
||||||
|
order.setUpdateTime(LocalDateTime.now());
|
||||||
|
orderFundMapper.updateById(order);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请提现 - 冻结余额
|
* 申请提现 - 冻结余额
|
||||||
*/
|
*/
|
||||||
@@ -17,14 +126,233 @@
|
|||||||
throw new RuntimeException("用户不存在");
|
throw new RuntimeException("用户不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:检查交易账户余额(提示)
|
// 检查并冻结余额
|
||||||
AccountTrade tradeAccount = assetService.getOrCreateTradeAccount(userId, "USDT");
|
|
||||||
if (tradeAccount.getQuantity().compareTo(BigDecimal.ZERO) > 0) {
|
|
||||||
throw new RuntimeException("交易账户有余额,请先划转到资金账户后再提现");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查并冻结资金账户余额
|
|
||||||
AccountFund fund = assetService.getOrCreateFundAccount(userId);
|
AccountFund fund = assetService.getOrCreateFundAccount(userId);
|
||||||
if (fund.getBalance().compareTo(amount) < 0) {
|
if (fund.getBalance().compareTo(amount) < 0) {
|
||||||
throw new RuntimeException("资金账户余额不足");
|
throw new RuntimeException("资金账户余额不足");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 冻结余额
|
||||||
|
fund.setBalance(fund.getBalance().subtract(amount));
|
||||||
|
fund.setFrozen(fund.getFrozen() != null ? fund.getFrozen().add(amount) : amount);
|
||||||
|
fund.setUpdateTime(LocalDateTime.now());
|
||||||
|
accountFundMapper.updateById(fund);
|
||||||
|
|
||||||
|
// 创建订单
|
||||||
|
OrderFund order = new OrderFund();
|
||||||
|
order.setOrderNo(OrderNoUtil.fundOrderNo());
|
||||||
|
order.setUserId(userId);
|
||||||
|
order.setUsername(user.getUsername());
|
||||||
|
order.setType(2); // 提现
|
||||||
|
order.setAmount(amount);
|
||||||
|
order.setStatus(1); // 待审批
|
||||||
|
order.setWalletAddress(withdrawAddress);
|
||||||
|
order.setWithdrawContact(withdrawContact);
|
||||||
|
order.setRemark(remark);
|
||||||
|
order.setCreateTime(LocalDateTime.now());
|
||||||
|
orderFundMapper.insert(order);
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("orderNo", order.getOrderNo());
|
||||||
|
result.put("amount", amount);
|
||||||
|
result.put("status", order.getStatus());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消订单 - 仅充值待付款状态可取消
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void cancel(Long userId, String orderNo) {
|
||||||
|
LambdaQueryWrapper<OrderFund> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(OrderFund::getUserId, userId)
|
||||||
|
.eq(OrderFund::getOrderNo, orderNo);
|
||||||
|
|
||||||
|
OrderFund order = orderFundMapper.selectOne(wrapper);
|
||||||
|
if (order == null) {
|
||||||
|
throw new RuntimeException("订单不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 充值订单仅待付款可取消
|
||||||
|
if (order.getType() == 1 && order.getStatus() != 1) {
|
||||||
|
throw new RuntimeException("当前状态不可取消");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提现订单仅待审批可取消,需要解冻余额
|
||||||
|
if (order.getType() == 2) {
|
||||||
|
if (order.getStatus() != 1) {
|
||||||
|
throw new RuntimeException("当前状态不可取消");
|
||||||
|
}
|
||||||
|
// 解冻余额
|
||||||
|
AccountFund fund = assetService.getOrCreateFundAccount(userId);
|
||||||
|
fund.setBalance(fund.getBalance().add(order.getAmount()));
|
||||||
|
fund.setFrozen(fund.getFrozen().subtract(order.getAmount()));
|
||||||
|
fund.setUpdateTime(LocalDateTime.now());
|
||||||
|
accountFundMapper.updateById(fund);
|
||||||
|
}
|
||||||
|
|
||||||
|
order.setStatus(5); // 已取消
|
||||||
|
order.setUpdateTime(LocalDateTime.now());
|
||||||
|
orderFundMapper.updateById(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取充提记录
|
||||||
|
*/
|
||||||
|
public IPage<OrderFund> getOrders(Long userId, Integer type, int pageNum, int pageSize) {
|
||||||
|
LambdaQueryWrapper<OrderFund> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(OrderFund::getUserId, userId);
|
||||||
|
if (type != null && type > 0) {
|
||||||
|
wrapper.eq(OrderFund::getType, type);
|
||||||
|
}
|
||||||
|
wrapper.orderByDesc(OrderFund::getCreateTime);
|
||||||
|
|
||||||
|
Page<OrderFund> page = new Page<>(pageNum, pageSize);
|
||||||
|
return orderFundMapper.selectPage(page, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待审批订单数量
|
||||||
|
*/
|
||||||
|
public int getPendingCount() {
|
||||||
|
// 充值待确认 + 提现待审批
|
||||||
|
LambdaQueryWrapper<OrderFund> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.and(w -> w.eq(OrderFund::getType, 1).eq(OrderFund::getStatus, 2))
|
||||||
|
.or(w -> w.eq(OrderFund::getType, 2).eq(OrderFund::getStatus, 1));
|
||||||
|
return Math.toIntExact(orderFundMapper.selectCount(wrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员审批
|
||||||
|
* 充值: 仅待确认(status=2)可审批
|
||||||
|
* 提现: 仅待审批(status=1)可审批
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void approve(Long adminId, String adminName, String orderNo, Integer status,
|
||||||
|
String rejectReason, String adminRemark) {
|
||||||
|
OrderFund order = orderFundMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<OrderFund>().eq(OrderFund::getOrderNo, orderNo));
|
||||||
|
|
||||||
|
if (order == null) {
|
||||||
|
throw new RuntimeException("订单不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 充值审批: 仅待确认可审批
|
||||||
|
if (order.getType() == 1 && order.getStatus() != 2) {
|
||||||
|
throw new RuntimeException("该充值订单不可审批,等待用户确认打款");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提现审批: 仅待审批可审批
|
||||||
|
if (order.getType() == 2 && order.getStatus() != 1) {
|
||||||
|
throw new RuntimeException("该提现订单已处理");
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountFund fund = assetService.getOrCreateFundAccount(order.getUserId());
|
||||||
|
|
||||||
|
if (status == 2) {
|
||||||
|
// 审批通过
|
||||||
|
if (order.getType() == 1) {
|
||||||
|
// 充值通过:增加余额
|
||||||
|
BigDecimal balanceBefore = fund.getBalance();
|
||||||
|
fund.setBalance(fund.getBalance().add(order.getAmount()));
|
||||||
|
fund.setTotalDeposit(fund.getTotalDeposit().add(order.getAmount()));
|
||||||
|
fund.setUpdateTime(LocalDateTime.now());
|
||||||
|
accountFundMapper.updateById(fund);
|
||||||
|
|
||||||
|
// 记录流水
|
||||||
|
assetService.createFlow(order.getUserId(), 1, order.getAmount(),
|
||||||
|
balanceBefore, fund.getBalance(), "USDT", orderNo, "充值");
|
||||||
|
} else {
|
||||||
|
// 提现通过:从冻结转为扣除,更新累计提现
|
||||||
|
if (fund.getFrozen().compareTo(order.getAmount()) < 0) {
|
||||||
|
throw new RuntimeException("冻结金额不足");
|
||||||
|
}
|
||||||
|
BigDecimal balanceBefore = fund.getBalance();
|
||||||
|
fund.setFrozen(fund.getFrozen().subtract(order.getAmount()));
|
||||||
|
fund.setTotalWithdraw(fund.getTotalWithdraw().add(order.getAmount()));
|
||||||
|
fund.setUpdateTime(LocalDateTime.now());
|
||||||
|
accountFundMapper.updateById(fund);
|
||||||
|
|
||||||
|
// 记录流水 (负数表示支出)
|
||||||
|
assetService.createFlow(order.getUserId(), 2, order.getAmount().negate(),
|
||||||
|
balanceBefore, fund.getBalance(), "USDT", orderNo, "提现");
|
||||||
|
}
|
||||||
|
|
||||||
|
order.setConfirmTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
} else if (status == 3) {
|
||||||
|
// 审批驳回
|
||||||
|
if (rejectReason == null || rejectReason.isEmpty()) {
|
||||||
|
throw new RuntimeException("请填写驳回原因");
|
||||||
|
}
|
||||||
|
order.setRejectReason(rejectReason);
|
||||||
|
|
||||||
|
if (order.getType() == 2) {
|
||||||
|
// 提现驳回:解冻金额退还
|
||||||
|
BigDecimal balanceBefore = fund.getBalance();
|
||||||
|
fund.setBalance(fund.getBalance().add(order.getAmount()));
|
||||||
|
fund.setFrozen(fund.getFrozen().subtract(order.getAmount()));
|
||||||
|
fund.setUpdateTime(LocalDateTime.now());
|
||||||
|
accountFundMapper.updateById(fund);
|
||||||
|
|
||||||
|
// 记录流水
|
||||||
|
assetService.createFlow(order.getUserId(), 2, order.getAmount(),
|
||||||
|
balanceBefore, fund.getBalance(), "USDT", orderNo, "提现驳回退还");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
order.setStatus(status);
|
||||||
|
order.setApproveAdminId(adminId);
|
||||||
|
order.setApproveAdminName(adminName);
|
||||||
|
order.setApproveTime(LocalDateTime.now());
|
||||||
|
order.setAdminRemark(adminRemark);
|
||||||
|
order.setUpdateTime(LocalDateTime.now());
|
||||||
|
orderFundMapper.updateById(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待审批订单列表
|
||||||
|
* 充值待确认(status=2) + 提现待审批(status=1)
|
||||||
|
*/
|
||||||
|
public IPage<OrderFund> getPendingOrders(Integer type, Integer status, int pageNum, int pageSize) {
|
||||||
|
LambdaQueryWrapper<OrderFund> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
|
if (type != null && type > 0) {
|
||||||
|
// 指定类型
|
||||||
|
wrapper.eq(OrderFund::getType, type);
|
||||||
|
if (type == 1) {
|
||||||
|
// 充值:待确认
|
||||||
|
wrapper.eq(OrderFund::getStatus, status != null ? status : 2);
|
||||||
|
} else {
|
||||||
|
// 提现:待审批
|
||||||
|
wrapper.eq(OrderFund::getStatus, status != null ? status : 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不指定类型:充值待确认 + 提现待审批
|
||||||
|
wrapper.and(w -> w.eq(OrderFund::getType, 1).eq(OrderFund::getStatus, 2))
|
||||||
|
.or(w -> w.eq(OrderFund::getType, 2).eq(OrderFund::getStatus, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.orderByAsc(OrderFund::getCreateTime);
|
||||||
|
|
||||||
|
Page<OrderFund> page = new Page<>(pageNum, pageSize);
|
||||||
|
return orderFundMapper.selectPage(page, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有充提订单(管理员)
|
||||||
|
*/
|
||||||
|
public IPage<OrderFund> getAllOrders(Integer type, Integer status, int pageNum, int pageSize) {
|
||||||
|
LambdaQueryWrapper<OrderFund> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (type != null && type > 0) {
|
||||||
|
wrapper.eq(OrderFund::getType, type);
|
||||||
|
}
|
||||||
|
if (status != null && status > 0) {
|
||||||
|
wrapper.eq(OrderFund::getStatus, status);
|
||||||
|
}
|
||||||
|
wrapper.orderByDesc(OrderFund::getCreateTime);
|
||||||
|
|
||||||
|
Page<OrderFund> page = new Page<>(pageNum, pageSize);
|
||||||
|
return orderFundMapper.selectPage(page, wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user