update 租赁系统1.1.0 新增充值,支付,提现 日志账本系统

This commit is contained in:
yyb
2025-12-23 10:27:50 +08:00
parent 4e23775014
commit bc2f76662c
18 changed files with 421 additions and 158 deletions

View File

@@ -0,0 +1,15 @@
package com.m2pool.lease.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/***
* 账本日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LedgerLog {
String value();
}

View File

@@ -0,0 +1,10 @@
package com.m2pool.lease.annotation;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LedgerLogParam {
String value() default "";
}

View File

@@ -0,0 +1,13 @@
package com.m2pool.lease.annotation;
import java.lang.annotation.*;
/***
* 账本日志地址标识注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LedgerLogTag {
String value() default "";
}

View File

@@ -0,0 +1,38 @@
package com.m2pool.lease.aspect;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 用户账本日志服务类
*/
@Service
public class LedgerLogService {
private static final String LOG_DIR = "/home/ubuntu/web/logs/ledger/";
private static final DateTimeFormatter MONTH_FORMAT = DateTimeFormatter.ofPattern("yyyyMM");
public void logOperation(String tag, String operation, String content) {
String month = LocalDate.now().format(MONTH_FORMAT);
String fileName = String.format("%s%s_%s.log", LOG_DIR, tag, month);
try {
Files.createDirectories(Paths.get(LOG_DIR));
String logEntry = String.format("[%s] %s: %s%n",
LocalDateTime.now(), operation, content);
Files.write(Paths.get(fileName),
logEntry.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE,
StandardOpenOption.APPEND);
} catch (IOException e) {
System.out.println("创建用户日志文件失败"+e.getMessage());
}
}
}

View File

@@ -0,0 +1,83 @@
package com.m2pool.lease.aspect;
import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.lease.annotation.EncryptedField;
import com.m2pool.lease.annotation.LedgerLog;
import com.m2pool.lease.annotation.LedgerLogParam;
import com.m2pool.lease.annotation.LedgerLogTag;
import com.m2pool.lease.dto.Result;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@Aspect
@Component
public class OperationLogAspect {
@Autowired
private LedgerLogService ledgerLogService;
@Pointcut("@annotation(com.m2pool.lease.annotation.LedgerLog)")
public void operationPointcut() {}
@AfterReturning(pointcut = "operationPointcut()", returning = "result")
public void afterOperation(JoinPoint joinPoint, Object result) {
// 获取当前登录用户
String address = "";
// 获取操作类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LedgerLog annotation = method.getAnnotation(LedgerLog.class);
//获取操作信息
StringBuilder ledgerLog = new StringBuilder();
for (Object arg : joinPoint.getArgs()) {
if (arg != null) {
Field[] fields = arg.getClass().getDeclaredFields();
for (Field field : fields) {
try {
if (field.isAnnotationPresent(LedgerLogParam.class)) {
field.setAccessible(true);
Object value = field.get(arg);
ledgerLog.append(field.getAnnotation(LedgerLogParam.class).value())
.append("=")
.append(value)
.append("; ");
}else if (field.isAnnotationPresent(LedgerLogTag.class)){
field.setAccessible(true);
address = (String) field.get(arg);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
if (result != null){
// 添加手续费值的特殊处理(手续不准在请求参数中传递,只能通过返回获取)
if (result instanceof Result) {
ledgerLog.append(((Result<?>) result).getData()).append("; ");
}
ledgerLog.append("\n结果:").append(result);
}
// 记录日志
ledgerLogService.logOperation(address, annotation.value(), ledgerLog.toString());
}
@AfterThrowing(pointcut = "operationPointcut()", throwing = "ex")
public void afterOperationError(JoinPoint joinPoint, Exception ex) {
// 获取当前登录用户
String username = SecurityUtils.getUsername();
String operation = joinPoint.getSignature().getName();
ledgerLogService.logOperation(username, operation, "操作失败: " + ex.getMessage());
}
}

View File

@@ -2,6 +2,7 @@ package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LedgerLog;
import com.m2pool.lease.dto.PageResult;
import com.m2pool.lease.dto.Result;
import com.m2pool.lease.dto.v2.PayWithdrawSellerRecordDto;
@@ -48,9 +49,10 @@ public class LeaseShopV2Controller {
return leaseShopService.getShopConfigV2(baseVo);
}
@LedgerLog(value = "卖家钱包--余额提现申请")
@Decrypt
@PostMapping("/withdrawBalanceForSeller")
@ApiOperation(value = "卖家店铺钱包余额提现")
@Decrypt
public Result<String> withdrawBalanceForSeller(@RequestBody BalanceVo balanceVo){
return leaseShopService.withdrawBalanceForSeller(balanceVo);
}

View File

@@ -3,6 +3,7 @@ package com.m2pool.lease.controller;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LedgerLog;
import com.m2pool.lease.dto.*;
import com.m2pool.lease.service.LeaseUserService;
import com.m2pool.lease.vo.*;
@@ -51,9 +52,10 @@ public class LeaseUserController {
}
@LedgerLog(value = "买家钱包--余额提现申请")
@Decrypt
@PostMapping("/withdrawBalance")
@ApiOperation(value = "申请余额提现")
@Decrypt
public Result<String> withdrawBalance(@RequestBody BalanceVo balanceVo){
return leaseUserService.withdrawBalance(balanceVo);
}

View File

@@ -3,6 +3,7 @@ package com.m2pool.lease.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.m2pool.lease.dto.*;
import com.m2pool.lease.dto.v2.ShopWalletInfoDto;
import com.m2pool.lease.entity.LeasePayRecordMessage;
import com.m2pool.lease.entity.LeaseShopConfig;
import org.apache.ibatis.annotations.Param;
@@ -61,4 +62,13 @@ public interface LeaseShopConfigMapper extends BaseMapper<LeaseShopConfig> {
* @return
*/
ShopWalletInfoDto getShopWalletInfo(@Param("shopId") Long shopId,@Param("address") String address,@Param("chain") String chain,@Param("coin") String coin);
/**
* 根据支付记录修改余额
* @param reocrdList 钱包信息
* @return 更新数量
*/
int updateBalance(@Param("list") List<LeasePayRecordMessage> reocrdList);
}

View File

@@ -3,6 +3,7 @@ package com.m2pool.lease.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.m2pool.lease.dto.ChainAndCoinDto;
import com.m2pool.lease.dto.UserWalletDataDto;
import com.m2pool.lease.entity.LeasePayRecordMessage;
import com.m2pool.lease.entity.LeaseUserWalletData;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -49,4 +50,12 @@ public interface LeaseUserWalletDataMapper extends BaseMapper<LeaseUserWalletDat
* @return 钱包信息
*/
List<LeaseUserWalletData> selectWalletByChainAndCoinAndUsername(@Param("list") Set<ChainAndCoinDto> chainAndCoinSet,@Param("username") String username);
/**
* 根据支付记录修改余额及冻结余额
* @param reocrdList 钱包信息
* @return 更新数量
*/
int updateBalanceAndBlockBalance(@Param("list") List<LeasePayRecordMessage> reocrdList);
}

View File

@@ -4,6 +4,8 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.lease.annotation.LedgerLog;
import com.m2pool.lease.annotation.LedgerLogParam;
import com.m2pool.lease.constant.RabbitmqConstant;
import com.m2pool.lease.entity.*;
import com.m2pool.lease.exception.PayRechargeException;
@@ -14,6 +16,9 @@ import com.m2pool.lease.utils.UuidGeneratorUtil;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -245,6 +250,7 @@ public class MessageReceiver {
* 余额充值 消费者 (正常流程一笔充值会有两个消息 2 充值中 1充值成功
* @param payRechargeReturnMessage
*/
@LedgerLog(value = "余额充值")
@RabbitListener(queues = RabbitmqConstant.PAY_RECHARGE_RETURN_QUEUE,containerFactory ="rabbitListenerContainerFactory")
@Transactional(rollbackFor = Exception.class)
public void listenerPayRechargeStatusQueueMessage(@Payload RabbitmqPayRechargeReturnMessage payRechargeReturnMessage) {
@@ -328,6 +334,7 @@ public class MessageReceiver {
* 余额提现 消费者
* @param payWithdrawReturnMessage
*/
@LedgerLog(value = "余额提现结果")
@RabbitListener(queues = RabbitmqConstant.PAY_WITHDRAW_RETURN_QUEUE,containerFactory ="rabbitListenerContainerFactory")
@Transactional(rollbackFor = Exception.class)
public void listenerPayWithdrawStatusQueueMessage(@Payload RabbitmqPayWithdrawReturnMessage payWithdrawReturnMessage) {
@@ -342,7 +349,8 @@ public class MessageReceiver {
LeaseShopConfig leaseShopConfig = leaseShopConfigMapper.selectOne(new LambdaQueryWrapper<LeaseShopConfig>()
.eq(LeaseShopConfig::getPayAddress, leasePayWithdrawMessage.getFromAddress())
.eq(LeaseShopConfig::getChain, leasePayWithdrawMessage.getFromChain())
.eq(LeaseShopConfig::getPayCoin, leasePayWithdrawMessage.getFromSymbol()));
.eq(LeaseShopConfig::getPayCoin, leasePayWithdrawMessage.getFromSymbol())
.eq(LeaseShopConfig::getDel, false));
if (leaseShopConfig != null){
//要修改的钱包状态为1 且提现的状态为1 则不处理
if (leasePayWithdrawMessage.getStatus() == 1 && payWithdrawReturnMessage.getStatus() == 1){
@@ -357,6 +365,8 @@ public class MessageReceiver {
leasePayWithdrawMessageMapper.updateById(LeasePayWithdrawMessage.builder()
.id(leasePayWithdrawMessage.getId())
.status(payWithdrawReturnMessage.getStatus())
.txHash(payWithdrawReturnMessage.getTx_hash())
.blockHeight(payWithdrawReturnMessage.getBlock_height())
.build());
//TODO 修改leaseShopConfig 金额(暂时不修改,提现申请的时候就修改了)
}
@@ -364,6 +374,12 @@ public class MessageReceiver {
}
/**
* 处理买家提现消息
* @param payWithdrawReturnMessage
* @param leasePayWithdrawMessageList
* @return
*/
public LeasePayWithdrawMessage handlerBuyerWithdraw(RabbitmqPayWithdrawReturnMessage payWithdrawReturnMessage,List<LeasePayWithdrawMessage> leasePayWithdrawMessageList){
LeasePayWithdrawMessage leasePayWithdrawMessage = leasePayWithdrawMessageList.get(0);
//获取对应的提现钱包
@@ -372,6 +388,7 @@ public class MessageReceiver {
.eq(LeaseUserWalletData::getFromChain, leasePayWithdrawMessage.getFromChain())
.eq(LeaseUserWalletData::getFromSymbol, leasePayWithdrawMessage.getFromSymbol())
.eq(LeaseUserWalletData::getDel,false));
//如果不存在,则说明本次提现申请的是卖方钱包提现
if (leaseUserWalletData == null){
return leasePayWithdrawMessage;
}
@@ -512,7 +529,6 @@ public class MessageReceiver {
}
}
////测试 开发环境 支付回调测试
//@RabbitListener(queues = RabbitmqConstant.PAY_AUTO_QUEUE,containerFactory ="rabbitListenerContainerFactory")
//@Transactional(rollbackFor = Exception.class)
@@ -537,22 +553,22 @@ public class MessageReceiver {
// rabbitTemplate.convertAndSend(RabbitmqConstant.PAY_AUTO_RETURN_QUEUE,rabbitmqPayAutoReturnMessage);
//}
//
////测试 开发环境 充值测试
//测试 开发环境 充值测试
//@RabbitListener(queues = RabbitmqConstant.PAY_RECHARGE_QUEUE,containerFactory ="rabbitListenerContainerFactory")
//@Transactional(rollbackFor = Exception.class)
//public void listenerPayRechargeQueueMessage(@Payload RabbitmqPayRechargeMessage payAutoReturnMessage) {
// String s = UuidGeneratorUtil.generateUuidWithoutHyphen();
// //发送充值消息
// RabbitmqPayRechargeReturnMessage rabbitmqPayRechargeReturnMessage = RabbitmqPayRechargeReturnMessage.builder()
// .queue_id(payAutoReturnMessage.getQueue_id())
// .status(2)
// .amount(BigDecimal.valueOf(20))
// .chain(payAutoReturnMessage.getChain())
// .symbol(payAutoReturnMessage.getSymbol())
// .address(payAutoReturnMessage.getAddress())
// .tx_hash(s)
// .build();
// rabbitTemplate.convertAndSend(RabbitmqConstant.PAY_RECHARGE_RETURN_QUEUE,rabbitmqPayRechargeReturnMessage);
// ////发送充值消息
// //RabbitmqPayRechargeReturnMessage rabbitmqPayRechargeReturnMessage = RabbitmqPayRechargeReturnMessage.builder()
// // .queue_id(payAutoReturnMessage.getQueue_id())
// // .status(2)
// // .amount(BigDecimal.valueOf(20))
// // .chain(payAutoReturnMessage.getChain())
// // .symbol(payAutoReturnMessage.getSymbol())
// // .address(payAutoReturnMessage.getAddress())
// // .tx_hash(s)
// // .build();
// //rabbitTemplate.convertAndSend(RabbitmqConstant.PAY_RECHARGE_RETURN_QUEUE,rabbitmqPayRechargeReturnMessage);
//
//
// //发送充值消息
@@ -567,8 +583,9 @@ public class MessageReceiver {
// .build();
// rabbitTemplate.convertAndSend(RabbitmqConstant.PAY_RECHARGE_RETURN_QUEUE,rabbitmqPayRechargeReturnMessage1);
//}
//
////提现
//提现
//@RabbitListener(queues = RabbitmqConstant.PAY_WITHDRAW_QUEUE,containerFactory ="rabbitListenerContainerFactory")
//@Transactional(rollbackFor = Exception.class)
//public void listenerWithdrawQueueMessage(@Payload RabbitmqPayWithdrawMessage payAutoReturnMessage) {
@@ -579,6 +596,7 @@ public class MessageReceiver {
// .amount(payAutoReturnMessage.getAmount())
// .chain(payAutoReturnMessage.getChain())
// .symbol(payAutoReturnMessage.getSymbol())
// .from_address(payAutoReturnMessage.getFrom_address())
// .tx_hash(UuidGeneratorUtil.generateUuidWithoutHyphen())
// .fee(payAutoReturnMessage.getFee())
// .build();

View File

@@ -1,5 +1,7 @@
package com.m2pool.lease.mq.message;
import com.m2pool.lease.annotation.LedgerLogParam;
import com.m2pool.lease.annotation.LedgerLogTag;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -20,44 +22,50 @@ public class RabbitmqPayRechargeReturnMessage {
/**
* 消息ID
*/
@LedgerLogParam(value = "消息ID")
private String queue_id;
/**
* 充值地址
*/
@LedgerLogTag(value = "充值地址")
private String address;
/**
* 来源地址(用户自己的钱包)
*/
@LedgerLogParam(value = "地址")
private String fromAddress;
/**
* 充值是否成功
*/
@LedgerLogParam(value = "充值结果")
private Integer status;
/**
* 链名称
*/
@LedgerLogParam(value = "")
private String chain;
/**
* 币种
*/
@LedgerLogParam(value = "币种")
private String symbol;
/**
* 充值金额
*/
@LedgerLogParam(value = "充值金额")
private BigDecimal amount;
/**
* 交易ID
*/
@LedgerLogParam(value = "交易ID")
private String tx_hash;
/**

View File

@@ -1,5 +1,7 @@
package com.m2pool.lease.mq.message;
import com.m2pool.lease.annotation.LedgerLogParam;
import com.m2pool.lease.annotation.LedgerLogTag;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -20,39 +22,46 @@ public class RabbitmqPayWithdrawReturnMessage {
/**
* 消息ID
*/
@LedgerLogParam(value = "消息ID")
private String queue_id;
/**
* 链名称
*/
@LedgerLogParam(value = "")
private String chain;
/**
* 币种
*/
@LedgerLogParam(value = "币种")
private String symbol;
/**
* 提现结果
*/
@LedgerLogParam(value = "提现结果")
private Integer status;
/**
* 提现金额
*/
@LedgerLogParam(value = "提现金额")
private BigDecimal amount;
/**
* 手续费
*/
@LedgerLogParam(value = "手续费")
private BigDecimal fee;
/**
* 交易hash
*/
@LedgerLogParam(value = "交易hash")
private String tx_hash;
/**
@@ -60,11 +69,12 @@ public class RabbitmqPayWithdrawReturnMessage {
*/
private Long block_height;
///**
// * 来源地址
// */
//private String from_address;
//
/**
* 来源地址
*/
@LedgerLogTag(value = "来源地址")
private String from_address;
///**
// * 收款地址
// */

View File

@@ -333,13 +333,13 @@ public class LeaseShopServiceImpl extends ServiceImpl<LeaseShopMapper, LeaseShop
List<String> payCoinsList = new ArrayList<>(Arrays.asList(shopConfigVo.getPayCoin().split(",")));
LeaseShopConfig configList = leaseShopConfigMapper.selectOne(new LambdaQueryWrapper<LeaseShopConfig>()
.eq(LeaseShopConfig::getShopId, leaseShop.getId())
.eq(LeaseShopConfig::getPayAddress, shopConfigVo.getPayAddress())
.eq(LeaseShopConfig::getPayCoin, shopConfigVo.getPayCoin())
.eq(LeaseShopConfig::getChain, shopConfigVo.getChain())
.eq(LeaseShopConfig::getDel, false)
);
if (configList != null){
return Result.fail("绑定钱包失败!已存在" + shopConfigVo.getChain()+""+ shopConfigVo.getPayCoin()+ "币种钱包");
return Result.fail("绑定"+shopConfigVo.getPayAddress()+"钱包失败!" + shopConfigVo.getChain()+""+ shopConfigVo.getPayCoin()+ "币种钱包,已被绑定");
}
//获取币种图标
@@ -669,9 +669,9 @@ public class LeaseShopServiceImpl extends ServiceImpl<LeaseShopMapper, LeaseShop
try {
//发送提现消息
rabbitTemplate.convertAndSend(PAY_WITHDRAW_QUEUE,message);
return Result.success("提现申请成功");
return Result.success("手续费=" + serviceCharge.toString() + ";消息ID=" + queueId,"提现申请成功");
} catch (Exception e) {
throw new PaymentException(("提现失败,失败原因"+e.getMessage()));
throw new PaymentException("提现失败,失败原因"+e.getMessage());
}
}
throw new PaymentException("提现失败,余额已变化,请重新提现!");
@@ -683,10 +683,19 @@ public class LeaseShopServiceImpl extends ServiceImpl<LeaseShopMapper, LeaseShop
if ( !WalletRuleCheckUtils.checkAddress(shopWalletInfoVo.getChain(),shopWalletInfoVo.getPayAddress())){
return Result.fail("提现地址格式不符合"+shopWalletInfoVo.getChain()+"节点");
}
//LeaseShopConfig byId = leaseShopConfigService.getById(shopWalletInfoVo.getId());
//if (byId.getBalance().compareTo(BigDecimal.ZERO) > 0){
// return Result.fail("钱包地址余额不为0,请先提现,否则会造成财产丢失");
//}
LeaseShopConfig byId = leaseShopConfigService.getById(shopWalletInfoVo.getId());
if (byId.getBalance().compareTo(BigDecimal.ZERO) > 0){
return Result.fail("钱包地址余额不为0,请先提现,否则会造成财产丢失");
}
LeaseShopConfig leaseShopConfig = leaseShopConfigMapper.selectOne(new LambdaQueryWrapper<LeaseShopConfig>()
.eq(LeaseShopConfig::getPayAddress, shopWalletInfoVo.getPayAddress())
.eq(LeaseShopConfig::getChain, shopWalletInfoVo.getChain())
.eq(LeaseShopConfig::getPayCoin, byId.getPayCoin())
.eq(LeaseShopConfig::getDel, false)
);
if (leaseShopConfig != null){
return Result.fail("修改失败,该钱包地址下链和币种已被绑定,请重新输入地址或先解绑后重新绑定");
}
boolean b = leaseShopConfigService.updateById(LeaseShopConfig.builder()
.id(shopWalletInfoVo.getId())
.payAddress(shopWalletInfoVo.getPayAddress())

View File

@@ -371,10 +371,9 @@ public class LeaseUserServiceImpl extends ServiceImpl<LeaseUserMapper, LeaseUser
try {
//发送 提现 消息
rabbitTemplate.convertAndSend(PAY_WITHDRAW_QUEUE,message);
System.out.println("发送提现消息成功"+queueId);
return Result.success("提现申请成功");
return Result.success("手续费=" + serviceCharge.toString() + ";消息ID=" + queueId,"提现申请成功");
} catch (Exception e) {
throw new PaymentException(("提现失败,失败原因"+e.getMessage()));
throw new PaymentException("提现失败,失败原因"+e.getMessage());
}
}
throw new PaymentException("提现失败,冻结金额已变化,请重新提现!");

View File

@@ -4,6 +4,7 @@ import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.lease.aspect.LedgerLogService;
import com.m2pool.lease.constant.PowerUnit;
import com.m2pool.lease.dto.*;
import com.m2pool.lease.dto.v2.PurchasedMachineListDto;
@@ -81,7 +82,8 @@ public class OrderAndPayTask {
private LeaseOrderMiningMapper leaseOrderMiningMapper;
@Resource
private LeaseMachineMapper leaseMachineMapper;
@Resource
private LedgerLogService ledgerLogService;
/**
* 检查钱包半年内是否有 支付,充值,提现操作
@@ -154,7 +156,7 @@ public class OrderAndPayTask {
//本次全部完成的订单id 集合
List<Long> orderComplete = new ArrayList<>();
//本次部分已完成订单详情id + 机器id 集合
//本次部分已完成订单详情id + 机 集合
List<Long> itemCompleteIds = new ArrayList<>();
List<LeaseMachine> completeMachines = new ArrayList<>();
@@ -204,7 +206,7 @@ public class OrderAndPayTask {
Map<Long, List<LeaseOrderItem>> userMapItem = needPayInfos.stream()
.collect(Collectors.groupingBy(LeaseOrderItem::getOrderId));
List<RabbitmqPayAutoMessage> rabbitmqPayAutoMessages = new ArrayList<>();
List<LeasePayRecordMessageInfo> recordMessageInfoList = new ArrayList<>();
List<LeaseOrderItem> saleIngList = new ArrayList<>();
// 按照订单分组
userMapItem.forEach((orderId, items) -> {
@@ -213,46 +215,52 @@ public class OrderAndPayTask {
//因为同一个订单的queueId相同所以这里直接使用订单id
LeaseOrderInfo orderInfo = queueIdMap.get(orderId);
//买方信息
RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
.queue_id(orderInfo.getOrderNumber())
.order_id(String.valueOf(orderId))
.shopId(leaseOrderItem.getShopId())
.chain(leaseOrderItem.getChain())
.symbol(leaseOrderItem.getSymbol())
.fee(orderInfo.getFee())
.userId(leaseOrderItem.getUserId())
.from_address(leaseOrderItem.getFromAddress())
.to_address(leaseOrderItem.getAddress())
LeasePayRecordMessageInfo build = LeasePayRecordMessageInfo.builder()
.orderId(String.valueOf(orderId))
.orderNumber(orderInfo.getOrderNumber())
.queueId(orderInfo.getOrderNumber())
.fromAddress(leaseOrderItem.getFromAddress())
.toAddress(leaseOrderItem.getAddress())
.amount(BigDecimal.ZERO)
.blockAmount(BigDecimal.ZERO)
.realAmount(BigDecimal.ZERO)
.needAmount(BigDecimal.ZERO)
.timestamp(timestamp)
.sign(HashUtils.sha256(timestamp))
.blockAmount(BigDecimal.ZERO)
.fromChain(leaseOrderItem.getChain())
.fromSymbol(leaseOrderItem.getSymbol())
.shopId(leaseOrderItem.getShopId())
.userId(leaseOrderItem.getUserId())
.toChain(leaseOrderItem.getChain())
.toSymbol(leaseOrderItem.getSymbol())
.build();
for (LeaseOrderItem item : items) {
BigDecimal amount = orderItemToPriceMap.get(item.getId());
BigDecimal realPayAmount = amount== null ? BigDecimal.ZERO : amount;
//设置理论支付金额 和 冻结金额 和 已支付理论金额 (冻结金额 = 理论支付金额 = 已支付理论金额)
build.setNeedAmount(build.getNeedAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
build.setBlockAmount(build.getBlockAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
BigDecimal realAmount = orderItemToPriceMap.get(item.getId());
BigDecimal realPayAmount = realAmount== null ? BigDecimal.ZERO : realAmount;
//已支付金额 和实际待支付金额
item.setAlreadyPayAmount(item.getAlreadyPayAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
//设置待支付真实金额
item.setSettlePayRealAmount(item.getSettlePayRealAmount().add(realPayAmount));
// mq消息真实支付金额
build.setAmount(build.getAmount().add(realPayAmount));
//设置理论支付金额 和 冻结金额 额 (冻结金额 = 理论支付金额
build.setBlockAmount(build.getBlockAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
build.setAmount(build.getAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
// 实际支付金额 + 理论实际应支付金额
build.setRealAmount(build.getRealAmount().add(realPayAmount));
build.setNeedAmount(build.getNeedAmount().add(realPayAmount));
saleIngList.add(item);
}
if (build.getAmount().compareTo(BigDecimal.ZERO) > 0){
rabbitmqPayAutoMessages.add(build);
}
//实际支付金额即使为0也要记录
recordMessageInfoList.add(build);
//实际支付不为0才记录
//if (build.getRealAmount().compareTo(BigDecimal.ZERO) > 0){
// recordMessageInfoList.add(build);
//}
});
//修改订单支付金额等相关信息
leaseOrderItemService.updateBatchById(saleIngList);
//保存支付信息到支付记录表中
saveMqMessageToDB(rabbitmqPayAutoMessages);
if (!recordMessageInfoList.isEmpty()){
leasePayRecordMessageInfoService.saveBatch(recordMessageInfoList);
}
}
//2.处理完成的订单 (订单部分完成)
if(!itemCompleteIds.isEmpty()){
@@ -387,43 +395,10 @@ public class OrderAndPayTask {
public void handlerOrderAllComplete(List<Long> orderIds){
//修改状态为已完成
leaseOrderInfoMapper.update(LeaseOrderInfo.builder().status(8).build(), new LambdaQueryWrapper<LeaseOrderInfo>().in(LeaseOrderInfo::getId, orderIds));
//发送支付消息
//老版本:发送支付消息
sendMessageToMq(orderIds);
}
/**
* 保存支付消息到支付记录表中
* @param rabbitmqPayAutoMessages
*/
public void saveMqMessageToDB( List<RabbitmqPayAutoMessage> rabbitmqPayAutoMessages){
if (!rabbitmqPayAutoMessages.isEmpty()){
List<LeasePayRecordMessageInfo> collect = new ArrayList<>();
for (RabbitmqPayAutoMessage rabbitmqPayAutoMessage : rabbitmqPayAutoMessages) {
collect.add( LeasePayRecordMessageInfo.builder()
.orderId(rabbitmqPayAutoMessage.getOrder_id())
.orderNumber(rabbitmqPayAutoMessage.getQueue_id())
.queueId(rabbitmqPayAutoMessage.getQueue_id())
.fromAddress(rabbitmqPayAutoMessage.getFrom_address())
.toAddress(rabbitmqPayAutoMessage.getTo_address())
.amount(rabbitmqPayAutoMessage.getNeedAmount())
.realAmount(rabbitmqPayAutoMessage.getAmount())
.needAmount(rabbitmqPayAutoMessage.getAmount())
.fromChain(rabbitmqPayAutoMessage.getChain())
.fromSymbol(rabbitmqPayAutoMessage.getSymbol())
.blockAmount(rabbitmqPayAutoMessage.getBlockAmount())
.shopId(rabbitmqPayAutoMessage.getShopId())
.userId(rabbitmqPayAutoMessage.getUserId())
.toChain(rabbitmqPayAutoMessage.getChain())
.toSymbol(rabbitmqPayAutoMessage.getSymbol())
.build());
}
leasePayRecordMessageInfoService.saveBatch(collect);
}
}
/**
* 处理订单部分完成
* @param itemIds 已完成订单项id
@@ -496,36 +471,36 @@ public class OrderAndPayTask {
//3.筛选出租期到期的商品
List<LeaseOrderItem> expireProductList = new ArrayList<>();
List<RabbitmqPayAutoMessage> rabbitmqPayAutoMessages = new ArrayList<>();
List<LeasePayRecordMessageInfo> recordMessageInfoList = new ArrayList<>();
Map<Long,Boolean> orderInfoIdAndIsComplete = new HashMap<>();
List<LeaseOrderItem> saleIngList = new ArrayList<>();
// 按照订单分组
userMapItem.forEach((orderId, items) -> {
LeaseOrderItem leaseOrderItem = items.get(0);
List<LeaseOrderItem> expire = new ArrayList<>();
long timestamp = System.currentTimeMillis()/1000;
//因为同一个订单的queueId相同所以这里直接使用订单id
LeaseOrderInfo orderInfo = queueIdMap.get(leaseOrderItem.getOrderId());
String queueId =orderInfo.getOrderNumber();
//买方信息
RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
.queue_id(queueId)
.order_id(String.valueOf(orderId))
.shopId(leaseOrderItem.getShopId())
.chain(leaseOrderItem.getChain())
.symbol(leaseOrderItem.getSymbol())
.fee(orderInfo.getFee())
.userId(leaseOrderItem.getUserId())
.from_address(leaseOrderItem.getFromAddress())
.to_address(leaseOrderItem.getAddress())
LeasePayRecordMessageInfo build = LeasePayRecordMessageInfo.builder()
.orderId(String.valueOf(orderId))
.orderNumber(orderInfo.getOrderNumber())
.queueId(orderInfo.getOrderNumber())
.fromAddress(leaseOrderItem.getFromAddress())
.toAddress(leaseOrderItem.getAddress())
.amount(BigDecimal.ZERO)
.blockAmount(BigDecimal.ZERO)
.realAmount(BigDecimal.ZERO)
.needAmount(BigDecimal.ZERO)
.timestamp(timestamp)
.sign(HashUtils.sha256(timestamp))
.blockAmount(BigDecimal.ZERO)
.fromChain(leaseOrderItem.getChain())
.fromSymbol(leaseOrderItem.getSymbol())
.shopId(leaseOrderItem.getShopId())
.userId(leaseOrderItem.getUserId())
.toChain(leaseOrderItem.getChain())
.toSymbol(leaseOrderItem.getSymbol())
.build();
for (LeaseOrderItem item : items) {
for (LeaseOrderItem item : items) {
orderInfoIdAndIsComplete.putIfAbsent(item.getOrderId(), true);
LocalDateTime expireTime = item.getCreateTime().plusDays(1).toLocalDate().atStartOfDay().plusDays(item.getLeaseTime());
//开发环境
@@ -540,7 +515,7 @@ public class OrderAndPayTask {
String key = item.getUser() + "-" + item.getMiner();
LeaseProductMachine machine = idAndMachineMap.get(item.getProductMachineId());
ProductMachineDto productMachineDto = machineDtoMap.get(key);
build.setNeedAmount(build.getNeedAmount().add(item.getPrice()));
build.setAmount(build.getAmount().add(item.getPrice()));
build.setBlockAmount(build.getBlockAmount().add(item.getPrice()));
if (productMachineDto != null){
//理论算力
@@ -555,11 +530,13 @@ public class OrderAndPayTask {
if (divide.compareTo(BigDecimal.valueOf(0.05)) > 0){
BigDecimal add = item.getPrice().multiply(BigDecimal.ONE.subtract(divide));
item.setSettlePayRealAmount(item.getSettlePayRealAmount().add(add));
build.setAmount(build.getAmount().add(add));
build.setRealAmount(build.getRealAmount().add(add));
build.setNeedAmount(build.getNeedAmount().add(add));
}else{
BigDecimal add = item.getPrice();
item.setSettlePayRealAmount(item.getSettlePayRealAmount().add(add));
build.setAmount(build.getAmount().add(add));
build.setRealAmount(build.getRealAmount().add(add));
build.setNeedAmount(build.getNeedAmount().add(add));
}
}
item.setAlreadyPayAmount(item.getAlreadyPayAmount().add(item.getPrice()));
@@ -634,12 +611,18 @@ public class OrderAndPayTask {
//});
//build.setTransactions(sellerPayInfoMessages);
if (build.getAmount().compareTo(BigDecimal.ZERO) > 0){
rabbitmqPayAutoMessages.add(build);
recordMessageInfoList.add(build);
}
expireProductList.addAll(expire);
});
//4.租约到期相关信息修改
//4.保存支付消息到支付记录表中
if (!recordMessageInfoList.isEmpty()){
leasePayRecordMessageInfoService.saveBatch(recordMessageInfoList);
}
//5.租约到期相关信息修改
if (!expireProductList.isEmpty()){
List<Long> itemIds = new ArrayList<>();
List<Long> machineIds = new ArrayList<>();
@@ -647,13 +630,13 @@ public class OrderAndPayTask {
itemIds.add(leaseOrderItem.getId());
machineIds.add(leaseOrderItem.getProductMachineId());
}
//4.1 修改订单详情表中状态为 0 租约已过期
//5.1 修改订单详情表中状态为 0 租约已过期
leaseOrderItemMapper.update(LeaseOrderItem.builder().status(0).build(), new LambdaUpdateWrapper<LeaseOrderItem>()
.in(LeaseOrderItem::getId, itemIds));
//4.2 修改商品库存矿机表 矿机状态为 0 未售出
//5.2 修改商品库存矿机表 矿机状态为 0 未售出
leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(), new LambdaUpdateWrapper<LeaseProductMachine>()
.in(LeaseProductMachine::getId, machineIds));
//4.3 修改用户已购矿机表状态为 1 套餐已过期
//5.3 修改用户已购矿机表状态为 1 套餐已过期
List<LeaseUserOwnedProduct> list = leaseUserOwnedProductService.list(new LambdaQueryWrapper<LeaseUserOwnedProduct>()
.select(LeaseUserOwnedProduct::getId,LeaseUserOwnedProduct::getSettleIncome,LeaseUserOwnedProduct::getCurrentIncome).in(LeaseUserOwnedProduct::getProductMachineId, machineIds));
List<LeaseUserOwnedProduct> collect = list.stream().map(item -> {
@@ -665,7 +648,7 @@ public class OrderAndPayTask {
}).collect(Collectors.toList());
leaseUserOwnedProductService.updateBatchById(collect);
//4.4 矿机对应商品 销售量修改
//5.4 矿机对应商品 销售量修改
//Map<Long, Long> productIdAndCountMap = expireProductList.stream().collect(Collectors.groupingBy(LeaseOrderItem::getProductId, Collectors.counting()));
//Set<Long> longs = productIdAndCountMap.keySet();
//List<LeaseProduct> leaseProducts = leaseProductService.list(new LambdaQueryWrapper<LeaseProduct>().in(LeaseProduct::getId, longs));
@@ -674,7 +657,7 @@ public class OrderAndPayTask {
//});
//leaseProductService.updateBatchById(leaseProducts);
//4.5 找到详情表所有状态为0 租约已过期 并且订单info表订单状态为7 进行中的订单 并改为状态8 订单已完成 并且发送支付消息
//5.5 找到详情表所有状态为0 租约已过期 并且订单info表订单状态为7 进行中的订单 并改为状态8 订单已完成 并且发送支付消息
List<Long> orderIds = orderInfoIdAndIsComplete.entrySet().stream()
.filter(entry -> Boolean.TRUE.equals(entry.getValue()))
.map(Map.Entry::getKey)
@@ -687,11 +670,9 @@ public class OrderAndPayTask {
}
}
//5.正在售出中矿机已支付金额
//6.正在售出中矿机已支付金额
leaseOrderItemService.updateBatchById(saleIngList);
//6.保存支付消息到支付记录表中
saveMqMessageToDB(rabbitmqPayAutoMessages);
}
/**
@@ -738,34 +719,30 @@ public class OrderAndPayTask {
public void sendMessageToMq(List<Long> orderIds){
List<LeasePayRecordMessageInfo> leasePayRecordMessages = leasePayRecordMessageInfoService.list(new LambdaQueryWrapper<LeasePayRecordMessageInfo>()
.in(LeasePayRecordMessageInfo::getOrderId, orderIds));
Map<String, BigDecimal> feeMap = getFee(orderIds);
//Map<String, BigDecimal> feeMap = getFee(orderIds);
Map<String, List<LeasePayRecordMessageInfo>> collect = leasePayRecordMessages.stream()
.collect(Collectors.groupingBy(LeasePayRecordMessageInfo::getOrderId));
List<LeasePayRecordMessage> reocrdList = new ArrayList<>();
//遍历按订单id分组后的map
collect.forEach((orderId, payRecordMessagesList) -> {
long timestamp = System.currentTimeMillis()/1000;
LeasePayRecordMessageInfo initForm = payRecordMessagesList.get(0);
RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
.queue_id(initForm.getQueueId())
.chain(initForm.getFromChain())
.symbol(initForm.getFromSymbol())
.from_address(initForm.getFromAddress())
.to_address(initForm.getToAddress())
.fee(feeMap.get(orderId))
.amount(BigDecimal.ZERO)
.blockAmount(BigDecimal.ZERO)
.needAmount(BigDecimal.ZERO)
.timestamp(timestamp)
.sign(HashUtils.sha256(timestamp))
.build();
//long timestamp = System.currentTimeMillis()/1000;
//RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
// .queue_id(initForm.getQueueId())
// .chain(initForm.getFromChain())
// .symbol(initForm.getFromSymbol())
// .from_address(initForm.getFromAddress())
// .to_address(initForm.getToAddress())
// .fee(feeMap.get(orderId))
// .amount(BigDecimal.ZERO)
// .blockAmount(BigDecimal.ZERO)
// .needAmount(BigDecimal.ZERO)
// .timestamp(timestamp)
// .sign(HashUtils.sha256(timestamp))
// .build();
for (LeasePayRecordMessageInfo leasePayRecordMessage : payRecordMessagesList) {
build.setAmount(build.getAmount().add(leasePayRecordMessage.getRealAmount()));
build.setBlockAmount(build.getBlockAmount().add(leasePayRecordMessage.getBlockAmount()));
build.setNeedAmount(build.getNeedAmount().add(leasePayRecordMessage.getNeedAmount()));
}
LeasePayRecordMessage build1 = LeasePayRecordMessage.builder()
LeasePayRecordMessage build = LeasePayRecordMessage.builder()
.queueId(initForm.getQueueId())
.fromAddress(initForm.getFromAddress())
.toAddress(initForm.getToAddress())
@@ -773,17 +750,27 @@ public class OrderAndPayTask {
.orderId(orderId)
.shopId(initForm.getShopId())
.userId(initForm.getUserId())
.blockAmount(build.getBlockAmount())
.amount(build.getAmount())
.realAmount(build.getAmount())
.needAmount(build.getNeedAmount())
.blockAmount(BigDecimal.ZERO)
.amount(BigDecimal.ZERO)
.realAmount(BigDecimal.ZERO)
.needAmount(BigDecimal.ZERO)
.fromSymbol(initForm.getFromSymbol())
.fromChain(initForm.getFromChain())
.toSymbol(initForm.getToSymbol())
.toChain(initForm.getToChain())
.build();
reocrdList.add(build1);
for (LeasePayRecordMessageInfo leasePayRecordMessage : payRecordMessagesList) {
build.setAmount(build.getAmount().add(leasePayRecordMessage.getAmount()));
build.setBlockAmount(build.getBlockAmount().add(leasePayRecordMessage.getBlockAmount()));
//现在可以删除NeedAmount这个字段了.新版本不存在需支付真实金额和实际支付真实金额不同的情况
build.setNeedAmount(build.getNeedAmount().add(leasePayRecordMessage.getNeedAmount()));
build.setRealAmount(build.getRealAmount().add(leasePayRecordMessage.getRealAmount()));
}
reocrdList.add(build);
//旧版本
//订单全部完成后不再需要发送支付信息,直接从买家钱包转账到卖家钱包
//try {
// rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build);
//}catch (Exception e){
@@ -793,8 +780,34 @@ public class OrderAndPayTask {
//}finally {
// reocrdList.add(build1);
//}
//新版本:买家钱包 冻结余额和余额减少 卖家钱包余额增加
});
leasePayRecordMessageService.saveBatch(reocrdList);
int buyerUpdate = leaseUserWalletDataMapper.updateBalanceAndBlockBalance(reocrdList);
int sellerUpdate = leaseShopConfigMapper.updateBalance(reocrdList);
if (buyerUpdate > 0 && sellerUpdate > 0){
for (LeasePayRecordMessage item : reocrdList) {
String buyerInfo = "订单号:" + item.getOrderNumber() +
"理论支付金额:" + item.getAmount() +
"实际支付金额:" + item.getRealAmount()+
"收款地址:" + item.getToAddress()+
"支付链:" + item.getFromChain()+
"支付币种" + item.getFromSymbol();
String sellerInfo = "订单号:" + item.getOrderNumber() +
"收款金额:" + item.getRealAmount()+
"支付地址:" + item.getFromAddress()+
"支付链:" + item.getFromChain()+
"支付币种" + item.getFromSymbol() ;
ledgerLogService.logOperation(item.getFromAddress(), "支付(付款)", buyerInfo);
ledgerLogService.logOperation(item.getToAddress(), "支付(收款)",sellerInfo);
}
}
}
@@ -815,10 +828,10 @@ public class OrderAndPayTask {
/**
* 一些校验失败的支付消息需要重新发送
* 一些校验失败的支付消息需要重新发送(新版本不再发送支付消息)
*/
@Scheduled(cron = "0 0 0/1 * * ? ")
@Transactional
//@Scheduled(cron = "0 0 0/1 * * ? ")
//@Transactional
public void checkPushFailPayMessage(){
//查找出状态为3 校验失败 4 发送消息失败 的消息需要重发
List<LeasePayRecordMessage> list = leasePayRecordMessageService.list(new LambdaQueryWrapper<LeasePayRecordMessage>()

View File

@@ -1,6 +1,8 @@
package com.m2pool.lease.vo;
import com.m2pool.lease.annotation.EncryptedField;
import com.m2pool.lease.annotation.LedgerLogParam;
import com.m2pool.lease.annotation.LedgerLogTag;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
@@ -30,18 +32,21 @@ public class BalanceVo {
* 提现金额
*/
@ApiModelProperty(value = "提现 金额",required = true)
@LedgerLogParam("提现金额")
private BigDecimal amount;
/**
* 链
*/
@ApiModelProperty(value = "用户自定义的钱包地址链",required = true)
@LedgerLogParam("")
private String toChain;
/**
* 币种
*/
@ApiModelProperty(value = "用户自定义的钱包地址的币种",required = true)
@LedgerLogParam("币种")
private String toSymbol;
@ApiModelProperty(value = "手续费",required = true)
@@ -49,12 +54,14 @@ public class BalanceVo {
@ApiModelProperty(value = "绑定的地址",required = true)
@EncryptedField
@LedgerLogTag
private String fromAddress;
/**
* 提现地址(用户自定义)
*/
@ApiModelProperty(value = "提现地址(用户自定义)",required = true)
@EncryptedField
@LedgerLogParam("提现目标地址")
private String toAddress;
@ApiModelProperty(value = "谷歌双重验证验证码",required = true)

View File

@@ -89,5 +89,12 @@
shop_id = #{shopId} AND pay_address = #{address} AND pay_coin = #{coin} AND chain = #{chain} AND del = 0
</select>
<update id="updateBalance">
<foreach collection="list" item="item" separator=";">
UPDATE lease_shop_config
SET balance = balance + #{item.realAmount}
WHERE pay_address = #{item.payAddress} AND pay_coin = #{item.payCoin} AND chain = #{item.chain} AND del = false
</foreach>
</update>
</mapper>

View File

@@ -24,6 +24,7 @@
id, user_id, from_address, balance, to_address, from_symbol, from_chain, to_symbol, to_chain, qrcode, create_time, update_time, del
</sql>
<!-- 根据用户 ID 查询钱包信息 -->
<select id="selectByUserId" resultType="com.m2pool.lease.dto.UserWalletDataDto">
SELECT
@@ -106,4 +107,13 @@
</select>
<update id="updateBalanceAndBlockBalance">
<foreach collection="list" item="item" separator=";">
UPDATE lease_user_wallet_data
SET balance = balance - #{item.realAmount},
blocked_balance = blocked_balance - #{item.blockAmount}
WHERE from_address = #{item.fromAddress} AND from_symbol = #{item.fromSymbol} AND from_chain = #{item.fromChain} AND del = false
</foreach>
</update>
</mapper>