update 租赁系统1.1.0 bug 测试修改

This commit is contained in:
yyb
2025-12-16 11:33:38 +08:00
parent 6983e8657b
commit 6250442c77
21 changed files with 313 additions and 206 deletions

View File

@@ -1,39 +0,0 @@
//package com.m2pool.lease.config;
//
//import com.m2pool.common.core.constant.SecurityConstants;
//import com.m2pool.common.core.context.SecurityContextHolder;
//import com.m2pool.common.core.utils.JwtUtils;
//import com.m2pool.common.core.utils.ServletUtils;
//import com.m2pool.common.security.utils.SecurityUtils;
//import org.springframework.stereotype.Component;
//import org.springframework.web.servlet.HandlerInterceptor;
//
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
////生产环境
//@Component
//public class AuthInterceptor implements HandlerInterceptor {
//
// @Override
// public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// // 获取请求头中的 Authorization 字段
//
// //System.out.println("获取到的Authorization:"+authorization + "666"+ SecurityUtils.getToken());
// //if (authorization != null) {
// // // 将 Authorization 值存入 ThreadLocal
// //
// //}
// String authorization = request.getHeader("Authorization");
//
// String userName = JwtUtils.getUserName(authorization);
// SecurityContextHolder.setUserName("liuyiqing0119@gmail.com");
// return true;
// }
//
// @Override
// public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// // 请求完成后清除 ThreadLocal 中的值,避免内存泄漏
// SecurityContextHolder.remove();
// }
//}

View File

@@ -1,16 +0,0 @@
package com.m2pool.lease.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*") // 允许跨域
.allowedMethods("GET", "POST")
.allowedHeaders("Content-Type")
.allowCredentials(true);
}
}

View File

@@ -1,22 +0,0 @@
//package com.m2pool.lease.config;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//
//@Configuration
//public class WebMvcConfig implements WebMvcConfigurer {
//
// @Autowired
// private AuthInterceptor authInterceptor;
//
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// // 注册拦截器并指定拦截路径
// registry.addInterceptor(authInterceptor)
// .addPathPatterns("/**") // 拦截所有请求
// .excludePathPatterns("/login", "/register") // 可选:排除不需要拦截的路径
// .excludePathPatterns("/swagger-ui.html", "/webjars/**", "/v2/api-docs", "/swagger-resources/**"); // 可选排除Swagger相关路径
// }
//}

View File

@@ -11,5 +11,5 @@ import lombok.Data;
public class MachineEffectDto {
private Long machineId;
private Boolean effect;
private Integer effect;
}

View File

@@ -71,25 +71,25 @@ public class MachineInfoDto {
private Integer saleOutNumbers;
//动态列名(方便前端显示)
private BigDecimal c1;
private String c1;
private BigDecimal c2;
private String c2;
private BigDecimal c3;
private String c3;
private BigDecimal c4;
private String c4;
private BigDecimal c5;
private String c5;
private BigDecimal c6;
private String c6;
private BigDecimal c7;
private String c7;
private BigDecimal c8;
private String c8;
private BigDecimal c9;
private String c9;
private BigDecimal c10;
private String c10;

View File

@@ -40,4 +40,7 @@ public class OrderMiningInfoDto {
@ApiModelProperty(value = "矿工号(用户自己输入)")
private String workerId;
@ApiModelProperty(value = "挖矿钱包币种")
private String coin;
}

View File

@@ -46,9 +46,6 @@ public class PurchasedMachineListDto {
private String poolUser;
@ApiModelProperty(value = "矿工号")
private String workerId;
@ApiModelProperty(value = "收款钱包")
private String walletAddress;
@@ -56,16 +53,18 @@ public class PurchasedMachineListDto {
private String watchUrl;
@ApiModelProperty(value = "0 租约已到期 1挖矿中 2卖家矿机启动中")
private Integer status;
@ApiModelProperty(value = "挖矿开始时间")
private LocalDateTime startTime;
@ApiModelProperty(value = "挖矿结束时间")
private LocalDateTime endTime;
private String workerId;
//
//@ApiModelProperty(value = "0 租约已到期 1挖矿中 2卖家矿机启动中")
//private Integer status;
//
//
//@ApiModelProperty(value = "挖矿开始时间")
//private LocalDateTime startTime;
//
//
//@ApiModelProperty(value = "挖矿结束时间")
//private LocalDateTime endTime;
private Long orderItemId;

View File

@@ -86,7 +86,7 @@ public class SellerMachineInfoDto {
private Boolean onlineStatus;
@ApiModelProperty(value = "矿机是否能够上架 0 不能 1 能")
private Boolean effect;
private Integer effect;
//@ApiModelProperty(value = "gpu和asic对应币种算力和月收益信息")
//private List<PowerIncomeInfoDto> powerIncomeInfoList;

View File

@@ -113,6 +113,11 @@ public class LeaseOrderItem implements Serializable {
*/
private String coin;
/**
* 单机理论算力
*/
private BigDecimal theoryPower;
/**
* 单机理论收益
*/

View File

@@ -146,4 +146,13 @@ public interface LeaseMachineMapper extends BaseMapper<LeaseMachine> {
*/
@MapKey("machineId")
Map<Long, MachineEffectDto> checkIsEffect(@Param("list") List<SellerMachineInfoDto> ids);
/**
* 批量修改矿机已售可售数量
* @param list
* @return
*/
boolean updateBatchSaleNumbers(@Param("list") List<LeaseMachine> list);
}

View File

@@ -3,6 +3,7 @@ package com.m2pool.lease.netty.handler;
import io.netty.channel.Channel;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@@ -19,9 +20,14 @@ public class ChannelManager {
private static final Map<String, Channel> channelMap = new ConcurrentHashMap<>();
/**
* key mac value ip
* key channel value mac
*/
private static final Map<String, String> macMap = new ConcurrentHashMap<>();
public static final Map<Channel, String> macMap = new ConcurrentHashMap<>();
/**
* key channel value id
*/
public static final Map<Channel, String> idMap = new ConcurrentHashMap<>();
/**
* 添加Channel
@@ -40,34 +46,39 @@ public class ChannelManager {
* @param ip
*/
public static void removeChannel(String ip) {
// 需要先移除MAC映射
macMap.values().removeIf(value -> value.equals(ip));
channelMap.remove(ip);
Channel channel = channelMap.get(ip);
if (channel != null){
idMap.remove(channel);
macMap.remove(channel);
channelMap.remove(ip);
}
}
/**
* 根据ip获取Channel
* @param ip
* @return
*/
public static Channel getChannelByIp(String ip) {
return channelMap.get(ip);
public static String getIdByChannel(String ip) {
Channel channel = channelMap.get(ip);
if (channel != null){
return idMap.get(channel);
}
return null;
}
/**
* 根据mac地址获取Channel
* @param mac
* @return
*/
public static Channel getChannelByMac(String mac) {
String ip = macMap.get(mac);
if (ip != null) {
return channelMap.get(ip);
}
return null;
Optional<Channel> key = macMap.entrySet()
.stream()
.filter(entry -> mac.equals(entry.getValue()))
.map(Map.Entry::getKey)
.findFirst();
return key.orElse(null);
}
public static boolean sendToClient(String mac, Object message) {

View File

@@ -23,7 +23,6 @@ import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import static com.m2pool.lease.netty.message.MethodConstant.PING;
@@ -88,11 +87,14 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
*/
private void handlerDownloadClientMessage(ChannelHandlerContext ctx,ClientMessage<Object> msg){
String id = msg.getId();
String[] split = id.split("\\.");
String[] split = id.split("::");
System.out.println("客户端消息"+JSONUtil.toJsonPrettyStr( split) + "长度"+split.length);
System.out.println("客户端消息 "+checkMessage(ctx,id,split[0]));
if (split.length == 2 && checkMessage(ctx,id,split[0])){
Object params = msg.getParams();
if (params instanceof GpuAndSoftMessage){
System.out.println("客户端消息"+JSONUtil.toJsonPrettyStr(params));
GpuAndSoftMessage gpuAndSoftMessage = (GpuAndSoftMessage) params;
Map<String, GpuMessage> gpus = gpuAndSoftMessage.getGpus();
List<String> miningsofts = gpuAndSoftMessage.getMiningsofts();
@@ -121,6 +123,8 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
leaseMachineMapper.insert(leaseMachine);
leaseMachineConfigService.saveBatch(leaseMachineConfigs);
}else {
leaseMachine.setOnlineStatus(true);
leaseMachineMapper.updateById(leaseMachine);
//检测对照表
List<LeaseMachineConfig> needUpdateInfo = packageInsert(leaseMachine.getId(),gpus, supportAlgorithmAndCoin);
//带检测矿机
@@ -157,7 +161,6 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
.memory(value.getMem())
.status(item.getIsEffect())
.unit("MH/S")
.status(true)
.del(false)
.build()).collect(Collectors.toList()));
}
@@ -261,7 +264,7 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
*/
private void handlerClientMiningMessage(ChannelHandlerContext ctx,ClientMessage<Object> msg){
String id = msg.getId();
String[] split = id.split("\\.");
String[] split = id.split("::");
if (split.length == 2 && checkMessage(ctx,id,split[0])){
Object params = msg.getParams();
if (params instanceof ClientConfigurationMining){
@@ -289,6 +292,9 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
*/
private boolean checkMessage(ChannelHandlerContext ctx,String id,String authCode){
LeaseShop leaseShop = getShop(authCode);
Channel channel = ctx.channel();
ChannelManager.idMap.put(channel,id);
ChannelManager.macMap.put(channel,getIPString(ctx));
//不存在对应身份码的店铺 发送消息给客户端
if (leaseShop == null){
sendErrorResp(ctx,id);
@@ -335,6 +341,11 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
@Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("ip:"+getIPString(ctx)+"断开连接");
String mac = ChannelManager.macMap.get(ctx.channel());
//修改矿机离线状态为 离线
if (mac != null){
leaseMachineMapper.update(LeaseMachine.builder().onlineStatus(false).build(), new LambdaUpdateWrapper<LeaseMachine>().eq(LeaseMachine::getHostMac,mac));
}
ChannelManager.removeChannel(getIPString(ctx));
ctx.close();
}
@@ -376,15 +387,18 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ClientMess
IdleStateEvent event = (IdleStateEvent) evt;
String ip = getIPString(ctx);
if (event.state() == IdleState.READER_IDLE) {
System.out.println("读超时,未收到任何客户都安消息,断开连接");
System.out.println("读超时,未收到任何客户消息,断开连接");
ChannelManager.removeChannel(ip);
ctx.disconnect();//断开
} else if (event.state() == IdleState.WRITER_IDLE) {
} else if (event.state() == IdleState.WRITER_IDLE ) {
System.out.println("写超时发送ping到客户端");
ClientMessage ping = new ClientMessage();
ping.setMethod(PING);
ping.setId("test.03000200-0400-0500-0006-000700080009");
ctx.writeAndFlush(ping);
String id = ChannelManager.getIdByChannel(ip);
if (id != null){
ClientMessage ping = new ClientMessage();
ping.setMethod(PING);
ping.setId(id);
ctx.writeAndFlush(ping);
}
} else if (event.state() == IdleState.ALL_IDLE) {
System.out.println("客户端 ALL_IDLE 总超时: " + socketString);
ChannelManager.removeChannel(ip);

View File

@@ -26,5 +26,4 @@ public class ClientMessage<T> {
}

View File

@@ -1,8 +1,6 @@
package com.m2pool.lease.service.impl;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@@ -15,7 +13,6 @@ import com.m2pool.lease.entity.LeaseMachineConfig;
import com.m2pool.lease.entity.LeaseMachinePrice;
import com.m2pool.lease.entity.LeaseShop;
import com.m2pool.lease.exception.MachineException;
import com.m2pool.lease.exception.ProductSoldOutException;
import com.m2pool.lease.mapper.*;
import com.m2pool.lease.service.LeaseMachineConfigService;
import com.m2pool.lease.service.LeaseMachinePriceService;
@@ -28,7 +25,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@@ -179,34 +175,34 @@ public class LeaseMachineServiceImpl extends ServiceImpl<LeaseMachineMapper, Lea
private void setDynamicPower(int index,MachineInfoDto machineInfo,PowerIncomeInfoDto powerIncomeInfoDto){
switch (index){
case 1:
machineInfo.setC1(powerIncomeInfoDto.getPower());
machineInfo.setC1(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 2:
machineInfo.setC2(powerIncomeInfoDto.getPower());
machineInfo.setC2(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 3:
machineInfo.setC3(powerIncomeInfoDto.getPower());
machineInfo.setC3(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 4:
machineInfo.setC4(powerIncomeInfoDto.getPower());
machineInfo.setC4(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 5:
machineInfo.setC5(powerIncomeInfoDto.getPower());
machineInfo.setC5(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 6:
machineInfo.setC6(powerIncomeInfoDto.getPower());
machineInfo.setC6(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 7:
machineInfo.setC7(powerIncomeInfoDto.getPower());
machineInfo.setC7(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 8:
machineInfo.setC8(powerIncomeInfoDto.getPower());
machineInfo.setC8(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 9:
machineInfo.setC9(powerIncomeInfoDto.getPower());
machineInfo.setC9(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
case 10:
machineInfo.setC10(powerIncomeInfoDto.getPower());
machineInfo.setC10(powerIncomeInfoDto.getPower() + powerIncomeInfoDto.getUnit());
break;
}
}
@@ -232,7 +228,7 @@ public class LeaseMachineServiceImpl extends ServiceImpl<LeaseMachineMapper, Lea
for (SellerMachineInfoDto row : success.getRows()) {
MachineEffectDto machineEffectDto = longMachineEffectDtoMap.get(row.getId());
row.setEffect(machineEffectDto != null ? machineEffectDto.getEffect() : false);
row.setEffect(machineEffectDto != null ? machineEffectDto.getEffect() : 0);
row.setPriceList(collect.get(row.getId()));
row.setCoinAndAlgoList(collect1.get(row.getId()));
}
@@ -312,6 +308,7 @@ public class LeaseMachineServiceImpl extends ServiceImpl<LeaseMachineMapper, Lea
.type(false)
.maxLeaseDays(asicMachineParamsVo.getMaxLeaseDays())
.saleNumbers(asicMachineParamsVo.getSaleNumbers())
.canSaleNumbers(asicMachineParamsVo.getSaleNumbers())
.build();
int machineInsert = leaseMachineMapper.insert(machine);

View File

@@ -20,11 +20,13 @@ import com.m2pool.lease.entity.*;
import com.m2pool.lease.exception.OrderException;
import com.m2pool.lease.mapper.*;
import com.m2pool.lease.netty.handler.ChannelManager;
import com.m2pool.lease.netty.message.ClientMessage;
import com.m2pool.lease.service.LeaseOrderInfoService;
import com.m2pool.lease.service.LeaseOrderItemService;
import com.m2pool.lease.service.LeaseProductService;
import com.m2pool.lease.service.LeaseUserOwnedProductService;
import com.m2pool.lease.utils.UuidGeneratorUtil;
import com.m2pool.lease.utils.WalletRuleCheckUtils;
import com.m2pool.lease.vo.*;
import com.m2pool.lease.vo.v2.CoinAndAlgorithmVo;
import org.springframework.stereotype.Service;
@@ -38,6 +40,8 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.m2pool.lease.netty.message.MethodConstant.MINING_RAG;
/**
* <p>
* 订单表 服务实现类
@@ -685,7 +689,8 @@ public class LeaseOrderInfoServiceImpl extends ServiceImpl<LeaseOrderInfoMapper,
String userEmail = SecurityUtils.getUsername();
List<OrderInfoVo> orderInfoVoList = orderAndCodeVo.getOrderInfoVoList();
List<OrderMiningInfoDto> orderMiningInfoDtoList = orderAndCodeVo.getOrderMiningInfoDtoList();
String errors = checkMiningMinersExist(orderMiningInfoDtoList);
String errors = checkMiningMinersExistAndAddress(orderMiningInfoDtoList);
if (StringUtils.isNotEmpty(errors)){
return Result.fail(errors);
}
@@ -927,22 +932,34 @@ public class LeaseOrderInfoServiceImpl extends ServiceImpl<LeaseOrderInfoMapper,
* 检测本次输入的钱包对应矿工号,是否已经存在并在挖矿中
* @param orderMiningInfoDtoList
*/
private String checkMiningMinersExist(List<OrderMiningInfoDto> orderMiningInfoDtoList){
private String checkMiningMinersExistAndAddress(List<OrderMiningInfoDto> orderMiningInfoDtoList){
List<OrderMiningInfoDto> orderMiningInfoDtos = leaseOrderMiningMapper.checkMiningMinersExist(orderMiningInfoDtoList);
StringBuilder errors = new StringBuilder();
String addressVerify = "";
List<OrderMiningInfoDto> addressInfos = new ArrayList();
if(!orderMiningInfoDtos.isEmpty()){
Map<String, List<OrderMiningInfoDto>> collect = orderMiningInfoDtos.stream().collect(Collectors.groupingBy(OrderMiningInfoDto::getWalletAddress));
collect.forEach((address,list)->{
errors.append("钱包地址: ").append(address).append("-已存在挖矿中矿工号");
for (OrderMiningInfoDto orderMiningInfoDto : list) {
errors.append(orderMiningInfoDto.getWorkerId()).append(" ");
}
errors.append("请重新输入矿工号\n");
addressInfos.add(list.get(0));
});
}
return errors.toString();
if (StringUtils.isNotEmpty(errors.toString())){
return errors.toString();
}
for (OrderMiningInfoDto addressInfo : addressInfos) {
if (!WalletRuleCheckUtils.checkAddress(addressInfo.getCoin(),addressInfo.getWalletAddress())){
addressVerify = addressInfo.getWalletAddress() + "钱包地址格式错误";
break;
}
}
return addressVerify;
}
/**
@@ -955,7 +972,7 @@ public class LeaseOrderInfoServiceImpl extends ServiceImpl<LeaseOrderInfoMapper,
Map<Long,MiningConfigDto> coinAndAlgoMap = leaseMachineMapper.getCoinAndAlgoById(configIds);
Map<Long, LeaseMachine> idAndMacMap = gpuMachines.stream().collect(Collectors
.toMap(LeaseMachine::getId, Function.identity()));
Map<String,MiningConfigDto> macMessageMap = new HashMap<>();
Map<String,ClientMessage<MiningConfigDto>> macMessageMap = new HashMap<>();
List<LeaseOrderMining> orderMiningList = new ArrayList<>();
for (OrderMiningInfoDto orderMiningInfoDto : orderMiningInfo) {
@@ -975,8 +992,8 @@ public class LeaseOrderInfoServiceImpl extends ServiceImpl<LeaseOrderInfoMapper,
//这里因为orderMiningInfo 存在ASIC 的信息可能为空
if (leaseMachine != null){
String mac = leaseMachine.getHostMac();
//TCP 消息
macMessageMap.put(mac,MiningConfigDto.builder()
ClientMessage<MiningConfigDto> message = new ClientMessage<>();
MiningConfigDto build = MiningConfigDto.builder()
.algo(algo)
.coin(coin)
.pool(poolName)
@@ -985,7 +1002,12 @@ public class LeaseOrderInfoServiceImpl extends ServiceImpl<LeaseOrderInfoMapper,
.wallet_address(walletAddress)
.pool_user(poolUser)
.worker_id(poolWorkerId)
.end_timestamp(endTime/1000).build());
.end_timestamp(endTime / 1000).build();
message.setId(userEmail+"::"+ mac);
message.setMethod(MINING_RAG);
message.setParams( build);
//TCP 消息
macMessageMap.put(mac,message);
}
LeaseOrderMining build = LeaseOrderMining.builder()
.orderId(orderId)
@@ -1021,7 +1043,7 @@ public class LeaseOrderInfoServiceImpl extends ServiceImpl<LeaseOrderInfoMapper,
* @param mac 矿机mac
* @param message 消息内容
*/
public void sendMessage(String mac,MiningConfigDto message){
public void sendMessage(String mac,ClientMessage<MiningConfigDto> message){
ChannelManager.sendToClient(mac,message);
}

View File

@@ -156,12 +156,13 @@ public class OrderAndPayTask {
List<Long> orderComplete = new ArrayList<>();
//本次部分已完成订单详情id + 机器id 集合
List<Long> itemCompleteIds = new ArrayList<>();
List<Long> completeMachineIds = new ArrayList<>();
List<LeaseMachine> completeMachines = new ArrayList<>();
//本此需支付订单详情id 集合
List<Long> needPayIds = new ArrayList<>();
//本次需支付订单详情 集合
List<LeaseOrderItem> needPayInfos = new ArrayList<>();
getCompleteOrderAndNeedPayOrder(orderComplete,completeMachineIds,itemCompleteIds,needPayIds,needPayInfos,leaseOrderItems);
getCompleteOrderAndNeedPayOrder(orderComplete,completeMachines,itemCompleteIds,needPayIds,needPayInfos,leaseOrderItems);
//订单进行过程中,卖方可能修改收款地址。所以每天支付前,需要修改旧收款地址为新地址
needPayInfos = updateOrderItemSellerWalletAddress(needPayInfos);
@@ -255,7 +256,7 @@ public class OrderAndPayTask {
}
//2.处理完成的订单 (订单部分完成)
if(!itemCompleteIds.isEmpty()){
handlerOrderPartComplete(itemCompleteIds,completeMachineIds);
handlerOrderPartComplete(itemCompleteIds,completeMachines);
}
//3.处理完成的订单 + 发送mq消息去支付订单全部完成
@@ -274,7 +275,7 @@ public class OrderAndPayTask {
* @param needPayInfos 本次需要支付的订单信息(租赁数量,租赁天数,单价等)
* @param oneDayApartOrder
*/
public void getCompleteOrderAndNeedPayOrder(List<Long> orderComplete,List<Long> completeMachineIds ,List<Long> completeIds,List<Long> needPayIds,List<LeaseOrderItem> needPayInfos,List<LeaseOrderItem> oneDayApartOrder){
public void getCompleteOrderAndNeedPayOrder(List<Long> orderComplete,List<LeaseMachine> completeMachines,List<Long> completeIds,List<Long> needPayIds,List<LeaseOrderItem> needPayInfos,List<LeaseOrderItem> oneDayApartOrder){
LocalDateTime now = LocalDateTime.now();
Map<Long,Boolean> orderCompleteMap = new HashMap<>();
for (LeaseOrderItem orderTimeInfoDto : oneDayApartOrder) {
@@ -287,7 +288,12 @@ public class OrderAndPayTask {
// 比较 now 和 endTime 的差值是否小于30分
if (Duration.between(now, endTime).toMinutes() <= 1) {
completeMachineIds.add(orderTimeInfoDto.getProductMachineId());
completeMachines.add(LeaseMachine.builder()
.id(orderTimeInfoDto.getProductMachineId())
.canSaleNumbers(orderTimeInfoDto.getNumbers())
.saleOutNumbers(orderTimeInfoDto.getNumbers())
.saleState(false)
.build());
completeIds.add(orderTimeInfoDto.getId());
needPayIds.add(orderTimeInfoDto.getId());
needPayInfos.add(orderTimeInfoDto);
@@ -324,15 +330,14 @@ public class OrderAndPayTask {
Map<Long,BigDecimal> orderItemIdToWaveMap = new HashMap<>();
orderIdToHashrateMap.forEach((orderItemId, realPowerList) -> {
// 计算平均值
BigDecimal average = realPowerList.stream()
.map(RealHashrateInfoDto::getPower)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(BigDecimal.valueOf(realPowerList.size()), 2, RoundingMode.HALF_UP);
// 计算每个数据点与平均值的比值
LeaseOrderItem itemInfo = orderIdToPriceMap.get(orderItemId);
// 计算每个数据点 理论算力的比值
List<BigDecimal> ratios = realPowerList.stream()
.map(dto -> dto.getPower().divide(average, 4, RoundingMode.HALF_UP))
.map(dto -> dto.getPower()
.divide(itemInfo.getTheoryPower(), 4, RoundingMode.HALF_UP))
.collect(Collectors.toList());
// 补零到48个数据点
@@ -345,11 +350,10 @@ public class OrderAndPayTask {
.reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(BigDecimal.valueOf(48), 2, RoundingMode.HALF_UP);
LeaseOrderItem itemInfo = orderIdToPriceMap.get(orderItemId);
BigDecimal payAmount = itemInfo.getPrice()
.multiply(BigDecimal.valueOf(itemInfo.getNumbers()))
.multiply(BigDecimal.valueOf(itemInfo.getLeaseTime()));
.multiply(BigDecimal.valueOf(itemInfo.getNumbers()));
if (finalValue.compareTo(BigDecimal.valueOf(0.95)) <= 0){
payAmount = payAmount.multiply(finalValue);
}
@@ -423,15 +427,14 @@ public class OrderAndPayTask {
/**
* 处理订单部分完成
* @param itemIds 已完成订单项id
* @param machineIds 已完成机器id
* @param completeMachines 已完成机器id
*/
public void handlerOrderPartComplete(List<Long> itemIds,List<Long> machineIds){
public void handlerOrderPartComplete(List<Long> itemIds,List<LeaseMachine> completeMachines){
//修改订单详情表中状态为 0 租约已过期
leaseOrderItemMapper.update(LeaseOrderItem.builder().status(0).build(), new LambdaUpdateWrapper<LeaseOrderItem>()
.in(LeaseOrderItem::getId, itemIds));
//修改商品库存矿机表 矿机状态为 0 未售出
leaseMachineMapper.update(LeaseMachine.builder().saleState(false).build(), new LambdaUpdateWrapper<LeaseMachine>()
.in(LeaseMachine::getId, machineIds));
leaseMachineMapper.updateBatchSaleNumbers(completeMachines);
//挖矿订单信息 改为状态0 租约已过期
leaseOrderMiningMapper.update(LeaseOrderMining.builder().status(false).build(), new LambdaUpdateWrapper<LeaseOrderMining>()
.in(LeaseOrderMining::getOrderItemId, itemIds));
@@ -779,15 +782,17 @@ public class OrderAndPayTask {
.toSymbol(initForm.getToSymbol())
.toChain(initForm.getToChain())
.build();
try {
rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build);
}catch (Exception e){
//设置状态为消息发送失败
build1.setStatus(4);
System.out.println("消息发送失败"+e.getMessage());
}finally {
reocrdList.add(build1);
}
//try {
// rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build);
//}catch (Exception e){
// //设置状态为消息发送失败
// build1.setStatus(4);
// System.out.println("消息发送失败"+e.getMessage());
//}finally {
// reocrdList.add(build1);
//}
});
leasePayRecordMessageService.saveBatch(reocrdList);

View File

@@ -3,8 +3,9 @@ package com.m2pool.lease.utils;
import com.m2pool.lease.entity.LeaseProduct;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
public class HashUtils {
@@ -57,9 +58,24 @@ public class HashUtils {
return decimalValue.toString(16) + key;
}
public static void main(String[] args) {
public static void main(String[] args) throws NoSuchAlgorithmException {
//Long inputStr = 1758610297L;
//System.out.println("加密结果" + sha256(inputStr));
// 生成RSA密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 密钥长度设置为2048位
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 将公钥转换为Base64字符串格式
String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
System.out.println("公钥 (Base64): " + publicKeyString);
// 将私钥转换为Base64字符串格式注意安全
String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
System.out.println("私钥 (Base64): " + privateKeyString);
}

View File

@@ -7,36 +7,56 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.m2pool.common.core.utils.StringUtils;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.regex.Pattern;
public class WalletRuleCheckUtils {
// ---------------TRON校验-------------------
private static final String API_KEY = "0925bdd7-7def-4a46-b65f-e17f02dc67c7";
public static boolean checkAddress(String chain, String address){
/**
* 校验地址
* @param chainOrCoin
* @param address
* @return
*/
public static boolean checkAddress(String chainOrCoin, String address) {
if (address == null) {
return false;
}
chain = chain.toUpperCase();
switch (chain) {
chainOrCoin = chainOrCoin.toUpperCase();
switch (chainOrCoin) {
case "TRON":
return checkTRON(address);
case "ETH":
return checkETH(address);
case "XTM":
return checkXTM(address);
case "IRON":
return checkIRON(address);
case "XEL":
return checkXEL(address);
case "RVN":
return checkRVN(address);
case "ERG":
return checkERG(address);
case "CFX":
return checkCFX(address);
case "NEXA":
return checkNEXA(address);
case "XNA":
return checkXNA(address);
case "KLS":
return checkKLS(address);
case "CLORE":
return checkCLORE(address);
default:
return false;
}
}
// ---------------TRON校验-------------------
private static final String API_KEY = "0925bdd7-7def-4a46-b65f-e17f02dc67c7";
/**
* 调用 Tronscan API 获取账户信息
* @param address 要查询的账户地址
@@ -89,6 +109,73 @@ public class WalletRuleCheckUtils {
return ETH_BASIC_PATTERN.matcher(address).matches();
}
// ---------------ETH校验-------------------
// ---------------XTM校验-------------------
private static final Pattern XTM_PATTERN = Pattern.compile("^P[0-9a-zA-Z]{34}$");
public static boolean checkXTM(String address) {
return StringUtils.isNotEmpty( address) && XTM_PATTERN.matcher(address).matches();
}
// ---------------IRON校验-------------------
private static final Pattern IRON_PATTERN = Pattern.compile("^i[0-9a-zA-Z]{33}$");
public static boolean checkIRON(String address) {
return StringUtils.isNotEmpty( address) && IRON_PATTERN.matcher(address).matches();
}
// ---------------XEL校验-------------------
private static final Pattern XEL_PATTERN = Pattern.compile("^XEL[0-9a-zA-Z]{33}$");
public static boolean checkXEL(String address) {
return StringUtils.isNotEmpty( address) && XEL_PATTERN.matcher(address).matches();
}
// ---------------RVN校验-------------------
private static final Pattern RVN_PATTERN = Pattern.compile("^R[0-9a-zA-Z]{33}$");
public static boolean checkRVN(String address) {
return StringUtils.isNotEmpty( address) && RVN_PATTERN.matcher(address).matches();
}
// ---------------ERG校验-------------------
private static final Pattern ERG_PATTERN = Pattern.compile("^9[0-9a-zA-Z]{50}$");
public static boolean checkERG(String address) {
return StringUtils.isNotEmpty( address) && ERG_PATTERN.matcher(address).matches();
}
// ---------------CFX校验-------------------
private static final Pattern CFX_PATTERN = Pattern.compile("^cfx:[a-z0-9]{42}$");
public static boolean checkCFX(String address) {
return StringUtils.isNotEmpty( address) && CFX_PATTERN.matcher(address).matches();
}
// ---------------NEXA校验-------------------
private static final Pattern NEXA_PATTERN = Pattern.compile("^nexa:[0-9a-zA-Z]{40}$");
private static final Pattern NEXA_PATTERN2 = Pattern.compile("^[0-9a-zA-Z]{40}$");
public static boolean checkNEXA(String address) {
if (address.startsWith("nexa:")){
return StringUtils.isNotEmpty(address) && NEXA_PATTERN.matcher(address).matches();
}else{
return StringUtils.isNotEmpty(address) && NEXA_PATTERN2.matcher(address).matches();
}
}
// ---------------XNA校验-------------------
private static final Pattern XNA_PATTERN = Pattern.compile("^X[0-9a-zA-Z]{33}$");
public static boolean checkXNA(String address) {
return StringUtils.isNotEmpty( address) && XNA_PATTERN.matcher(address).matches();
}
// ---------------KLS校验-------------------
private static final Pattern KLS_PATTERN = Pattern.compile("^k[0-9a-zA-Z]{33}$");
public static boolean checkKLS(String address) {
return StringUtils.isNotEmpty( address) && KLS_PATTERN.matcher(address).matches();
}
// ---------------CLORE校验-------------------
private static final Pattern CLORE_PATTERN = Pattern.compile("^C[0-9a-zA-Z]{33}$");
public static boolean checkCLORE(String address) {
return StringUtils.isNotEmpty( address) && CLORE_PATTERN.matcher(address).matches();
}
public static void main(String[] args) {
}

View File

@@ -1,5 +1,6 @@
package com.m2pool.lease.vo;
import com.m2pool.common.core.decrpy.Decrypt;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
@@ -47,6 +48,7 @@ public class ShopConfigVo extends BaseVo {
/**
* 卖方对应收款钱包
*/
@Decrypt
@ApiModelProperty(value = "卖方对应收款钱包",example = "nexa:nqtsq5g50jkkmklvjyaflg46c4nwuy46z9gzswqe3l0csc7g")
private String payAddress;

View File

@@ -126,7 +126,7 @@
FROM
lease_machine lm
JOIN
lease_machine_config gpc ON lm.id = gpc.machine_id AND lm.type = #{shopMachineVo.type} AND lm.shop_id = #{shopMachineVo.shopId} AND lm.online_status = true
lease_machine_config gpc ON lm.id = gpc.machine_id AND lm.type = #{shopMachineVo.type} AND lm.shop_id = #{shopMachineVo.shopId} AND lm.online_status = true AND lm.sale_state = 0
GROUP BY lm.id,gpc.coin,gpc.algorithm
) sub
LEFT JOIN lease_machine_price mp
@@ -337,7 +337,9 @@
<update id="updateLockState">
UPDATE lease_machine
SET
sale_state = 1
sale_state = 1,
can_sale_numbers = 0,
sale_out_numbers = 1
WHERE
id IN
<foreach item="item" collection="list" open="(" separator="," close=")">
@@ -350,13 +352,15 @@
UPDATE lease_machine
SET
sale_out_numbers = #{item.saleOutNumbers},
sale_state = CASE WHEN #{item.saleOutNumbers} = sale_numbers THEN 1 ELSE sale_state END
sale_state = CASE WHEN #{item.saleOutNumbers} = sale_numbers THEN 1 ELSE sale_state END,
can_sale_numbers = sale_numbers - #{item.saleOutNumbers}
WHERE
id = #{item.id}
AND sale_out_numbers = #{item.lockNumbers}
</foreach>
</update>
<select id="getCoinAndAlgoById" resultType="com.m2pool.lease.dto.v2.MiningConfigDto">
select
id,
@@ -441,5 +445,15 @@
</foreach>
</select>
<update id="updateBatchSaleNumbers">
<foreach collection="list" item="item" separator=";">
UPDATE lease_machine
SET
sale_out_numbers = sale_out_numbers - #{item.saleOutNumbers},
can_sale_numbers = can_sale_numbers + #{item.canSaleNumbers}
WHERE
id = #{item.id}
</foreach>
</update>
</mapper>

View File

@@ -68,7 +68,6 @@
<select id="getPurchasedItems" resultType="com.m2pool.lease.dto.v2.PurchasedMachineListDto">
select
id ,
coin,
algorithm,
pool,
@@ -92,12 +91,14 @@
pool,
pool_url as poolUrl,
pool_user as poolUser,
worker_id as workerId,
-- worker_id as workerId,
-- status,
-- start_time as startTime,
-- end_time as endTime,
wallet_address as walletAddress,
watch_url as watchUrl,
status,
start_time as startTime,
end_time as endTime
watch_url as watchUrl
FROM lease_order_mining
WHERE id = #{id}
</select>