diff --git a/m2pool-modules/m2pool-lease/pom.xml b/m2pool-modules/m2pool-lease/pom.xml new file mode 100644 index 0000000..e40b527 --- /dev/null +++ b/m2pool-modules/m2pool-lease/pom.xml @@ -0,0 +1,225 @@ + + + + m2pool-modules + com.m2pool + 3.5.0 + + 4.0.0 + + m2pool-lease + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.boot + spring-boot-starter-web + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + mysql + mysql-connector-java + + + + + org.projectlombok + lombok-maven-plugin + provided + + + + + + + + + + + + + + + + + + + + + com.m2pool + common-datasource + + + + + com.m2pool + common-security + + + + + com.m2pool + common-log + + + + com.m2pool + common-swagger + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.java-websocket + Java-WebSocket + 1.3.5 + + + + cn.hutool + hutool-all + 5.6.2 + + + + org.mybatis + mybatis + 3.5.7 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.3 + + + + + de.taimos + totp + 1.0 + + + + commons-codec + commons-codec + 1.10 + + + + com.google.zxing + javase + 3.3.0 + + + + net.java.dev.jna + jna + 5.12.1 + + + + pt.kcry + blake3_3 + 3.1.2 + + + + + + + + + + dev + + dev + 127.0.0.1:8808 + + + + true + + + + + test + + test + 127.0.0.1:8808 + + + false + + + + + prod + + prod + 127.0.0.1:8808 + + + false + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + 2.5.6 + + + + repackage + + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/M2poolLeaseApplication.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/M2poolLeaseApplication.java new file mode 100644 index 0000000..3e27c64 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/M2poolLeaseApplication.java @@ -0,0 +1,21 @@ +package com.m2pool.lease; + +import com.m2pool.common.security.annotation.EnableCustomConfig; +import com.m2pool.common.security.annotation.EnableM2PoolFeignClients; +import com.m2pool.common.swagger.annotation.EnableCustomSwagger2; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableM2PoolFeignClients +@SpringBootApplication +@MapperScan({"com.m2pool.lease.mapper"}) +public class M2poolLeaseApplication { + + public static void main(String[] args) { + SpringApplication.run(M2poolLeaseApplication.class, args); + } + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/AuthInterceptor.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/AuthInterceptor.java new file mode 100644 index 0000000..52b2d8a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/AuthInterceptor.java @@ -0,0 +1,39 @@ +//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(); +// } +//} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/CorsConfig.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/CorsConfig.java new file mode 100644 index 0000000..9d640f2 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/CorsConfig.java @@ -0,0 +1,16 @@ +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); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/JacksonMessageConverter.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/JacksonMessageConverter.java new file mode 100644 index 0000000..f94de52 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/JacksonMessageConverter.java @@ -0,0 +1,16 @@ +package com.m2pool.lease.config; + +import org.springframework.amqp.core.Message; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; + +public class JacksonMessageConverter extends Jackson2JsonMessageConverter { + public JacksonMessageConverter() { + super(); + } + + @Override + public Object fromMessage(Message message) { + message.getMessageProperties().setContentType("application/json"); + return super.fromMessage(message); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/Knife4jConfiguration.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/Knife4jConfiguration.java new file mode 100644 index 0000000..7af7653 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/Knife4jConfiguration.java @@ -0,0 +1,40 @@ +package com.m2pool.lease.config;//package com.m2pool.lease.config; +// +//import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import springfox.documentation.builders.ApiInfoBuilder; +//import springfox.documentation.builders.PathSelectors; +//import springfox.documentation.builders.RequestHandlerSelectors; +//import springfox.documentation.service.ApiInfo; +//import springfox.documentation.spi.DocumentationType; +//import springfox.documentation.spring.web.plugins.Docket; +//import springfox.documentation.swagger2.annotations.EnableSwagger2; +// +//@Configuration +//@EnableSwagger2 +//@EnableKnife4j +//public class Knife4jConfiguration { +// +// @Bean +// public Docket createRestApi() { +// return new Docket(DocumentationType.SWAGGER_2) +// .useDefaultResponseMessages(false) +// .apiInfo(apiInfo()) +// .select() +// .apis(RequestHandlerSelectors.basePackage("com.m2pool.lease.controller")) +// .paths(PathSelectors.any()) +// .build(); +// +// } +// +// private ApiInfo apiInfo() { +// return new ApiInfoBuilder() +// .description("Kinfe4j 集成测试文档") +// .version("v1.0.0") +// .title("API测试文档") +// .build(); +// } +// +//} +// diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/RabbitMQConfig.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/RabbitMQConfig.java new file mode 100644 index 0000000..80c1812 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/RabbitMQConfig.java @@ -0,0 +1,289 @@ +package com.m2pool.lease.config; + + +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +import static com.m2pool.lease.constant.RabbitmqConstant.*; + +@Configuration +public class RabbitMQConfig { + + @Bean + public MessageConverter jackson2JsonMessageConverter() { + //自动生成消息唯一id + //jackson2JsonMessageConverter.setCreateMessageIds(true); + return new JacksonMessageConverter(); + } + + @Bean + public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { + RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); + rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter()); + + //// 自定义 MessagePostProcessor 来设置 content-type + //rabbitTemplate.setBeforePublishPostProcessors(new MessagePostProcessor() { + // @Override + // public Message postProcessMessage(Message message) { + // // 设置 content-type 为 application/json + // message.getMessageProperties().setContentType("application/json"); + // return message; + // } + //}); + // 开启发布确认模式 + rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> { + if (ack) { + System.out.println("消息发送成功,correlationData: " + correlationData); + } else { + System.out.println("消息发送失败,原因: " + cause); + // 这里可以添加将失败消息存储到数据库的逻辑 + } + }); + rabbitTemplate.setMandatory(true); + return rabbitTemplate; + } + + + @Bean + public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + factory.setConnectionFactory(connectionFactory); + //消费者序列化 + factory.setMessageConverter(jackson2JsonMessageConverter()); + factory.setConcurrentConsumers(3); // 设置初始消费者数量 + factory.setMaxConcurrentConsumers(5); // 设置最大消费者数量 + return factory; + } + + + /** + * 矿池代理队列 + * @return + */ + @Bean + public Queue poolProxyQueue() { + // durable 设置为 true 表示队列持久化 + return new Queue(POOL_PROXY_QUEUE_NAME, true); + } + + //----------------定义订单延迟队列------------------------ + + /** + * 死信 交换机 + * @return + */ + @Bean + public DirectExchange deadLetterExchange() { + return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME); + } + + /** + * 死信 队列 + * @return + */ + @Bean + public Queue deadLetterQueue() { + return new Queue(DEAD_LETTER_QUEUE_NAME, true); + } + + /** + * 死信 队列绑定死信交换机 + * @return + */ + @Bean + public Binding deadLetterBinding() { + return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()).with(DEAD_LETTER_ROUTING_KEY); + } + + /** + * 订单超时消息 交换机 + * @return + */ + @Bean + public DirectExchange orderOvertimeExchange() { + return new DirectExchange(ORDER_OVERTIME_EXCHANGE_NAME); + } + + /** + * 订单超时消息 队列 (死信交换机达成延迟队列功能) + * @return + */ + @Bean + public Queue orderOvertimeQueue() { + Map args = new HashMap<>(); + // 设置死信交换机 + args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE_NAME); + // 设置死信路由键 + args.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY); + // 设置队列中消息的 TTL(单位:毫秒) + args.put("x-message-ttl", 900000); + return new Queue(ORDER_OVERTIME_QUEUE_NAME, true, false, false, args); + } + + /** + * 订单超时消息 队列绑定普通交换机 + * @return + */ + @Bean + public Binding orderOvertimeBinding() { + return BindingBuilder.bind(orderOvertimeQueue()).to(orderOvertimeExchange()).with(ORDER_OVERTIME_ROUTING_KEY); + } + + //----------------定义订单延迟队列------------------------ + + //----------------定义支付相关队列------------------------ + /** + * 声明 Topic 类型的交换机 + */ + @Bean + public DirectExchange payExchange() { + return new DirectExchange(PAY_EXCHANGE); + } + + // 支付相关队列声明 + /** + * 声明支付消息队列 + */ + @Bean + public Queue payAutoQueue() { + return new Queue(PAY_AUTO_QUEUE, true); + } + + /** + * 声明支付返回消息队列 + */ + @Bean + public Queue payAutoReturnQueue() { + return new Queue(PAY_AUTO_RETURN_QUEUE, true); + } + + // 余额充值相关队列声明 + /** + * 声明余额充值消息队列 + */ + @Bean + public Queue payRechargeQueue() { + return new Queue(PAY_RECHARGE_QUEUE, true); + } + + /** + * 声明余额充值返回信息队列 + */ + @Bean + public Queue payRechargeReturnQueue() { + return new Queue(PAY_RECHARGE_RETURN_QUEUE, true); + } + + // 余额提现相关队列声明 + /** + * 声明余额提现消息队列 + */ + @Bean + public Queue payWithdrawQueue() { + return new Queue(PAY_WITHDRAW_QUEUE, true); + } + + /** + * 声明余额提现返回信息队列 + */ + @Bean + public Queue payWithdrawReturnQueue() { + return new Queue(PAY_WITHDRAW_RETURN_QUEUE, true); + } + + // 支付相关绑定 + /** + * 将支付消息队列绑定到交换机 + */ + @Bean + public Binding payAutoBinding() { + return BindingBuilder.bind(payAutoQueue()).to(payExchange()).with(PAY_AUTO_ROUTING_KEY); + } + + /** + * 将支付返回消息队列绑定到交换机 + */ + @Bean + public Binding payAutoReturnBinding() { + return BindingBuilder.bind(payAutoReturnQueue()).to(payExchange()).with(PAY_AUTO_RETURN_ROUTING_KEY); + } + + + // 余额充值相关绑定 + /** + * 将余额充值消息队列绑定到交换机 + */ + @Bean + public Binding payRechargeBinding() { + return BindingBuilder.bind(payRechargeQueue()).to(payExchange()).with(PAY_RECHARGE_ROUTING_KEY); + } + + /** + * 将余额充值返回信息队列绑定到交换机 + */ + @Bean + public Binding payRechargeReturnBinding() { + return BindingBuilder.bind(payRechargeReturnQueue()).to(payExchange()).with(PAY_RECHARGE_RETURN_ROUTING_KEY); + } + + // 余额提现相关绑定 + /** + * 将余额提现消息队列绑定到交换机 + */ + @Bean + public Binding payWithdrawBinding() { + return BindingBuilder.bind(payWithdrawQueue()).to(payExchange()).with(PAY_WITHDRAW_ROUTING_KEY); + } + + /** + * 将余额提现返回信息队列绑定到交换机 + */ + @Bean + public Binding payWithdrawReturnBinding() { + return BindingBuilder.bind(payWithdrawReturnQueue()).to(payExchange()).with(PAY_WITHDRAW_RETURN_ROUTING_KEY); + } + + + + + //钱包删除 提现相关绑定 + + + @Bean + public Queue deleteWalletReturnQueue() { + return new Queue(DELETE_WALLET_RETURN_QUEUE, true); + } + + @Bean + public Queue deleteWalletQueue() { + return new Queue(DELETE_WALLET_QUEUE, true); + } + + /** + * 将钱包删除消息队列绑定到交换机 + */ + @Bean + public Binding deleteWalletBinding() { + return BindingBuilder.bind(deleteWalletQueue()).to(payExchange()).with(DELETE_WALLET_ROUTING_KEY); + } + + /** + * 将钱包删除返回信息队列绑定到交换机 + */ + @Bean + public Binding deleteWalletReturnBinding() { + return BindingBuilder.bind(deleteWalletReturnQueue()).to(payExchange()).with(DELETE_WALLET_RETURN_ROUTING_KEY); + } + + + //----------------定义支付相关队列------------------------ +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/ThreadPoolConfig.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/ThreadPoolConfig.java new file mode 100644 index 0000000..20e7f7f --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/ThreadPoolConfig.java @@ -0,0 +1,31 @@ +package com.m2pool.lease.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ThreadPoolExecutor; + +@Configuration +public class ThreadPoolConfig { + + @Bean(name = "customThreadPool") + public ThreadPoolTaskExecutor customTaskThreadPool() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + // 核心线程数 + executor.setCorePoolSize(5); + // 最大线程数 + executor.setMaxPoolSize(10); + // 队列容量 + executor.setQueueCapacity(50); + // 线程空闲时间(秒) + executor.setKeepAliveSeconds(30); + // 线程名前缀 + executor.setThreadNamePrefix("custom-task-thread-"); + // 拒绝策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + // 初始化 + executor.initialize(); + return executor; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/WebMvcConfig.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/WebMvcConfig.java new file mode 100644 index 0000000..ad24b7c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/config/WebMvcConfig.java @@ -0,0 +1,22 @@ +//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相关路径 +// } +//} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/Algorithm.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/Algorithm.java new file mode 100644 index 0000000..d7afab5 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/Algorithm.java @@ -0,0 +1,106 @@ +package com.m2pool.lease.constant; + +import com.m2pool.common.core.utils.StringUtils; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description 币种算法 + * @Date 2025/8/18 16:19 + * @Author yyb + */ +public class Algorithm { + // GRS 出块间隔时间单位s + public static final String GRS_ALGORITHM= "groestl"; + // Mona 出块间隔时间单位s + public static final String MONA_ALGORITHM= "Lyra2REv2"; + // NEXA 出块间隔时间单位s + public static final String NEXA_ALGORITHM= "NexaPow"; + // RXD 出块间隔时间单位s + public static final String RXD_ALGORITHM= "Sha512256D"; + + public static final String DGBQ_ALGORITHM= "DigiByte(Qubit)"; + + public static final String DGBS_ALGORITHM= "DigiByte(Skein)"; + + public static final String DGBO_ALGORITHM= "DigiByte(Odocrypt)"; + + public static final String MONERO_ALGORITHM= "randomx"; + + public static final String ALPH_ALGORITHM= "Blake3"; + + + + public static final String GRS_FULL_NAME= "Groestlcoin"; + + public static final String MONA_FULL_NAME= "Monacoin"; + + public static final String NEXA_FULL_NAME= "nexa"; + + public static final String RXD_FULL_NAME= "Radiant"; + + public static final String DGBQ_FULL_NAME= "DigiByte(qubit)"; + + public static final String DGBS_FULL_NAME= "DigiByte(skein)"; + + public static final String DGBO_FULL_NAME= "DigiByte(odocrypt)"; + + public static final String MONERO_FULL_NAME= "monero"; + + public static final String ALPH_FULL_NAME = "Alephium"; + + private static final Map ALGORITHM_MAP; + + private static final Map COINFLULLNAME_MAP; + + + static { + HashMap map = new HashMap<>(); + map.put("grs", GRS_ALGORITHM); + map.put("mona", MONA_ALGORITHM); + map.put("nexa", NEXA_ALGORITHM); + map.put("rxd", RXD_ALGORITHM); + map.put("dgbq", DGBQ_ALGORITHM); + map.put("dgbs", DGBS_ALGORITHM); + map.put("dgbo", DGBO_ALGORITHM); + map.put("monero", MONERO_ALGORITHM); + map.put("alph", ALPH_ALGORITHM); + ALGORITHM_MAP = Collections.unmodifiableMap(map); + HashMap mapFullName = new HashMap<>(); + mapFullName.put("grs", GRS_FULL_NAME); + mapFullName.put("mona", MONA_FULL_NAME); + mapFullName.put("nexa", NEXA_FULL_NAME); + mapFullName.put("rxd", RXD_FULL_NAME); + mapFullName.put("dgbq", DGBQ_FULL_NAME); + mapFullName.put("dgbs", DGBS_FULL_NAME); + mapFullName.put("dgbo", DGBO_FULL_NAME); + mapFullName.put("monero", MONERO_FULL_NAME); + mapFullName.put("alph", ALPH_FULL_NAME); + COINFLULLNAME_MAP = Collections.unmodifiableMap(mapFullName); + } + + /** + * 根据币种名称获取对应的算法 + * @param coinName 币种名称,不区分大小写 + * @return 对应的每日理论出块数,如果未找到则返回 null + */ + public static String getAlgorithm(String coinName) { + String algorithm = ALGORITHM_MAP.get(coinName.toLowerCase()); + if (StringUtils.isEmpty(algorithm)){ + return ""; + } + return algorithm; + } + + + public static String getCoinFullName(String coinName) { + String algorithm = COINFLULLNAME_MAP.get(coinName.toLowerCase()); + if (StringUtils.isEmpty(algorithm)){ + return ""; + } + return algorithm; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/BlockInterval.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/BlockInterval.java new file mode 100644 index 0000000..19d9c26 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/BlockInterval.java @@ -0,0 +1,45 @@ +package com.m2pool.lease.constant; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description 出块间隔数 + * @Date 2025/8/18 16:19 + * @Author yyb + */ +public class BlockInterval { + // GRS 出块间隔时间单位s + public static final BigDecimal GRS_BLOCK_INTERVAL = BigDecimal.valueOf(60); + // Mona 出块间隔时间单位s + public static final BigDecimal MONA_BLOCK_INTERVAL = BigDecimal.valueOf(90); + // NEXA 出块间隔时间单位s + public static final BigDecimal NEXA_BLOCK_INTERVAL = BigDecimal.valueOf(120); + // RXD 出块间隔时间单位s + public static final BigDecimal RXD_BLOCK_INTERVAL= BigDecimal.valueOf(300); + + private static final Map BLOCK_MAP; + + static { + HashMap map = new HashMap<>(); + map.put("grs", GRS_BLOCK_INTERVAL); + map.put("mona", MONA_BLOCK_INTERVAL); + map.put("nexa", NEXA_BLOCK_INTERVAL); + map.put("rxd", RXD_BLOCK_INTERVAL); + BLOCK_MAP = Collections.unmodifiableMap(map); + } + + /** + * 根据币种名称获取对应的每日理论出块数 + * @param coinName 币种名称,不区分大小写 + * @return 对应的每日理论出块数,如果未找到则返回 null + */ + public static BigDecimal getBlockCountByCoinName(String coinName) { + if (coinName == null) { + return BigDecimal.ZERO; + } + return BLOCK_MAP.get(coinName.toLowerCase()); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/CoinCharge.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/CoinCharge.java new file mode 100644 index 0000000..dc0c6f1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/CoinCharge.java @@ -0,0 +1,65 @@ +package com.m2pool.lease.constant; + +import com.m2pool.lease.dto.ChargeDto; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * @Description 币种手续费 + * @Date 2025/10/23 11:15 + * @Author yyb + */ +public enum CoinCharge { + + ETH_USDT("ETH","USDT", BigDecimal.valueOf(1)), + TRON_USDT("TRON","USDT", BigDecimal.valueOf(1)), + TRON_NEXA("TRON","NEXA", BigDecimal.valueOf(1000)); + + private final String chain; + /** 币种参数名 */ + private final String coin; + /** 手续费 */ + private final BigDecimal amount; + + + CoinCharge(String chain, String coin, BigDecimal amount) { + this.chain = chain; + this.coin = coin; + this.amount = amount; + } + /** + * 根据 chain 和 coin 查找对应的手续费,未找到则返回 1 + * @param chain 链名 + * @param coin 币种名 + * @return 对应的手续费,未找到返回 1 + */ + public static BigDecimal getChargeByChainAndCoin(String chain, String coin) { + for (CoinCharge charge : CoinCharge.values()) { + if (charge.chain.equals(chain) && charge.coin.equals(coin)) { + return charge.amount; + } + } + return BigDecimal.ONE; + } + + + /** + * 获取枚举类中所有枚举,并封装成 List + * @return 包含所有枚举信息的 ChargeDto 列表 + */ + public static List getAllChargesAsDtoList() { + List chargeDtoList = new ArrayList<>(); + for (CoinCharge charge : CoinCharge.values()) { + chargeDtoList.add(new ChargeDto( + charge.amount, + charge.chain, + charge.coin + )); + } + return chargeDtoList; + } + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/DailyBlockOutputConstant.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/DailyBlockOutputConstant.java new file mode 100644 index 0000000..1f5db3c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/DailyBlockOutputConstant.java @@ -0,0 +1,65 @@ +package com.m2pool.lease.constant; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +public class DailyBlockOutputConstant { + // GRS 每日理论出块数常量 + public static final BigDecimal GRS_BLOCK = BigDecimal.valueOf(1440); + // Mona 每日理论出块数常量 + public static final BigDecimal MONA_BLOCK = BigDecimal.valueOf(960); + // DGBS 每日理论出块数常量 + public static final BigDecimal DGBS_BLOCK = BigDecimal.valueOf(1180); + // DGBQ 每日理论出块数常量 + public static final BigDecimal DGBQ_BLOCK = BigDecimal.valueOf(1180); + // DGBO 每日理论出块数常量 + public static final BigDecimal DGBO_BLOCK = BigDecimal.valueOf(1180); + // DGB2_ODO 每日理论出块数常量 + public static final BigDecimal DGB2_ODO_BLOCK = BigDecimal.valueOf(720); + // DGB_QUBIT_A10 每日理论出块数常量 + public static final BigDecimal DGB_QUBIT_A10_BLOCK = BigDecimal.valueOf(720); + // DGB_SKEIN_A10 每日理论出块数常量 + public static final BigDecimal DGB_SKEIN_A10_BLOCK = BigDecimal.valueOf(720); + // DGB_ODO_B20 每日理论出块数常量 + public static final BigDecimal DGB_ODO_B20_BLOCK = BigDecimal.valueOf(720); + // NEXA 每日理论出块数常量 + public static final BigDecimal NEXA_BLOCK = BigDecimal.valueOf(720); + // RXD 每日理论出块数常量 + public static final BigDecimal RXD_BLOCK = BigDecimal.valueOf(288); + // ALPH 每日理论出块数常量 + public static final BigDecimal ALPH_BLOCK = BigDecimal.valueOf(5400); + // ENX 每日理论出块数常量 + public static final BigDecimal ENX_BLOCK = BigDecimal.valueOf(86400); + + private static final Map BLOCK_MAP; + + static { + BLOCK_MAP = new HashMap<>(); + BLOCK_MAP.put("grs", GRS_BLOCK); + BLOCK_MAP.put("mona", MONA_BLOCK); + BLOCK_MAP.put("dgbs", DGBS_BLOCK); + BLOCK_MAP.put("dgbq", DGBQ_BLOCK); + BLOCK_MAP.put("dgbo", DGBO_BLOCK); + BLOCK_MAP.put("dgb2_odo", DGB2_ODO_BLOCK); + BLOCK_MAP.put("dgb_qubit_a10", DGB_QUBIT_A10_BLOCK); + BLOCK_MAP.put("dgb_skein_a10", DGB_SKEIN_A10_BLOCK); + BLOCK_MAP.put("dgb_odo_b20", DGB_ODO_B20_BLOCK); + BLOCK_MAP.put("nexa", NEXA_BLOCK); + BLOCK_MAP.put("rxd", RXD_BLOCK); + BLOCK_MAP.put("alph", ALPH_BLOCK); + BLOCK_MAP.put("enx", ENX_BLOCK); + } + + /** + * 根据币种名称获取对应的每日理论出块数 + * @param coinName 币种名称,不区分大小写 + * @return 对应的每日理论出块数,如果未找到则返回 null + */ + public static BigDecimal getBlockCountByCoinName(String coinName) { + if (coinName == null) { + return BigDecimal.ZERO; + } + return BLOCK_MAP.get(coinName.toLowerCase()); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/OrderStatus.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/OrderStatus.java new file mode 100644 index 0000000..a9f1fc7 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/OrderStatus.java @@ -0,0 +1,55 @@ +package com.m2pool.lease.constant; + +/** + * @Description 普通订单状态 + * @Date 2025/9/3 16:19 + * @Author yyb + */ +public enum OrderStatus { + PENDING_PAYMENT(0, "待支付"), + FULLY_PAID(1, "(全部)已支付"), + CANCELLED(2, "已取消"), + AFTER_SALES(3, "售后状态"), + REFUNDED(4, "已退款"), + PAYMENT_TIMEOUT(5, "支付已超时"), + PAYMENT_IN_PROGRESS(6, "支付中"), + PARTIALLY_PAID(10, "部分已支付"); + + private final int code; + private final String description; + + OrderStatus(int code, String description) { + this.code = code; + this.description = description; + } + + /** + * 获取订单状态编码 + * @return 订单状态编码 + */ + public int getCode() { + return code; + } + + /** + * 获取订单状态描述 + * @return 订单状态描述 + */ + public String getDescription() { + return description; + } + + /** + * 根据编码获取对应的订单状态枚举 + * @param code 订单状态编码 + * @return 订单状态枚举,如果未找到则返回 null + */ + public static OrderStatus getByCode(int code) { + for (OrderStatus status : OrderStatus.values()) { + if (status.getCode() == code) { + return status; + } + } + return null; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/PaymentStatus.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/PaymentStatus.java new file mode 100644 index 0000000..bc3a78c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/PaymentStatus.java @@ -0,0 +1,53 @@ +package com.m2pool.lease.constant; + +/** + * @Description 支付订单状态 + * @Date 2025/9/3 16:19 + * @Author yyb + */ +public enum PaymentStatus { + PAYMENT_FAILED(0, "支付失败"), + PAYMENT_SUCCESS_FULL(1, "支付成功--全部货款已支付"), + PENDING_PAYMENT(2, "待支付"), + PAYMENT_TIMEOUT(5, "支付已超时"), + PAYMENT_IN_PROGRESS(6, "支付中"), + PAYMENT_SUCCESS_PARTIAL(10, "支付成功--已支付部分货款"); + + private final int code; + private final String description; + + PaymentStatus(int code, String description) { + this.code = code; + this.description = description; + } + + /** + * 获取支付状态编码 + * @return 支付状态编码 + */ + public int getCode() { + return code; + } + + /** + * 获取支付状态描述 + * @return 支付状态描述 + */ + public String getDescription() { + return description; + } + + /** + * 根据编码获取对应的支付状态枚举 + * @param code 支付状态编码 + * @return 支付状态枚举,如果未找到则返回 null + */ + public static PaymentStatus getByCode(int code) { + for (PaymentStatus status : PaymentStatus.values()) { + if (status.getCode() == code) { + return status; + } + } + return null; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/PowerUnit.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/PowerUnit.java new file mode 100644 index 0000000..e388fa2 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/PowerUnit.java @@ -0,0 +1,44 @@ +package com.m2pool.lease.constant; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description 单位换算 + * @Date 2025/8/18 16:19 + * @Author yyb + */ +public class PowerUnit { + + public static final String KH_UNIT = "KH/S"; + + public static final String MH_UNIT = "MH/S"; + + public static final String GH_UNIT = "GH/S"; + + public static final String TH_UNIT = "TH/S"; + + public static final String PH_UNIT = "PH/S"; + + private static final Map UNIT_MAP; + + static { + HashMap map = new HashMap<>(); + map.put(KH_UNIT, BigDecimal.valueOf(1000)); + map.put(MH_UNIT, BigDecimal.valueOf(1000 * 1000)); + map.put(GH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000)); + map.put(TH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000)); + map.put(PH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000 * 1000)); + UNIT_MAP = Collections.unmodifiableMap(map); + } + + + public static BigDecimal getPower(String unit) { + if (unit == null) { + return BigDecimal.ZERO; + } + return UNIT_MAP.get(unit); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/RabbitmqConstant.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/RabbitmqConstant.java new file mode 100644 index 0000000..2992f62 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/RabbitmqConstant.java @@ -0,0 +1,156 @@ +package com.m2pool.lease.constant; + +/** + * @Description 常量信息 + * @Date 2024/6/11 18:13 + * @Author dy + */ +public class RabbitmqConstant { + + + + /** + * 矿池代理消息队列 + */ + public static final String POOL_PROXY_QUEUE_NAME = "pool.proxy.queue"; + + /** + * 矿池代理消息correlationData(用于生成者手动ack) + */ + public static final String POOL_PROXY_CORRELATION = "pool.proxy.message"; + + + + + + + /** + * 订单超时消息 交换机 + */ + public static final String ORDER_OVERTIME_EXCHANGE_NAME = "order.overtime.exchange"; + + /** + * 订单超时消息 路由键 + */ + public static final String ORDER_OVERTIME_ROUTING_KEY = "order.overtime.routing.key"; + /** + * + * 订单超时消息 队列 + */ + public static final String ORDER_OVERTIME_QUEUE_NAME = "order.overtime.queue"; + /** + * 订单超时消息correlationData(用于生成者手动ack) + */ + public static final String ORDER_OVERTIME_CORRELATION= "order.overtime.message"; + + /** + * 死信 队列 + */ + public static final String DEAD_LETTER_QUEUE_NAME = "dead.letter.queue"; + /** + * 死信 交换机 + */ + public static final String DEAD_LETTER_EXCHANGE_NAME = "dead.letter.exchange"; + /** + * 死信 路由键 + */ + public static final String DEAD_LETTER_ROUTING_KEY = "dead.letter.routing.key"; + + + //----------------定义支付相关队列------------------------ + + /** + * 支付模块 交换机 + */ + public static final String PAY_EXCHANGE = "pay.exchange"; + + + /** + * 支付 消息队列 + */ + public static final String PAY_AUTO_QUEUE = "pay.auto.queue"; + + /** + * 支付 路由键 + */ + public static final String PAY_AUTO_ROUTING_KEY = "pay.auto.routing.key"; + + /** + * 支付 返回消息消息队列 + */ + public static final String PAY_AUTO_RETURN_QUEUE = "pay.auto.return.queue"; + + /** + * 支付 返回消息路由键 + */ + public static final String PAY_AUTO_RETURN_ROUTING_KEY = "pay.auto.return.routing.key"; + + + /** + * 余额充值 消息队列 + */ + public static final String PAY_RECHARGE_QUEUE = "pay.recharge.queue"; + + /** + * 余额充值 路由键 + * + */ + public static final String PAY_RECHARGE_ROUTING_KEY = "pay.recharge.routing.key"; + + /** + * 余额充值 返回信息消息队列 + */ + public static final String PAY_RECHARGE_RETURN_QUEUE = "pay.recharge.return.queue"; + + /** + * 余额充值 返回信息路由键 + * + */ + public static final String PAY_RECHARGE_RETURN_ROUTING_KEY = "pay.recharge.return.routing.key"; + /** + * 余额提现 消息队列 + */ + public static final String PAY_WITHDRAW_QUEUE = "pay.withdraw.queue"; + + /** + * 余额提现 路由键 + * + */ + public static final String PAY_WITHDRAW_ROUTING_KEY = "pay.withdraw.routing.key"; + + /** + * 余额提现 返回信息消息队列 + */ + public static final String PAY_WITHDRAW_RETURN_QUEUE = "pay.withdraw.return.queue"; + /** + * 余额提现 返回信息路由键 + * + */ + public static final String PAY_WITHDRAW_RETURN_ROUTING_KEY = "pay.withdraw.return.routing.key"; + + + /** + * 钱包删除 信息消息队列 + */ + public static final String DELETE_WALLET_QUEUE = "pay.remove.queue"; + /** + * 钱包删除 信息路由键 + * + */ + public static final String DELETE_WALLET_ROUTING_KEY = "pay.remove.routing.key"; + + + /** + * 钱包删除 返回信息消息队列 + */ + public static final String DELETE_WALLET_RETURN_QUEUE = "pay.remove.return.queue"; + /** + * 钱包删除 返回信息路由键 + * + */ + public static final String DELETE_WALLET_RETURN_ROUTING_KEY = "pay.remove.return.routing.key"; + + + //----------------定义支付相关队列------------------------ + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/RedisKey.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/RedisKey.java new file mode 100644 index 0000000..c64cdec --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/RedisKey.java @@ -0,0 +1,72 @@ +package com.m2pool.lease.constant; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description redis key + * @Date 2025/8/18 09:49 + * @Author yyb + */ +public class RedisKey { + // 静态不可变的 Map,存储币种名和对应价格标识 + private static final Map COIN_PRICE_MAP; + + private static final Map COIN_MHS_MAP; + + private static final Map COIN_REWARD_MAP; + static { + + Map mapPrice = new HashMap<>(); + mapPrice.put("nexa", "nexa:price"); + mapPrice.put("mona", "mona:price"); + mapPrice.put("rxd", "rxd:price"); + mapPrice.put("grs", "grs:price"); + mapPrice.put("dgbs","dgb:price"); + mapPrice.put("dgbq","dgb:price"); + mapPrice.put("dgbo","dgb:price"); + mapPrice.put("alph","alph:price"); + mapPrice.put("eth","eth:price"); + + Map mapMhs = new HashMap<>(); + mapMhs.put("nexa", "nexa:mhs"); + mapMhs.put("mona", "mona:mhs"); + mapMhs.put("rxd", "rxd:mhs"); + mapMhs.put("grs", "grs:mhs"); + mapMhs.put("dgbo","dgbo:mhs"); + mapMhs.put("dgbq","dgbq:mhs"); + mapMhs.put("dgbs","dgbs:mhs"); + mapMhs.put("alph","alph:mhs"); + + + Map mapReward = new HashMap<>(); + mapReward.put("nexa", "nexa:reward"); + mapReward.put("mona", "mona:reward"); + mapReward.put("rxd", "rxd:reward"); + mapReward.put("grs", "grs:reward"); + mapReward.put("dgbs","dgb:reward"); + mapReward.put("dgbq","dgb:reward"); + mapReward.put("dgbo","dgb:reward"); + mapReward.put("alph","alph:reward"); + COIN_PRICE_MAP = Collections.unmodifiableMap(mapPrice); + COIN_MHS_MAP = Collections.unmodifiableMap(mapMhs); + COIN_REWARD_MAP = Collections.unmodifiableMap(mapReward); + } + + /** + * 根据币种名获取对应的价格标识 + * @param coinName 币种名 + * @return 对应的价格标识,若不存在则返回 null + */ + public static String getPiceKey(String coinName) { + return COIN_PRICE_MAP.get(coinName); + } + + public static String getMhsKey(String coinName) { + return COIN_MHS_MAP.get(coinName); + } + public static String getRewardKey(String coinName) { + return COIN_REWARD_MAP.get(coinName); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/ResponseConstant.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/ResponseConstant.java new file mode 100644 index 0000000..95d7ead --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/constant/ResponseConstant.java @@ -0,0 +1,92 @@ +package com.m2pool.lease.constant; + +/** + * @Description 常量信息 + * @Date 2024/6/11 18:13 + * @Author dy + */ +public class ResponseConstant { + /** + * 成功标记 + */ + public static final Integer SUCCESS = 200; + + /** + * 失败标记 + */ + public static final Integer FAIL = 500; + + /** + * 登录成功状态 + */ + public static final String LOGIN_SUCCESS_STATUS = "0"; + + /** + * 登录失败状态 + */ + public static final String LOGIN_FAIL_STATUS = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 当前记录起始索引 + */ + public static final String PAGE_NUM = "pageNum"; + + /** + * 每页显示记录数 + */ + public static final String PAGE_SIZE = "pageSize"; + + /** + * 排序列 + */ + public static final String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排序的方向 "desc" 或者 "asc". + */ + public static final String IS_ASC = "isAsc"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 验证码有效期(分钟) + */ + public static final long CAPTCHA_EXPIRATION = 2; + + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseMachineAvgPowerController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseMachineAvgPowerController.java new file mode 100644 index 0000000..15740b2 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseMachineAvgPowerController.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 矿池nexa机器实时平均算力 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-29 + */ +@RestController +@RequestMapping("/machine/avg/power") +public class LeaseMachineAvgPowerController { + +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseMachinePowerController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseMachinePowerController.java new file mode 100644 index 0000000..5fb106d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseMachinePowerController.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 已售商品矿工实时算力表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-25 + */ +@RestController +@RequestMapping("/machine/power") +public class LeaseMachinePowerController { + +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseOrderInfoController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseOrderInfoController.java new file mode 100644 index 0000000..714ec68 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseOrderInfoController.java @@ -0,0 +1,84 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.common.security.annotation.RequiresLogin; +import com.m2pool.lease.dto.OrderInfoDto; +import com.m2pool.lease.dto.PageResult; +import com.m2pool.lease.dto.PaymentRecordDto; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.service.LeaseOrderInfoService; +import com.m2pool.lease.vo.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 订单表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Api(tags = "订单控制器") +@RestController +@RequestMapping("/order/info") +public class LeaseOrderInfoController { + + + @Resource + private LeaseOrderInfoService leaseOrderInfoService; + + @ApiOperation("创建订单及订单详情 + 支付订单(返回二维码内容)") + @PostMapping("/addOrders") + public Result addOrders(@RequestBody OrderAndCodeVo orderAndCodeVo) { + return leaseOrderInfoService.addOrders(orderAndCodeVo); + } + + @ApiOperation("订单支付超时--再次购买功能") + @PostMapping("/buyAgain") + @Deprecated + public Result> buyAgain(@RequestBody List orderInfoVoList) { + return leaseOrderInfoService.buyAgain(orderInfoVoList); + } + + @ApiOperation("查询订单列表(买家)") + @PostMapping("/getOrdersByStatus") + public PageResult getOrdersByStatus(@RequestBody OrderInfoStateVo orderInfoStateVo) { + return leaseOrderInfoService.getOrdersByStatus(orderInfoStateVo); + } + + + @ApiOperation("卖家已售出订单列表(卖家)") + @PostMapping("/getOrdersByStatusForSeller") + public PageResult getOrdersByStatusForSeller(@RequestBody OrderInfoStateVo orderInfoStateVo) { + return leaseOrderInfoService.getOrdersByStatusForSeller(orderInfoStateVo); + } + + + @ApiOperation("根据订单id查询订单信息") + @PostMapping("/getOrdersByIds") + public Result getOrdersByIds(@RequestBody OrderVo orderVo) { + return leaseOrderInfoService.getOrdersByIds(orderVo); + } + + @ApiOperation("取消订单(如果有支付订单同时取消)") + @PostMapping("/cancelOrder") + public Result cancelOrder(@RequestBody OrderVo orderVo) { + return leaseOrderInfoService.cancelOrder(orderVo); + } + + @ApiOperation("生成订单时获取用户选择的支付币种 实时币价") + @PostMapping("/getCoinPrice") + public Result getCoinPrice(@RequestBody CoinVo coinVo){ + return leaseOrderInfoService.getCoinPrice(coinVo); + } +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeasePaymentRecordController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeasePaymentRecordController.java new file mode 100644 index 0000000..19c25fb --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeasePaymentRecordController.java @@ -0,0 +1,65 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.common.security.annotation.RequiresLogin; +import com.m2pool.lease.dto.PaymentCallbackDto; +import com.m2pool.lease.dto.PaymentRecordDto; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.service.LeasePaymentRecordService; +import com.m2pool.lease.vo.CheckPayStatusVo; +import com.m2pool.lease.vo.OrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + *

+ * 支付记录表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Api(tags = "支付记录控制器") +@RestController +@RequestMapping("/payment/record") +public class LeasePaymentRecordController { + + @Resource + private LeasePaymentRecordService leasePaymentRecordService; + + @ApiOperation("根据订单详情信息生成 支付订单 + 根据返回的集合生成多个支付二维码") + @PostMapping("/addPayOrder") + @Deprecated + public Result> addPayOrder(@RequestBody OrderVo orderVo) { + return leasePaymentRecordService.addPayOrder(orderVo); + } + + + @ApiOperation("根据订单id找到支付订单") + @PostMapping("/getPayOrderByOrderId") + public Result> getPayOrderByOrderId(@RequestBody OrderVo orderVo) { + return leasePaymentRecordService.getPayOrderByOrderId(orderVo); + } + + + @ApiOperation("支付回调结果---根据订单id批量校验本次支付是否成功") + @PostMapping("/paymentCallbackBatch") + @Deprecated + public Result> paymentCallbackBatch(@RequestBody List checkPayStatusVoList) { + return leasePaymentRecordService.paymentCallbackBatch(checkPayStatusVoList); + } + + @ApiOperation("支付回调结果----根据支付id校验支付是否成功") + @PostMapping("/paymentCallbackByPayId") + @Deprecated + public Result paymentCallbackByPayId(@RequestBody CheckPayStatusVo checkPayStatusVo) { + return leasePaymentRecordService.paymentCallbackByPayId(checkPayStatusVo); + } + + +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseProductController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseProductController.java new file mode 100644 index 0000000..44f4a2b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseProductController.java @@ -0,0 +1,100 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.lease.dto.*; +import com.m2pool.lease.service.LeaseProductService; +import com.m2pool.lease.service.LeaseUserOwnedProductService; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.ProductPageVo; +import com.m2pool.lease.vo.ProductURDVo; +import com.m2pool.lease.vo.UserOwnedProductVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + *

+ * 商品表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Api(tags = "商品控制器") +@RestController +@RequestMapping("/product") +public class LeaseProductController { + @Autowired + private LeaseProductService leaseProductService; + + + @Resource + private LeaseUserOwnedProductService leaseUserOwnedProductService; + @ApiOperation("查询商品列表(不包含商品对应的售卖机器详情列表)") + @PostMapping("/getList") + public PageResult getProductList(@RequestBody(required = false) ProductPageVo productPageVo) { + if (productPageVo == null){ + productPageVo = new ProductPageVo(); + } + return leaseProductService.getProductList(productPageVo); + } + + + @ApiOperation("根据商品id查询单个商品详情信息") + @PostMapping("/getMachineInfoById") + public Result getMachineInfoById(@RequestBody BaseVo baseVo) { + return leaseProductService.getMachineInfoById(baseVo); + } + + + + @ApiOperation("查询单个商品详情(包含商品对应的售卖机器详情列表)") + @PostMapping("/getMachineInfo") + public Result getProductMachineInfo(@RequestBody BaseVo BaseVo) { + return leaseProductService.getProductMachineInfo(BaseVo.getId()); + } + + + + @ApiOperation("新增商品(不包含商品对应的售卖机器)") + @PostMapping("/add") + public Result addProduct(@RequestBody ProductURDVo productURDVo) { + return leaseProductService.addProduct(productURDVo); + } + + @ApiOperation("编辑商品 + 商品上下架(不包含商品对应的售卖机器)") + @PostMapping("/update") + public Result updateProduct(@RequestBody ProductURDVo productURDVo) { + return leaseProductService.updateProduct(productURDVo); + } + + @ApiOperation("删除商品(包含商品对应的售卖机器)") + @PostMapping("/delete") + public Result deleteProduct(@RequestBody BaseVo baseVo) { + return leaseProductService.deleteProduct(baseVo.getId()); + } + + + @ApiOperation("用户查询当前自身已购商品列表") + @PostMapping("/getOwnedList") + public PageResult getOwnedList(@RequestBody(required = false) UserOwnedProductVo userOwnedProductVo) { + if (userOwnedProductVo == null){ + userOwnedProductVo = new UserOwnedProductVo(); + } + return leaseUserOwnedProductService.getOwnedList(userOwnedProductVo); + } + + + @ApiOperation("根据id查询当前自身已购商品详情") + @PostMapping("/getOwnedById") + public Result getOwnedById(@RequestBody BaseVo baseVo) { + return leaseUserOwnedProductService.getOwnedById(baseVo); + } +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseProductMachineController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseProductMachineController.java new file mode 100644 index 0000000..2ded01b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseProductMachineController.java @@ -0,0 +1,85 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.common.security.annotation.RequiresLogin; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.service.LeaseProductMachineService; +import com.m2pool.lease.vo.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +/** + *

+ * 商品表对应的物品机器表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Api(tags = "商品矿机控制器(库存控制器)") +@RestController +@RequestMapping("/product/machine") +public class LeaseProductMachineController { + + + @Resource + private LeaseProductMachineService leaseProductMachineService; + + @ApiOperation("根据 登录账户 获取挖矿账户及挖矿币种集合----用于用户为商品添加实际出售机器库存") + @PostMapping("/getUserMinersList") + public Result>> getUserMinersList(@RequestBody UserMinerVo userMinerVo) { + return leaseProductMachineService.getUserMinersList(userMinerVo); + } + + @ApiOperation("根据挖矿账户获取对应的 矿机机器编码集合----用于用户为商品添加实际出售机器库存") + @PostMapping("/getUserMachineList") + public Result> getUserMachineList(@RequestBody UserMinerVo userMinerVo) { + return leaseProductMachineService.getUserMachineList(userMinerVo); + } + + + + + @ApiOperation("根据商品id查询商品矿机列表----用于卖方修改矿机信息") + @PostMapping("/getMachineListForUpdate") + public PageResult getMachineListForUpdate(@RequestBody ProductForUpdateMachineVo productForUpdateMachineVo) { + return leaseProductMachineService.getMachineListForUpdate(productForUpdateMachineVo); + } + + + @ApiOperation("单个新增或批量新增出售机器") + @PostMapping("/addSingleOrBatchMachine") + public Result addSingleOrBatchMachine(@RequestBody ProductMachineParamsVo productMachineParamsVoList) { + return leaseProductMachineService.addSingleOrBatchMachine(productMachineParamsVoList); + } + + @ApiOperation("单个/批量 编辑矿机 + 矿机上下架") + @PostMapping("/updateMachine") + public Result updateMachine(@RequestBody List productUpdateMachineVoList) { + return leaseProductMachineService.updateMachine(productUpdateMachineVoList); + } + + @ApiOperation("根据矿机id 删除商品矿机") + @PostMapping("/delete") + public Result deleteMachine(@RequestBody BaseVo baseVo) { + return leaseProductMachineService.deleteMachine(baseVo); + } + + + //@ApiOperation("价格计算器---添加机器到商品中时需要给一个价格") + //@PostMapping("/calculatePrice") + //public Result calculatePrice(@RequestBody PriceCalculateVo priceCalculateVo) { + // return leaseProductMachineService.calculatePrice(priceCalculateVo); + //} + + +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseShopController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseShopController.java new file mode 100644 index 0000000..b3cfbac --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseShopController.java @@ -0,0 +1,173 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.lease.dto.*; +import com.m2pool.lease.service.LeaseShopService; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.ShopConfigVo; +import com.m2pool.lease.vo.ShopVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + *

+ * 店铺表 前端控制器 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Api(tags = "店铺控制器") +@RestController +@RequestMapping("/shop") +public class LeaseShopController { + + @Resource + private LeaseShopService leaseShopService; + + /** + * 新增店铺 + * @param shopVo 店铺信息 + * @return 操作结果 + */ + @ApiOperation("新增店铺") + @PostMapping("/addShop") + public Result addShop(@RequestBody ShopVo shopVo) { + + return leaseShopService.addShop(shopVo); + } + + + /** + * 修改店铺 + * @param shopVo 店铺信息 + * @return 操作结果 + */ + @ApiOperation("根据店铺id修改店铺") + @PostMapping("/updateShop") + public Result updateShop(@RequestBody ShopVo shopVo) { + return leaseShopService.updateShop(shopVo); + } + + /** + * 关闭/打开店铺 + * @param baseVo 店铺 ID + * @return 操作结果 + */ + @ApiOperation("根据店铺id关闭店铺") + @PostMapping("/closeShop") + public Result closeShop(@RequestBody BaseVo baseVo) { + return leaseShopService.closeShop(baseVo); + } + + /** + * 根据用户邮箱查询店铺 + * @return 店铺信息 + */ + @ApiOperation("根据用户邮箱查询店铺") + @GetMapping("/getShopByUserEmail") + public Result getShopByUserEmail() { + return leaseShopService.getShopByUserEmail(); + } + + /** + * 根据店铺id查询店铺 + * @param baseVo 店铺 ID + * @return 店铺信息 + */ + @ApiOperation("根据店铺id查询店铺") + @PostMapping("/getShopById") + public Result getShopById(@RequestBody BaseVo baseVo) { + return leaseShopService.getShopById(baseVo); + } + + + + /** + * 删除店铺(逻辑删除) + * @param baseVo 店铺 ID + * @return 操作结果 + */ + @ApiOperation("删除店铺") + @PostMapping("/deleteShop") + public Result deleteShop(@RequestBody BaseVo baseVo) { + return leaseShopService.deleteShop(baseVo); + } + + + + @ApiOperation("根据店铺id获取到商品列表") + @PostMapping("/getProductListById") + public Result> getProductListById(@RequestBody BaseVo baseVo) { + return leaseShopService.getProductListById(baseVo); + } + /** + * 根据店铺id 查询配置信息列表 + * @param baseVo + * @return 操作结果 + */ + @ApiOperation("钱包配置----根据店铺id查询收款钱包绑定信息列表") + @PostMapping("/getShopConfig") + public Result> getShopConfig(@RequestBody BaseVo baseVo) { + return leaseShopService.getShopConfig(baseVo); + } + + /** + * 新增商铺配置 (新增配置时,如果没有指定商品,就默通用配置) + * @param shopConfigVo 商铺配置信息 + * @return 操作结果 + */ + @ApiOperation("钱包配置---新增商铺收款钱包绑定配置") + @PostMapping("/addShopConfig") + public Result addShopConfig(@RequestBody ShopConfigVo shopConfigVo) { + return leaseShopService.addShopConfig(shopConfigVo); + } + + + + /** + * 修改配置 + * @param shopConfigVo 商铺配置信息 + * @return 操作结果 + */ + @ApiOperation("钱包配置----根据配置id 修改商铺收款钱包配置") + @PostMapping("/updateShopConfig") + public Result updateShopConfig(@RequestBody ShopConfigVo shopConfigVo) { + return leaseShopService.updateShopConfig(shopConfigVo); + } + + /** + * 删除配置(逻辑删除) + * @param baseVo 配置 ID + * @return 操作结果 + */ + @ApiOperation("钱包配置----根据配置id 删除商铺收款钱包配置") + @PostMapping("/deleteShopConfig") + public Result deleteShopConfig(@RequestBody BaseVo baseVo) { + return leaseShopService.deleteShopConfig(baseVo); + } + + @ApiOperation("钱包配置(用于充值选择链和币种)----获取链(一级)和币(二级) 下拉列表(获取本系统支持的链和币种)") + @PostMapping("/getChainAndList") + public Result> getChainAndList(){ + return leaseShopService.getChainAndList(); + } + + @ApiOperation("钱包配置(用于下单选择商家支持的链和币种)----获取链(一级)和币(二级) 下拉列表(获取本商家支持的链和币种)") + @PostMapping("/getChainAndListForSeller") + public Result> getChainAndListForSeller(@RequestBody BaseVo baseVo){ + return leaseShopService.getChainAndListForSeller(baseVo); + } + + + @ApiOperation("钱包配置(用于修改卖家钱包地址)----获取链(一级)和币(二级) 下拉列表(获取本系统支持的链和币种)") + @PostMapping("/getChainAndCoin") + public Result getChainAndCoin(@RequestBody BaseVo baseVo){ + return leaseShopService.getChainAndCoin(baseVo); + } +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseShoppingCartController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseShoppingCartController.java new file mode 100644 index 0000000..0a3ff3e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseShoppingCartController.java @@ -0,0 +1,76 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.lease.dto.PageResult; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.dto.ShopCartDto; +import com.m2pool.lease.service.LeaseShoppingCartService; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.PageVo; +import com.m2pool.lease.vo.ProductAndMachineVo; +import com.m2pool.lease.vo.ShoppingCartInfoURDVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +/** + *

+ * 购物车表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Api(tags = "购物车表控制器") +@RestController +@RequestMapping("/shopping/cart") +public class LeaseShoppingCartController { + + @Resource + private LeaseShoppingCartService leaseShoppingCartService; + + @ApiOperation("添加商品到购物车(批量+单个)") + @PostMapping("/addGoods") + public Result addGoods(@RequestBody List shoppingCartInfoURDVoList) { + return leaseShoppingCartService.addGoods(shoppingCartInfoURDVoList); + } + + + @ApiOperation("查询购物车中商品列表") + @PostMapping("/getGoodsList") + public PageResult getGoodsList(@RequestBody(required = false) PageVo pageVo) { + if (pageVo == null){ + pageVo = new PageVo(); + } + return leaseShoppingCartService.getGoodsList(pageVo); + } + + @ApiOperation("删除购物车中商品") + @PostMapping("/deleteGoods") + @Deprecated + public Result deleteGoods(@RequestBody BaseVo baseVo) { + return leaseShoppingCartService.deleteGoods(baseVo); + } + + @ApiOperation("批量删除购物车中商品") + @PostMapping("/deleteBatchGoods") + public Result deleteBatchGoods(@RequestBody List baseVoList) { + return leaseShoppingCartService.deleteBatchGoods(baseVoList); + } + + @ApiOperation("批量删除购物车中已下架商品") + @PostMapping("/deleteBatchGoodsForIsDelete") + public Result deleteBatchGoodsForIsDelete() { + return leaseShoppingCartService.deleteBatchGoodsForIsDelete(); + } + + + +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseUserController.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseUserController.java new file mode 100644 index 0000000..8a8fbf1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/controller/LeaseUserController.java @@ -0,0 +1,102 @@ +package com.m2pool.lease.controller; + + +import com.m2pool.common.security.annotation.RequiresLogin; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.service.LeaseUserService; +import com.m2pool.lease.vo.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +/** + *

+ * 用户表 前端控制器 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Api(tags = "用户控制器") +@RestController +@RequestMapping("/user") +public class LeaseUserController { + + @Resource + private LeaseUserService leaseUserService; + @PostMapping("/login") + @ApiOperation(value = "用户登录/注册") + @Deprecated + public Result login(@RequestBody UserURDVo userURDVo){ + return leaseUserService.login(userURDVo); + } + + + @PostMapping("/bindWallet") + @ApiOperation(value = "买家:充值步骤选择链和钱包后自动绑定钱包") + public Result bindWallet(@RequestBody ChainAndCoinVo chainAndCoinVo){ + return leaseUserService.bindWallet(chainAndCoinVo); + } + + @PostMapping("/getWalletInfo") + @ApiOperation(value = "获取用户相关钱包信息") + public Result> getWalletInfo() { + return leaseUserService.getWalletInfo(); + } + + + @PostMapping("/withdrawBalance") + @ApiOperation(value = "申请余额提现") + public Result withdrawBalance(@RequestBody BalanceVo balanceVo){ + return leaseUserService.withdrawBalance(balanceVo); + } + + + @PostMapping("/balanceWithdrawList") + @ApiOperation(value = "买家:余额提现记录列表") + @Deprecated + public PageResult balanceWithdrawList(@RequestBody BalancePageVo balancePageVo){ + return leaseUserService.balanceWithdrawList(balancePageVo); + } + + + @PostMapping("/balanceRechargeList") + @ApiOperation(value = "买家:余额充值记录列表") + @Deprecated + public PageResult balanceRechargeList(@RequestBody BalancePageVo balancePageVo){ + return leaseUserService.balanceRechargeList(balancePageVo); + } + + @PostMapping("/balancePayList") + @ApiOperation(value = "卖家:钱包交易(收款)记录列表") + public PageResult balancePayList(@RequestBody BalancePageVo balancePageVo){ + return leaseUserService.balancePayList(balancePageVo); + } + + @PostMapping("/transactionRecord") + @ApiOperation(value = "买家:交易流水(支付,提现,充值)") + public PageResult transactionRecord(@RequestBody RecordTypePageVo recordTypePageVo){ + return leaseUserService.transactionRecord(recordTypePageVo); + } + + @PostMapping("/getRecentlyTransaction") + @ApiOperation(value = "最近5条交易") + public Result> getRecentlyTransaction(){ + return leaseUserService.getRecentlyTransaction(); + } + + + @PostMapping("/getCharge") + @ApiOperation(value = "获取系统支持的交易手续费") + @Deprecated + public Result> getCharge(){ + return leaseUserService.getCharge(); + } +} + diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ChainListDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ChainListDto.java new file mode 100644 index 0000000..224e07e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ChainListDto.java @@ -0,0 +1,53 @@ +package com.m2pool.lease.dto; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @Description 币种实时收益实体类 + * @Date 2024/6/14 15:57 + * @Author dy + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(description = "链(一级) 下拉列表返回对象",value = "ChainListDto") +public class ChainListDto { + + + @ApiModelProperty(value = "链名value") + private String value; + + @ApiModelProperty(value = "地址") + private String address; + + @ApiModelProperty(value = "联名标签") + private String label; + + @ApiModelProperty(value = "币(二级) 下拉列表") + private List children; + + + @Data + @ApiModel(description = "币(二级) 下拉列表返回对象",value = "CoinListDto") + public static class CoinListDto{ + @ApiModelProperty(value = "币种value") + private String value; + + @ApiModelProperty(value = "币种label") + private String label; + + @ApiModelProperty(value = "币种是否绑定(只用于卖家钱包绑定页面相关接口) 0 未绑定 1 已绑定") + private Integer hasBind; + } + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ChargeDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ChargeDto.java new file mode 100644 index 0000000..1cd5f50 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ChargeDto.java @@ -0,0 +1,37 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 余额提现请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "交易费接口",value = "ChargeDto") +public class ChargeDto { + + @ApiModelProperty(value = "手续费",required = true) + private BigDecimal amount; + + @ApiModelProperty(value = "链",required = true) + private String chain; + + @ApiModelProperty(value = "币种",required = true) + private String coin; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/CheckAddressDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/CheckAddressDto.java new file mode 100644 index 0000000..3d7de21 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/CheckAddressDto.java @@ -0,0 +1,35 @@ +package com.m2pool.lease.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @Description 币种实时收益实体类 + * @Date 2024/6/14 15:57 + * @Author dy + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CheckAddressDto { + + /** + * 地址 + */ + private String fromAddress; + + private String fromChain; + + private String fromSymbol; + /** + * 半年内是否有操作 + */ + private String hasOperator; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/CoinFullDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/CoinFullDto.java new file mode 100644 index 0000000..90474c0 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/CoinFullDto.java @@ -0,0 +1,32 @@ +package com.m2pool.lease.dto; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 币种实时收益实体类 + * @Date 2024/6/14 15:57 + * @Author dy + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CoinFullDto { + + private String chainValue; + + private String chainLabel; + + + private String coinValue; + + private String coinLabel; + + private Integer hasBind; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/HasPayTotalDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/HasPayTotalDto.java new file mode 100644 index 0000000..95c3376 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/HasPayTotalDto.java @@ -0,0 +1,38 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 支付订单返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "已支付和理论支付总金额返回对象",value = "HasPayTotalDto") +public class HasPayTotalDto { + + + /** + * 理论支付金额 + */ + private BigDecimal totalAmount; + + /** + * 实际支付金额 + */ + private BigDecimal totalRealAmount; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/HourIncomeDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/HourIncomeDto.java new file mode 100644 index 0000000..a5a315a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/HourIncomeDto.java @@ -0,0 +1,47 @@ +package com.m2pool.lease.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @Description 币种实时收益实体类 + * @Date 2024/6/14 15:57 + * @Author dy + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class HourIncomeDto{ + + private Long id; + + /** + * 挖矿账户 + */ + private String user; + + /** + * 矿工编号 + */ + private String miner; + + /** + * 挖矿收益nexa 币 + */ + private BigDecimal income; + + /** + * 挖矿收益 稳定币usdt + */ + private BigDecimal usdtIncome; + + private LocalDateTime createTime; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/MachinePowerDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/MachinePowerDto.java new file mode 100644 index 0000000..6437d4a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/MachinePowerDto.java @@ -0,0 +1,61 @@ +package com.m2pool.lease.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 已售商品矿工实时算力表 + *

+ * + * @author yyb + * @since 2025-07-25 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MachinePowerDto{ + + /** + * ID + */ + private Long id; + + /** + * 挖矿账户 + */ + private String user; + + /** + * 矿工 + */ + private String miner; + + /** + * 记录时间(每五分钟整点) + */ + private LocalDateTime date; + + /** + * 五分钟一次的矿工矿机算力 + */ + private BigDecimal accepts; + + /** + * 矿机在离线状态 离线offline 在线online + */ + private String state; + + /** + * 实际记录时间 + */ + private LocalDateTime lastSubmit; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderInfoDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderInfoDto.java new file mode 100644 index 0000000..e7f2f78 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderInfoDto.java @@ -0,0 +1,95 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 订单详情返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单详情返回对象",value = "OrderInfoDto") +public class OrderInfoDto { + + /** + * 订单 ID + */ + @ApiModelProperty(value = "订单 ID") + private Long id; + + @ApiModelProperty(value = "店铺id") + private Long shopId; + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单号") + private String orderNumber; + + /** + * 用户id + */ + @ApiModelProperty(value = "用户id") + private String userId; + /** + * 订单总价 + */ + @ApiModelProperty(value = "订单总价") + private BigDecimal totalPrice; + + ///** + // * 收货地址 + // */ + //private String address; + + /** + * 订单状态 0待付款 1待发货 2待收货 3待评价 4已完成 5取消订单 + */ + @ApiModelProperty(value = "订单状态 7 订单进行中 8 订单已完成") + private Integer status; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + + // ---------------------------------------------- 一个普通订单对应一个支付订单(多个封装下面四个字段为一个对象,并返回list)---------------------------------------------------------------------- + + + @ApiModelProperty(value = "二维码图片") + private String img; + + @ApiModelProperty(value = "需支付总金额") + private BigDecimal amount; + + @ApiModelProperty(value = "已支付金额") + private String payAmount; + + @ApiModelProperty(value = "未支付金额") + private Double noPayAmount; + + //---------------------------------------------- 一个普通订单对应一个支付订单(多个封装下面四个字段为一个对象,并返回list)- ---------------------------------------------------------------------- + /** + * 订单详情 + */ + @ApiModelProperty(value = "订单详情") + private List orderItemDtoList; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderItemDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderItemDto.java new file mode 100644 index 0000000..92d792c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderItemDto.java @@ -0,0 +1,85 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 订单列表返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单列表返回对象",value = "LeaseOrderItemDto") +public class OrderItemDto { + + /** + * 订单 ID + */ + @ApiModelProperty(value = "订单 ID") + private Long orderId; + + @ApiModelProperty(value = "店铺id") + private Long shopId; + + /** + * 商品 ID + */ + @ApiModelProperty(value = "商品 ID") + private Long productId; + + /** + * 机器id + */ + @ApiModelProperty(value = "机器id") + private Long productMachineId; + + /** + * 商品租期天数 + */ + @ApiModelProperty(value = "商品租期天数") + private Integer leaseTime; + + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称") + private String name; + /** + * 商品图片路径 + */ + @ApiModelProperty(value = "商品图片路径") + private String image; + + + /** + * 收货地址(模拟) + */ + @ApiModelProperty(value = "收货地址(模拟)") + private String address; + + + @ApiModelProperty(value = "机器单价") + private BigDecimal price; + + /** + * 支付币种 + */ + @ApiModelProperty(value = "支付币种") + private String payCoin; + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderStatusDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderStatusDto.java new file mode 100644 index 0000000..98e7308 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/OrderStatusDto.java @@ -0,0 +1,36 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 订单状态修改返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单状态修改返回对象",value = "OrderStatusDto") +public class OrderStatusDto { + + /** + * 订单 ID + */ + @ApiModelProperty(value = "订单 ID") + private Long orderId; + + + @ApiModelProperty(value = "订单主表状态") + private Integer orderInfoStatus; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PageResult.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PageResult.java new file mode 100644 index 0000000..2abd229 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PageResult.java @@ -0,0 +1,70 @@ +package com.m2pool.lease.dto; + +import com.github.pagehelper.PageInfo; +import com.m2pool.lease.constant.ResponseConstant; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Description 表格分页数据对象 + * @Date 2024/6/13 11:59 + * @Author dy + */ +@Data +@NoArgsConstructor +@ApiModel(description = "分页返回对象") +public class PageResult implements Serializable +{ + private static final long serialVersionUID = 1L; + + + /** 成功 */ + public static final int SUCCESS = ResponseConstant.SUCCESS; + + /** 失败 */ + public static final int FAIL = ResponseConstant.FAIL; + + /** 总记录数 */ + @ApiModelProperty(value = "总记录数", example = "1") + private long total; + + /** 总页数 */ + @ApiModelProperty(value = "总页数", example = "1") + private long totalPage; + + /** 列表数据 */ + @ApiModelProperty(value = "查询结果集合") + private List rows; + + /** 消息状态码 */ + @ApiModelProperty(value = "消息状态码", example = "200") + private int code; + + /** 消息内容 */ + @ApiModelProperty(value = "查询结果描述", example = "成功") + private String msg; + + public static PageResult success(List data) + { + return setPageResult(data, SUCCESS, "成功"); + } + + public static PageResult fail(List data, String msg) + { + return setPageResult(data, FAIL, msg); + } + + private static PageResult setPageResult(List data, int code, String msg) + { + PageResult rspData = new PageResult(); + rspData.setCode(SUCCESS); + rspData.setRows(data); + rspData.setMsg("查询成功"); + return rspData; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayConfigDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayConfigDto.java new file mode 100644 index 0000000..24880dd --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayConfigDto.java @@ -0,0 +1,46 @@ +package com.m2pool.lease.dto; + +import com.m2pool.lease.vo.BaseVo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 店铺商品配置返回对象 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品收款钱包配置",value = "PayConfigDto") +public class PayConfigDto { + + + /** + * nexa rxd dgbo dgbq dgbs alph enx grs mona usdt + */ + @ApiModelProperty(value = "支持的支付币种") + private String payCoin; + + + /** + * 卖方对应收款钱包 + */ + @ApiModelProperty(value = "币种图标") + private String payCoinImage; + + + @ApiModelProperty(value = "链") + private String payChain; + + + private Long shopId; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayOrderDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayOrderDto.java new file mode 100644 index 0000000..3b431fb --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayOrderDto.java @@ -0,0 +1,48 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 支付订单返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付订单返回对象",value = "PayOrderDto") +public class PayOrderDto { + + /** + * 支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd + */ + @ApiModelProperty(value = "支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd") + private String payCoin; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "支付金额") + private BigDecimal amount; + + + /** + * 支付地址 + */ + @ApiModelProperty(value = "支付地址") + private String payAddress; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayRechargeMessageDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayRechargeMessageDto.java new file mode 100644 index 0000000..b4f0dd7 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayRechargeMessageDto.java @@ -0,0 +1,78 @@ +package com.m2pool.lease.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 充值记录表 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "余额充值返回对象",value = "PayRechargeMessageDto" ) +public class PayRechargeMessageDto { + + + + private Long id; + + + /** + * 充值地址 + */ + @ApiModelProperty(value = "充值地址(官方自动生成绑定地址)") + private String address; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "充值金额") + private BigDecimal amount; + + + /** + * 币种 + */ + @ApiModelProperty(value = "币种") + private String fromSymbol; + + /** + * 链名称 + */ + @ApiModelProperty(value = "链名称") + private String fromChain; + + /** + * 充值时间 + */ + @ApiModelProperty(value = "充值到账时间)") + private LocalDateTime createTime; + + + /** + * 0 充值失败 1 充值成功 2 充值中 + */ + @ApiModelProperty(value = "充值状态 0 充值失败 1 充值成功 2 充值中 3 校验失败") + private Integer status; + + /** + * 交易hash + */ + @ApiModelProperty(value = "交易hash") + private String txHash; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayRecordMessageDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayRecordMessageDto.java new file mode 100644 index 0000000..fb28e05 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayRecordMessageDto.java @@ -0,0 +1,112 @@ +package com.m2pool.lease.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 支付消息记录表 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付返回对象",value = "PayRecordMessageDto" ) +public class PayRecordMessageDto { + + + /** + * 消息ID + */ + @ApiModelProperty(value = "消息ID") + private String queueId; + + /** + * 买家充值地址 + */ + @ApiModelProperty(value = "买家钱包地址") + private String fromAddress; + + /** + * 卖家地址(卖家自定义地址) + */ + @ApiModelProperty(value = "收款地址(卖家自定义地址)") + private String toAddress; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "理论支付支付金额") + private BigDecimal amount; + + /** + *实际支付金额(根据一天内预估算力和实际算力差值计算得来,并且已经真实支付成功的金额) + */ + @ApiModelProperty(value = "实际支付金额(根据一天内预估算力和实际算力差值计算得来,并且已经真实支付成功的金额)") + private BigDecimal realAmount; + /** + * 卖家钱包币种 + */ + @ApiModelProperty(value = "收款钱包币种") + private String toSymbol; + + /** + * 卖家钱包链名称 + */ + @ApiModelProperty(value = "收款钱包链名称") + private String toChain; + + + /** + * 买家钱包币种 + */ + @ApiModelProperty(value = "买家钱包币种") + private String fromSymbol; + + /** + * 买家钱包链名称 + */ + @ApiModelProperty(value = "买家钱包链名称") + private String fromChain; + + /** + * 交易hash + */ + @ApiModelProperty(value = "交易hash") + private String txHash; + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单号") + private String orderId; + + /** + * 支付时间 + */ + @ApiModelProperty(value = "支付时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty(value = "支付成功/失败/证书校验失败时间") + private LocalDateTime updateTime; + + /** + * 0 支付失败 1 支付成功 2 等待校验 3 证书校验失败 + */ + @ApiModelProperty(value = "支付状态 0 支付失败 1 支付成功 2 待校验 3 校验失败") + private Integer status; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayWithdrawMessageDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayWithdrawMessageDto.java new file mode 100644 index 0000000..7789f58 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PayWithdrawMessageDto.java @@ -0,0 +1,98 @@ +package com.m2pool.lease.dto; + +import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 余额提现返回对象 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "余额提现返回对象",value = "PayWithdrawMessageDto" ) +public class PayWithdrawMessageDto { + + private Long id; + + + /** + * 用户充值地址 + */ + @ApiModelProperty(value = "用户充值地址") + private String fromAddress; + + /** + * 提现地址(用户自定义) + */ + @ApiModelProperty(value = "提现地址(用户自定义)") + private String toAddress; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "提现金额") + private BigDecimal amount; + + /** + * 币种 + */ + @ApiModelProperty(value = "币种") + private String toSymbol; + + /** + * 链名称 + */ + @ApiModelProperty(value = "链名称") + private String toChain; + + + /** + * 币种 + */ + @ApiModelProperty(value = "币种") + private String fromSymbol; + + /** + * 链名称 + */ + @ApiModelProperty(value = "链名称") + private String fromChain; + + /** + * 充值时间 + */ + @ApiModelProperty(value = "提现时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty(value = "提现完成时间") + private LocalDateTime updateTime; + + /** + * 0 支付失败 1 支付成功 2 支付中 + */ + @ApiModelProperty(value = "记录状态 提现业务: 0 提现失败 1 提现成功 2 提现中 3 校验失败") + private Integer status; + + /** + * 交易hash + */ + @ApiModelProperty(value = "交易hash") + private String txHash; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PaymentCallbackDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PaymentCallbackDto.java new file mode 100644 index 0000000..8b76b01 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PaymentCallbackDto.java @@ -0,0 +1,42 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 支付回调结果返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付回调结果返回对象",value = "PaymentCallbackDto") +public class PaymentCallbackDto { + + @ApiModelProperty(value = "本次支付是否支付完成 ---- 支付状态0支付失败 1支付成功--全部货款已支付 2待支付 5支付已超时 10支付成功--已支付部分货款 ") + private int isPayAll; + + @ApiModelProperty(value = "剩余未支付的金额") + private BigDecimal noPayAmount; + + @ApiModelProperty(value = "需要支付的总金额 = payAmount + noPayAmount") + private BigDecimal totalAmount; + + @ApiModelProperty(value = "已支付的金额(从卖方钱包交易记录中获取的)") + private BigDecimal payAmount; + + @ApiModelProperty(value = "卖方二维码图片(如果支付状态为 1 则不再返回该字段)") + private String img; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PaymentRecordDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PaymentRecordDto.java new file mode 100644 index 0000000..0ddec3b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PaymentRecordDto.java @@ -0,0 +1,61 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 支付记录返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付记录返回对象",value = "PaymentRecordDto") +public class PaymentRecordDto { + + /** + * 支付记录 ID + */ + @ApiModelProperty(value = "支付记录 ID") + private Long id; + + /** + * 支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd + */ + @ApiModelProperty(value = "支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd") + private String payCoin; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "支付金额") + private BigDecimal amount; + + /** + * 支付状态0支付失败 1支付成并验证 2待支付 10表示支付成功未验证 + */ + @ApiModelProperty(value = "支付状态0支付失败 1支付成功--全部货款已支付 2待支付 5支付已超时 6 支付中( 目前只有这三种状态 7 订单进行中 8 订单已完成 9 余额不足,订单已取消) 10支付成功--已支付部分货款") + private Integer status; + + /** + * 支付地址 + */ + @ApiModelProperty(value = "支付地址(卖方)") + private String payAddress; + + @ApiModelProperty(value = "二维码图片") + private String img; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PriceDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PriceDto.java new file mode 100644 index 0000000..2bb5354 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/PriceDto.java @@ -0,0 +1,41 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 价格范围返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "价格范围返回对象",value = "PriceDto" ) +public class PriceDto { + + + + @ApiModelProperty(value = "库存") + private Integer totalMachineNumber; + + @ApiModelProperty(value = "价格最大值") + private BigDecimal priceMax; + + + @ApiModelProperty(value = "价格最小值") + private BigDecimal priceMin; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductDto.java new file mode 100644 index 0000000..d5efd63 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductDto.java @@ -0,0 +1,142 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 商品返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品返回对象",value = "ProductDto" ) +public class ProductDto { + + @ApiModelProperty(value = "商品id") + private Long id; + + + /** + * 店铺id + */ + @ApiModelProperty(value = "店铺id") + private Long shopId; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称") + private String name; + + /** + * 商品图片路径 + */ + @ApiModelProperty(value = "商品图片路径") + private String image; + + /** + * 商品类型,0 挖矿机器套餐,1 算力套餐 + */ + @ApiModelProperty(value = "商品类型,0 挖矿机器套餐,1 算力套餐") + private Integer type; + + /** + * 上下架状态,0 上架,1 下架 + */ + @ApiModelProperty(value = "上下架状态,0 上架,1 下架") + private Integer state; + + /** + * 商品机器单机算力(卖方手动填写) + */ + //@ApiModelProperty(value = "商品机器单机理论算力(卖方手动填写)") + //private BigDecimal power; + + + /** + * 库存中机器价格范围 + */ + @ApiModelProperty(value = "价格范围") + private String priceRange; + + /** + * 算法 + */ + @ApiModelProperty(value = "算法") + private String algorithm; + + /** + * 商品描述 + */ + @ApiModelProperty(value = "商品描述") + private String description; + + + /** + * 功耗 单位kw/h + */ + //@ApiModelProperty(value = "功耗 单位kw/h") + //private BigDecimal powerDissipation; + + + /** + * 电费 单位 $/度 + */ + //@ApiModelProperty(value = "电费 单位 $/度") + //private BigDecimal electricityBill; + + /** + * 收益率 单位 % + */ + //@ApiModelProperty(value = "收益率 单位 %") + //private BigDecimal incomeRate; + + + /** + * 机器成本价格单位$ [ 功耗 * 电费 * 24 * (1 + 收益率) ] + */ + //@ApiModelProperty(value = "机器成本价格单位$ [ 功耗 * 电费 * 24 * (1 + 收益率) ]") + // private BigDecimal cost; + + /** + * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + @ApiModelProperty(value = "矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona") + private String coin; + + /** + * 矿机挖矿币种全称 + */ + @ApiModelProperty(value = "矿机挖矿币种全称") + private String coinFullName; + + + /** + * 销售机器数 + */ + @ApiModelProperty(value = "已售矿机数") + private Integer saleNumber; + + /** + * 总矿机数 + */ + @ApiModelProperty(value = "总矿机数(已售 + 未售出矿机)") + private Integer totalMachineNumber; + + + @ApiModelProperty(value = "商品对应的出售矿机集合") + List productMachineRangeList; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineDto.java new file mode 100644 index 0000000..f4a3cea --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineDto.java @@ -0,0 +1,135 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 商品对应实际商品返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品对应实际商品返回对象",value = "ProductMachineDto" ) +public class ProductMachineDto { + + @ApiModelProperty(value = "矿机ID") + private Long id; + + + @ApiModelProperty(value = "店铺id") + private Long shopId; + + /** + * 商品 ID + */ + @ApiModelProperty(value = "商品 ID") + private Long productId; + + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号") + private String user; + + /** + * 挖矿机器型号 + */ + @ApiModelProperty(value = "挖矿机器型号") + private String type; + + /** + * 挖矿机器编号 + */ + @ApiModelProperty(value = "挖矿机器编号") + private String miner; + + + /** + * 单价 + */ + @ApiModelProperty(value = "单价") + private BigDecimal price; + + /** + * 实际算力(计算得到,商家不能够自己添加和修改) + */ + @ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)") + private BigDecimal computingPower; + + + /** + * 理论算力 + */ + @ApiModelProperty(value = "理论算力(卖方手动填写)") + private BigDecimal theoryPower; + + @ApiModelProperty(value = "算力单位") + private String unit; + + /** + * 上下架状态,0 上架,1 下架 + */ + @ApiModelProperty(value = "上下架状态,0 上架,1 下架") + private Integer state; + + /** + * 售出状态 0未售出 1已售出 2售出中 + */ + @ApiModelProperty(value = "售出状态 0未售出 1已售出 2售出中") + private Integer saleState; + + @ApiModelProperty(value = "机器算力最早记录的一次时间(和endTime相减得到商品上实时算力平均值计算的时间段)") + private LocalDateTime startTime; + + @ApiModelProperty(value = "机器算力最近记录的一次时间") + private LocalDateTime endTime; + + /** + * 单机理论收入 + */ + @ApiModelProperty(value = "单机理论收入(每日) 单位币种") + private BigDecimal theoryIncome; + + @ApiModelProperty(value = "单机理论收入(每日) 单位USDT") + private BigDecimal theoryUsdtIncome; + + @ApiModelProperty(value = "租赁天数") + private Integer leaseTime; + + /** + * 单机预估实际收入 + */ + //@ApiModelProperty(value = "单机预估实际收入(每日)") + //private BigDecimal actualIncome; + + @ApiModelProperty(value = "算法") + private String algorithm; + + @ApiModelProperty(value = "功耗 单位kw/h",example = "10") + private BigDecimal powerDissipation; + + @ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7") + private Integer maxLeaseDays; + + @ApiModelProperty(value = "币种") + private String coin; + + @ApiModelProperty(value = "商品名称") + private String name; + + @ApiModelProperty(value = "是否删除 0否 1是") + private Integer del; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineInfoDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineInfoDto.java new file mode 100644 index 0000000..885fdb9 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineInfoDto.java @@ -0,0 +1,34 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + *

+ * 机器范围返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商城商城矿机返回对象",value = "ProductMachineInfoDto" ) +public class ProductMachineInfoDto { + + @ApiModelProperty(value = "商品支持的支付地址") + private List payConfigList; + + + @ApiModelProperty(value = "矿机范围及矿机详情返回对象") + private List machineRangeInfoList; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeDto.java new file mode 100644 index 0000000..06b714c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeDto.java @@ -0,0 +1,47 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 机器范围返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "机器范围返回对象",value = "ProductMachineRangeDto" ) +public class ProductMachineRangeDto { + + @ApiModelProperty(value = "功耗范围") + private String powerRange; + + @ApiModelProperty(value = "理论算力范围") + private String theoryPowerRange; + + @ApiModelProperty(value = "实际算力范围") + private String computingPowerRange; + + @ApiModelProperty(value = "数量") + private Integer number; + + @ApiModelProperty(value = "实际单价") + private BigDecimal price; + + @ApiModelProperty(value = "商品对应的出售矿机") + List productMachines; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeGroupDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeGroupDto.java new file mode 100644 index 0000000..ab7fb8d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeGroupDto.java @@ -0,0 +1,49 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 机器范围返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "机器范围返回对象",value = "ProductMachineRangeGroupDto" ) +public class ProductMachineRangeGroupDto { + + @ApiModelProperty(value = "唯一标识") + private Integer onlyKey; + + @ApiModelProperty(value = "功耗范围") + private String powerRange; + + @ApiModelProperty(value = "理论算力范围") + private String theoryPowerRange; + + @ApiModelProperty(value = "实际算力范围") + private String computingPowerRange; + + @ApiModelProperty(value = "数量") + private Integer number; + + @ApiModelProperty(value = "实际单价") + private BigDecimal price; + + @ApiModelProperty(value = "算力单位") + private String unit; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeInfoDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeInfoDto.java new file mode 100644 index 0000000..a780313 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductMachineRangeInfoDto.java @@ -0,0 +1,34 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 机器范围返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "机器范围返回对象",value = "ProductMachineRangeInfoDto" ) +public class ProductMachineRangeInfoDto { + + @ApiModelProperty(value = "商城商品详情---价格分组对象") + private ProductMachineRangeGroupDto productMachineRangeGroupDto; + + @ApiModelProperty(value = "价格分组下对应的商品矿机") + private List productMachines; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductUpdateMachineDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductUpdateMachineDto.java new file mode 100644 index 0000000..8d9072c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ProductUpdateMachineDto.java @@ -0,0 +1,98 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 商品机器修改返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品机器修改返回对象",value = "ProductUpdateMachineDto" ) +public class ProductUpdateMachineDto { + + @ApiModelProperty(value = "矿机ID") + private Long id; + + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号") + private String user; + + /** + * 挖矿机器型号 + */ + @ApiModelProperty(value = "挖矿机器型号") + private String type; + + /** + * 挖矿机器编号 + */ + @ApiModelProperty(value = "挖矿机器编号") + private String miner; + + + /** + * 单价 + */ + @ApiModelProperty(value = "单价") + private BigDecimal price; + + /** + * 实际算力(计算得到,商家不能够自己添加和修改) + */ + @ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)") + private BigDecimal computingPower; + + + /** + * 理论算力 + */ + @ApiModelProperty(value = "理论算力(卖方手动填写)") + private BigDecimal theoryPower; + + @ApiModelProperty(value = "算力单位") + private String unit; + + /** + * 上下架状态,0 上架,1 下架 + */ + @ApiModelProperty(value = "上下架状态,0 上架,1 下架") + private Integer state; + + /** + * 售出状态 0未售出 1已售出 2售出中 + */ + @ApiModelProperty(value = "售出状态 0未售出 1已售出 2售出中") + private Integer saleState; + + @ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7") + private Integer maxLeaseDays; + + /** + * 单机预估实际收入 + */ + //@ApiModelProperty(value = "单机预估实际收入(每日)") + //private BigDecimal actualIncome; + + //@ApiModelProperty(value = "算法") + //private String algorithm; + + @ApiModelProperty(value = "功耗 单位kw/h",example = "10") + private BigDecimal powerDissipation; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/QrCodeDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/QrCodeDto.java new file mode 100644 index 0000000..c1d13ab --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/QrCodeDto.java @@ -0,0 +1,40 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 二维码 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "二维码",value = "QrCodeDto") +public class QrCodeDto { + + + + /** + * 支付金额 + */ + @ApiModelProperty(value = "支付金额") + private BigDecimal amount; + + /** + * 支付地址 + */ + @ApiModelProperty(value = "支付地址(卖方)") + private String payAddress; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/RecentlyTransactionDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/RecentlyTransactionDto.java new file mode 100644 index 0000000..2264ccd --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/RecentlyTransactionDto.java @@ -0,0 +1,50 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 最近交易返回对象 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "最近交易返回对象",value = "RecentlyTransactionDto" ) +public class RecentlyTransactionDto { + + + + /** + * 支付金额 + */ + @ApiModelProperty(value = "交易金额") + private BigDecimal amount; + + /** + * 交易类型 + */ + @ApiModelProperty(value = "交易类型 0 支付 1 充值 2 提现") + private Integer type; + + /** + * 交易完成时间 + */ + @ApiModelProperty(value = "交易完成时间") + private LocalDateTime updateTime; + + @ApiModelProperty(value = "交易状态 0 失败 1 成功 2 充值/提现/支付中 3校验失败") + private Integer status; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/Result.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/Result.java new file mode 100644 index 0000000..ac8ed04 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/Result.java @@ -0,0 +1,78 @@ +package com.m2pool.lease.dto; + +import com.m2pool.lease.constant.ResponseConstant; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description 响应对象封装类 + * @Date 2024/6/11 9:18 + * @Author yyb + */ +@Data +public class Result implements Serializable +{ + private static final long serialVersionUID = 3276842119125241681L; + + /** 成功 */ + public static final int SUCCESS = ResponseConstant.SUCCESS; + + /** 失败 */ + public static final int FAIL = ResponseConstant.FAIL; + + private int code; + + private String msg; + + private T data; + + public static Result success() + { + return restResult(null, SUCCESS, null); + } + + public static Result success(T data) + { + return restResult(data, SUCCESS, null); + } + + public static Result success(T data, String msg) + { + return restResult(data, SUCCESS, msg); + } + + public static Result fail() + { + return restResult(null, FAIL, null); + } + + public static Result fail(String msg) + { + return restResult(null, FAIL, msg); + } + + public static Result fail(T data) + { + return restResult(data, FAIL, null); + } + + public static Result fail(T data, String msg) + { + return restResult(data, FAIL, msg); + } + + public static Result fail(int code, String msg) + { + return restResult(null, code, msg); + } + + private static Result restResult(T data, int code, String msg) + { + Result apiResult = new Result<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopCartDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopCartDto.java new file mode 100644 index 0000000..9482dd5 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopCartDto.java @@ -0,0 +1,49 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 购物车一层列表 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "购物车一层商铺列表返回对象",value = "ShopCartDto") +public class ShopCartDto { + + @ApiModelProperty(value = "店铺id") + private Long id; + /** + * 店铺名称 + */ + @ApiModelProperty(value = "店铺名称") + private String name; + @ApiModelProperty(value = "店铺下机器总价") + private BigDecimal totalPrice; + + @ApiModelProperty(value = "店铺下机器总数") + private Integer totalMachine; + + @ApiModelProperty(value = "商品支持的支付地址") + private List payConfigList; + + //@ApiModelProperty(value = "购物车二层商品列表返回对象") + //List shoppingCartInfoDtoList; + + @ApiModelProperty(value = "商品机器列表") + List productMachineDtoList; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopChainAndCoinDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopChainAndCoinDto.java new file mode 100644 index 0000000..09ebdd3 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopChainAndCoinDto.java @@ -0,0 +1,51 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 店铺钱包配置返对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺钱包配置返对象",value = "ShopChainAndCoinDto") +public class ShopChainAndCoinDto { + private Long shopId; + private String chain; + private String coin; + + + /** + * 用于stream distinct()去重 + * @param o + * @return + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ShopChainAndCoinDto that = (ShopChainAndCoinDto) o; + return shopId.equals(that.shopId) && coin.equals(that.coin) && chain.equals(that.chain); + } + + @Override + public int hashCode() { + int result = shopId.hashCode(); + result = 31 * result + coin.hashCode(); + result = 31 * result + chain.hashCode(); + return result; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopConfigDelDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopConfigDelDto.java new file mode 100644 index 0000000..8aa71e0 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopConfigDelDto.java @@ -0,0 +1,39 @@ +package com.m2pool.lease.dto; + +import com.m2pool.lease.vo.BaseVo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + *

+ * 店铺商品配置返回对象 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺商品配置返回对象",value = "ShopConfigDelDto") +public class ShopConfigDelDto extends BaseVo { + + + private Long shopId; + + + private String payAddress; + + private String chain; + + private Boolean del; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopConfigDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopConfigDto.java new file mode 100644 index 0000000..f13f8b9 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopConfigDto.java @@ -0,0 +1,66 @@ +package com.m2pool.lease.dto; + +import com.m2pool.lease.vo.BaseVo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + *

+ * 店铺商品配置返回对象 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺商品配置返回对象",value = "ShopConfigDto") +public class ShopConfigDto extends BaseVo { + + + /** + * 商铺ID + */ + @ApiModelProperty(value = "商铺ID") + private Long shopId; + + + /** + * 币种类型 0 虚拟币 1 稳定币 + */ + @ApiModelProperty(value = "币种类型 0 虚拟币 1 稳定币") + private Integer payType; + + /** + * 卖方对应收款钱包 + */ + @ApiModelProperty(value = "卖方对应收款钱包") + private String payAddress; + + @ApiModelProperty(value = "链") + private String chain; + + @ApiModelProperty(value = "币(二级) 下拉列表") + private List children; + + @Data + @ApiModel(description = "币种图片返回对象",value = "CoinDto") + public static class CoinDto{ + @ApiModelProperty(value = "商品支付方式及价格单位 取值 虚拟币( nexa rxd dgbo dgbq dgbs alph enx grs mona) 稳定币(usdt usdc busd)") + private String payCoin; + + @ApiModelProperty(value = "币种图片") + private String image; + + } + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopDto.java new file mode 100644 index 0000000..b44f49c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopDto.java @@ -0,0 +1,57 @@ +package com.m2pool.lease.dto; + +import com.m2pool.lease.vo.BaseVo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 店铺表 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺返回对象",value = "ShopDto") +public class ShopDto { + + @ApiModelProperty(value = "店铺id") + private Long id; + + /** + * 店铺名称 + */ + @ApiModelProperty(value = "店铺名称") + private String name; + + /** + * 店铺图片路径 + */ + @ApiModelProperty(value = "店铺图片路径") + private String image; + + /** + * 店铺描述 + */ + @ApiModelProperty(value = "店铺描述") + private String description; + + /** + * 商铺状态 0 待审核 1 审核通过(店铺开启) 2 店铺关闭 + */ + @ApiModelProperty(value = "商铺状态 0 待审核 1 审核通过(店铺开启) 2 店铺关闭") + private Integer state; + /** + * 逻辑删除字段 + */ + @ApiModelProperty(value = "逻辑删除字段") + private Boolean del; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopNameDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopNameDto.java new file mode 100644 index 0000000..c78530e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShopNameDto.java @@ -0,0 +1,33 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 店铺配置商品列表返回对象 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺配置商品列表返回对象",value = "ShopNameDto") +public class ShopNameDto { + + @ApiModelProperty(value = "店铺id") + private Long id; + + /** + * 店铺名称 + */ + @ApiModelProperty(value = "店铺名称") + private String name; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShoppingCartInfoDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShoppingCartInfoDto.java new file mode 100644 index 0000000..904fc67 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/ShoppingCartInfoDto.java @@ -0,0 +1,72 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + *

+ * 购物车详情表 + *

+ * + * @author yyb + * @since 2025-07-24 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "购物车二层商品列表返回对象",value = "ShoppingCartInfoDto" ) +public class ShoppingCartInfoDto { + + /** + * ID + */ + //@ApiModelProperty(value = "购物车详情ID") + //private Long id; + + + @ApiModelProperty(value = "店铺ID",example = "8") + private Long shopId; + + /** + * 商品 ID + */ + @ApiModelProperty(value = "商品 ID") + private Long productId; + + /** + * 商品机器ID + */ + @ApiModelProperty(value = "商品机器ID") + private Long productMachineId; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称") + private String name; + + /** + * 商品上下架状态,0 上架,1 下架 + */ + @ApiModelProperty(value = "商品上下架状态,0 上架,1 下架") + private Integer productState; + + + @ApiModelProperty(value = "矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona",example = "nexa") + private String coin; + + @ApiModelProperty(value = "商品图片路径") + private String image; + + + @ApiModelProperty(value = "商品机器列表") + List productMachineDtoList; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/TransactionRecordDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/TransactionRecordDto.java new file mode 100644 index 0000000..6d66de1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/TransactionRecordDto.java @@ -0,0 +1,118 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 支付消息记录表 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "交易流水返回对象",value = "TransactionRecordDto" ) +public class TransactionRecordDto { + + + /** + * 消息ID + */ + @ApiModelProperty(value = "消息ID") + private String queueId; + + /** + * 买家充值地址 + */ + @ApiModelProperty(value = "买家充值地址") + private String fromAddress; + + /** + * 卖家地址(卖家自定义地址) + */ + @ApiModelProperty(value = "提现流水:用户提现地址 充值流水:不需要该字段 支付流水:卖家收款地址") + private String toAddress; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "理论支付支付金额") + private BigDecimal amount; + + /** + *实际支付金额(根据一天内预估算力和实际算力差值计算得来,并且已经真实支付成功的金额) + */ + @ApiModelProperty(value = "实际支付金额(根据一天内预估算力和实际算力差值计算得来,并且已经真实支付成功的金额)") + private BigDecimal realAmount; + + /** + * 钱包冻结金额 + */ + @ApiModelProperty(value = "钱包冻结金额") + private BigDecimal blockAmount; + /** + * 卖家钱包币种 + */ + @ApiModelProperty(value = "提现流水:用户提现钱包币种 充值流水:不需要该字段 支付流水:卖家收款钱包币种") + private String toSymbol; + + /** + * 卖家钱包链名称 + */ + @ApiModelProperty(value = "提现流水:用户提现链链名称 充值流水:不需要该字段 支付流水:卖家收款链名称") + private String toChain; + + + /** + * 买家钱包币种 + */ + @ApiModelProperty(value = "买家钱包币种") + private String fromSymbol; + + /** + * 买家钱包链名称 + */ + @ApiModelProperty(value = "买家钱包链名称") + private String fromChain; + + /** + * 交易hash + */ + @ApiModelProperty(value = "交易hash") + private String txHash; + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单号") + private String orderId; + + /** + * 支付时间 + */ + @ApiModelProperty(value = "流水建立时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty(value = "成功/失败/证书校验失败时间") + private LocalDateTime updateTime; + + /** + * 0 失败 1 成功 2 等待校验 3 证书校验失败 + */ + @ApiModelProperty(value = " 0 支付/充值/提现失败 1 支付/充值/提现成功 2 支付/充值/提现校验中 3 支付/充值/提现证书校验失败") + private Integer status; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserDto.java new file mode 100644 index 0000000..b5b9d9b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserDto.java @@ -0,0 +1,39 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 用户返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户返回对象",value = "UserDto" ) +public class UserDto{ + + private Long id; + + /** + * 用户id(邮箱) + */ + @ApiModelProperty(value = "用户id(邮箱)") + private String userId; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserMinerDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserMinerDto.java new file mode 100644 index 0000000..1b7671d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserMinerDto.java @@ -0,0 +1,43 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 用户挖矿账户矿工返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户挖矿账户矿工返回对象",value = "UserMinerDto" ) +public class UserMinerDto { + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号") + private String user; + /** + * 挖矿机器编号 + */ + @ApiModelProperty(value = "挖矿机器编号") + private String miner; + + @ApiModelProperty(value = "机器挖矿币种") + private String coin; + + @ApiModelProperty(value = "实时算力(单位MH/S)") + private BigDecimal realPower; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserMinerPowerDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserMinerPowerDto.java new file mode 100644 index 0000000..02bf571 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserMinerPowerDto.java @@ -0,0 +1,48 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 用户挖矿账户矿工返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户挖矿账户矿工实时算力返回对象",value = "UserMinerPowerDto" ) +public class UserMinerPowerDto { + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号") + private String user; + /** + * 挖矿机器编号 + */ + @ApiModelProperty(value = "挖矿机器编号") + private String miner; + + @ApiModelProperty(value = "机器挖矿币种") + private String coin; + + @ApiModelProperty(value = "机器算力") + private BigDecimal power; + + @ApiModelProperty(value = "记录开始时间") + private LocalDateTime startTime; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserOwnedProductDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserOwnedProductDto.java new file mode 100644 index 0000000..06af2ad --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserOwnedProductDto.java @@ -0,0 +1,115 @@ +package com.m2pool.lease.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 用户拥有商品返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value="UserOwnedProductDto", description="UserOwnedProductDto") +public class UserOwnedProductDto { + + @ApiModelProperty(value = "ID") + private Long id; + + /** + * 用户ID(暂时使用租赁者钱包地址) + */ + @ApiModelProperty(value = "用户id(邮箱)") + private String userId; + + /** + * 商品对应的机器id + */ + @ApiModelProperty(value = "商品对应的机器id") + private Long productMachineId; + + /** + * 订单明细 ID,关联订单中的购买记录 + */ + @ApiModelProperty(value = "订单明细 ID,关联订单中的购买记录") + private Long orderItemId; + + /** + * 商品开始使用时间(购买当天24点生效) + */ + @ApiModelProperty(value = "商品开始使用时间(购买当天24点生效)") + private LocalDateTime startTime; + + /** + * 商品使用结束时间 + */ + @ApiModelProperty(value = "商品使用结束时间") + private LocalDateTime endTime; + + /** + * 购买算力的量,当 type 为 1 时有效 + */ + @ApiModelProperty(value = "购买算力的量,当 type 为 1 时有效") + private BigDecimal purchasedComputingPower; + + /** + * 当前实时算力 + */ + @ApiModelProperty(value = "当前实时算力:单位默认MH/S") + private BigDecimal currentComputingPower; + + /** + * 商品状态,0 表示运行中,1 表示已过期 + */ + @ApiModelProperty(value = "商品状态,0 表示运行中,1 表示已过期") + private Integer status; + + /** + * 商品类型,0 表示挖矿机器,1 表示算力套餐 + */ + @ApiModelProperty(value = "商品类型,0 表示挖矿机器,1 表示算力套餐") + private Integer type; + + /** + * 购买时间 + */ + @ApiModelProperty(value = "购买时间") + private LocalDateTime createTime; + + + /** + * 预估商品结束时的总收益 + */ + @ApiModelProperty(value = "预估商品结束时的总收益") + private BigDecimal estimatedEndIncome; + + + /** + * 预估商品结束时的总收益 单位usdt + */ + @ApiModelProperty(value = "预估商品结束时的总收益 单位usdt") + private BigDecimal estimatedEndUsdtIncome; + /** + * 当前收益(根据购买机器到现在的平均算力计算得到) + */ + @ApiModelProperty(value = "当前收益(根据购买机器到现在的平均算力计算得到)") + private BigDecimal currentIncome; + + /** + * 当前收益(根据购买机器到现在的平均算力计算得到)单位usdt + */ + @ApiModelProperty(value = "当前收益(根据购买机器到现在的平均算力计算得到)单位usdt") + private BigDecimal currentUsdtIncome; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserWalletDataDto.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserWalletDataDto.java new file mode 100644 index 0000000..3f17da0 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/dto/UserWalletDataDto.java @@ -0,0 +1,101 @@ +package com.m2pool.lease.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 用户钱包信息表 + *

+ * + * @author 根据实际情况填写 + * @since 2025-09-08 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户钱包资料信息",value = "UserWalletDataDto") +public class UserWalletDataDto { + + + @ApiModelProperty(value = "用户钱包信息id") + private Long id; + + /** + * 钱包唯一id(用于充值功能) + */ + private String queueId; + + /** + * 用户id(邮箱) + */ + @ApiModelProperty(value = "用户id(邮箱)") + private String userId; + + /** + * 钱包地址 + */ + @ApiModelProperty(value = "充值钱包地址(我们提供") + private String fromAddress; + + + /** + * 钱包地址 + */ + @ApiModelProperty(value = "收款钱包地址(用户自己填写)") + private String toAddress; + + /** + * 余额 + */ + @ApiModelProperty(value = "余额") + private BigDecimal balance; + + @ApiModelProperty(value = "冻结余额,不能用于提现(用户购买机器完成租约所需金额)") + private BigDecimal blockedBalance; + + /** + * 支付地址二维码 + */ + @ApiModelProperty(value = "支付地址二维码") + private String qrcode; + + /** + * 币种 + */ + @ApiModelProperty(value = "用户自定义钱包地址的币种") + private String toSymbol; + + /** + * 链名称 + */ + @ApiModelProperty(value = "用户自定义钱包地址的链名称") + private String toChain; + + + /** + * 币种 + */ + @ApiModelProperty(value = "官方自动绑定钱包地址的币种") + private String fromSymbol; + + /** + * 链名称 + */ + @ApiModelProperty(value = "官方自动绑定钱包地址的链名称") + private String fromChain; + + private LocalDateTime createTime; + + @ApiModelProperty(value = "手续费") + private BigDecimal charge; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/GoogleInfo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/GoogleInfo.java new file mode 100644 index 0000000..5f34cd4 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/GoogleInfo.java @@ -0,0 +1,32 @@ +package com.m2pool.lease.entity; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @Description 文件 + * @Date 2024/6/14 15:57 + * @Author dy + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GoogleInfo implements Serializable { + + /** 邮箱 */ + private String email; + + /** 谷歌验证码 */ + private String secret; + + /** 谷歌验证码 */ + private int status; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseAutoAddress.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseAutoAddress.java new file mode 100644 index 0000000..34c572c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseAutoAddress.java @@ -0,0 +1,58 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.m2pool.lease.dto.PageResult; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +/** + *

+ * 矿池nexa机器实时平均算力 - 自动钱包地址表 + *

+ * + * @author yyb + * @since 2025-09-04 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseAutoAddress implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 钱包地址 + */ + private String address; + + /** + * 币种 + */ + private String fromSymbol; + + /** + * 链名称 + */ + private String fromChain; + /** + * 0 未使用 1 已使用 + */ + private Integer status; + + /** + * 绑定用户用户邮箱 + */ + private String bindUser; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseNexaMachineAvgPower.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseNexaMachineAvgPower.java new file mode 100644 index 0000000..f46fffc --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseNexaMachineAvgPower.java @@ -0,0 +1,60 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 矿池nexa机器实时平均算力 + *

+ * + * @author yyb + * @since 2025-07-29 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseNexaMachineAvgPower implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 挖矿账户 + */ + private String user; + + /** + * 矿工 + */ + private String miner; + + /** + * 记录开始时间 + */ + private LocalDateTime startTime; + + /** + * 记录结束时间 + */ + private LocalDateTime endTime; + + /** + * 实时平均算力 + */ + private BigDecimal realAvgPower; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseNexaMachinePower.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseNexaMachinePower.java new file mode 100644 index 0000000..633d1b4 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseNexaMachinePower.java @@ -0,0 +1,65 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 已售商品矿工实时算力表 + *

+ * + * @author yyb + * @since 2025-07-25 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseNexaMachinePower implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 挖矿账户 + */ + private String user; + + /** + * 矿工 + */ + private String miner; + + /** + * 记录时间(每五分钟整点) + */ + private LocalDateTime date; + + /** + * 五分钟一次的矿工矿机算力 + */ + private BigDecimal accepts; + + /** + * 矿机在离线状态 离线offline 在线online + */ + private String state; + + /** + * 实际记录时间 + */ + private LocalDateTime lastSubmit; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseOrderInfo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseOrderInfo.java new file mode 100644 index 0000000..0b658c7 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseOrderInfo.java @@ -0,0 +1,69 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 订单表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseOrderInfo implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 订单 ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 订单号 + */ + private String orderNumber; + + /** + * 用户 ID + */ + private String userId; + + /** + * 订单总价 + */ + private BigDecimal totalPrice; + + /** + * 订单状态,0 表示待支付,1 表示(全部)已支付,2 表示已取消 3售后状态 4已退款 5已超时 10 部分已支付 + */ + private Integer status; + /** + * 下单时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseOrderItem.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseOrderItem.java new file mode 100644 index 0000000..3da8efd --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseOrderItem.java @@ -0,0 +1,163 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 订单明细表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseOrderItem implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 订单明细 ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 店铺 ID + */ + private Long shopId; + + /** + * 用户 ID(邮箱) + */ + private String userId; + /** + * 订单 ID + */ + private Long orderId; + + /** + * 商品 ID + */ + private Long productId; + + /** + * 机器id + */ + private Long productMachineId; + + /** + * 矿工账号 + */ + private String user; + + /** + * 矿机编号 + */ + private String miner; + + /** + * 商品数量 + */ + private Integer quantity; + + /** + * 收货地址(模拟) + */ + private String address; + + + /** + *卖家地址链名称 + */ + private String chain; + + /** + * 卖家地址支付币种 + */ + private String symbol; + + private String fromAddress; + + private String fromChain; + + private String fromSymbol; + + /** + * 租期 + */ + private Integer leaseTime; + + /** + * 支付币种 + */ + private String payCoin; + + /** + * 商品单价 + */ + private BigDecimal price; + + /** + * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + private String coin; + + /** + * 单机理论收益 + */ + private BigDecimal theoryIncome; + + /** + * 单机预估实际收益 + */ + //private BigDecimal actualIncome; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + /** + * 0 租约已过期 1 租约生效中 + */ + private Integer status; + + + /** + * 商品名称 + */ + private String name; + /** + * 商品图片路径 + */ + private String image; + + /** + * 商品类型 0 矿机 1 算力 + */ + @TableField(exist = false) + private Integer type; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayRechargeMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayRechargeMessage.java new file mode 100644 index 0000000..cdb13b8 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayRechargeMessage.java @@ -0,0 +1,95 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 充值记录表 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeasePayRechargeMessage implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + *消息ID + */ + private String queueId; + + + /** + * 充值地址 + */ + private String address; + + /** + * 支付金额 + */ + private BigDecimal amount; + /** + * 币种 + */ + private String symbol; + + /** + * 链名称 + */ + private String chain; + + // + ///** + // * 币种 + // */ + //private String fromSymbol; + // + ///** + // * 链名称 + // */ + //private String fromChain; + + /** + * 充值时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 交易hash + */ + private String txHash; + + /** + * 0 充值失败 1 充值成功 2 充值中 + */ + private Integer status; + + /** + * 逻辑删除字段 + */ + private Boolean del; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayRecordMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayRecordMessage.java new file mode 100644 index 0000000..47fbcb8 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayRecordMessage.java @@ -0,0 +1,136 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 支付消息记录表 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeasePayRecordMessage implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 消息ID + */ + private String queueId; + + /** + * 买家充值地址 + */ + private String fromAddress; + + /** + * 卖家充值地址 + */ + private String toAddress; + + /** + * 订单号 + */ + private String orderNumber; + + /** + * 店铺ID + */ + private Long shopId; + + /** + * 用户邮箱 + */ + private String userId; + + /** + * 理论支付金额(根据商家定价) + */ + private BigDecimal amount; + + /** + *真实支付金额 + */ + private BigDecimal realAmount; + + /** + * 实际应支付金额(根据一天内预估算力和实际算力差值计算得来) + */ + private BigDecimal needAmount; + + /** + * 钱包冻结金额 + */ + private BigDecimal blockAmount; + /** + * 币种 + */ + private String toSymbol; + + /** + * 链名称 + */ + private String toChain; + + + /** + * 币种 + */ + private String fromSymbol; + + /** + * 链名称 + */ + private String fromChain; + + /** + * 交易hash + */ + private String txHash; + + private Long blockHeight; + + /** + * 订单id + */ + private String orderId; + + /** + * 支付时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 0 支付失败 1 支付成功 2 等待校验 + */ + private Integer status; + + /** + * 逻辑删除字段 + */ + private boolean del; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayWithdrawMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayWithdrawMessage.java new file mode 100644 index 0000000..30ac9ff --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePayWithdrawMessage.java @@ -0,0 +1,105 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 提现记录表 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeasePayWithdrawMessage implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 消息ID + */ + private String queueId; + + /** + * 用户充值地址 + */ + private String fromAddress; + + /** + * 提现地址(用户自定义) + */ + private String toAddress; + + /** + * 支付金额 + */ + private BigDecimal amount; + + /** + * 交易hash + */ + private String txHash; + + /** + * 手续费 + */ + private BigDecimal serviceCharge; + + /** + * 币种 + */ + private String toSymbol; + + /** + * 链名称 + */ + private String toChain; + + + /** + * 币种 + */ + private String fromSymbol; + + /** + * 链名称 + */ + private String fromChain; + + /** + * 充值时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 0 支付失败 1 支付成功 2 支付中 + */ + private Integer status; + + /** + * 逻辑删除字段 + */ + private Boolean del; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePaymentRecord.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePaymentRecord.java new file mode 100644 index 0000000..daf1a5c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeasePaymentRecord.java @@ -0,0 +1,109 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 支付记录表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeasePaymentRecord implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 支付记录 ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 订单 ID + */ + private Long orderId; + + /** + * 店铺 ID + */ + private Long shopId; + + /** + * 商品 ID + */ + private Long productId; + + /** + * 支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd + */ + private String payCoin; + + /** + * 支付金额 + */ + private BigDecimal amount; + + /** + * 已支付金额 + */ + private BigDecimal payAmount; + + /** + * 支付状态0支付失败 1支付成功--全部货款已支付 2待支付 5支付已超时 10支付成功--已支付部分货款 + */ + private Integer status; + + /** + * 支付地址 + */ + private String payAddress; + + /** + * 交易hash(交易成功后会生成) + */ + private String hash; + + + /** + * 买家钱包地址 + */ + + @TableField("`from`") + private String from; + + /** + * 支付二维码 + */ + private String qrcode; + + /** + * 支付时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProduct.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProduct.java new file mode 100644 index 0000000..36a0c16 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProduct.java @@ -0,0 +1,115 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 商品表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseProduct implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 商品 ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 店铺id + */ + private Long shopId; + + /** + * 商品名称 + */ + private String name; + + /** + * 商品图片路径 + */ + private String image; + + /** + * 商品类型,0 挖矿机器套餐,1 算力套餐 + */ + private Integer type; + + /** + * 上下架状态,0 上架,1 下架 + */ + private Integer state; + + /** + * 最高价格 + */ + private BigDecimal maxPrice; + + /** + * 最低价格 + */ + private BigDecimal minPrice; + + + /** + * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + private String coin; + + /** + * 矿机挖矿币种全称 + */ + private String coinFullName; + + /** + * 算法 + */ + private String algorithm; + + /** + * 商品描述 + */ + private String description; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + /** + * 销售机器数 + */ + private Integer saleNumber; + + /** + * 总矿机数 + */ + private Integer totalMachineNumber; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProductIncome.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProductIncome.java new file mode 100644 index 0000000..fb8a232 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProductIncome.java @@ -0,0 +1,60 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 商品收益表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseProductIncome implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 收益记录 ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户拥有商品详情 ID,关联 lease_user_owned_product 表 + */ + private Long userOwnedProductId; + + /** + * 预估商品结束时的总收益 + */ + private BigDecimal estimatedEndIncome; + + /** + * 当前实际总收益 + */ + private BigDecimal currentActualIncome; + + /** + * 记录创建时间 + */ + private LocalDateTime createTime; + + /** + * 记录更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProductMachine.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProductMachine.java new file mode 100644 index 0000000..064af81 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseProductMachine.java @@ -0,0 +1,145 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 商品表对应的物品机器表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseProductMachine implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 主键ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + + /** + * 店铺ID + */ + private Long shopId; + + /** + * 商品 ID + */ + private Long productId; + + /** + * 挖矿机器 对应的矿工账号 + */ + private String user; + + /** + * 挖矿机器编号 + */ + private String miner; + + /** + * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + private String coin; + + /** + * 单机理论收入(每日) + */ + private BigDecimal theoryIncome; + + /** + * 单机预估实际收入(每日) + */ + //private BigDecimal actualIncome; + + /** + * 矿机型号 + */ + private String type; + + /** + * 实际价格单价 + */ + private BigDecimal price; + + /** + * 算力大小(计算得到,商家不能够自己添加和修改) + */ + private BigDecimal computingPower; + + /** + * 上下架状态,0 上架,1 下架 + */ + private Integer state; + + /** + * 售出状态 0未售出 1已售出 2售出中 + */ + private Integer saleState; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + + /** + * 商品机器单机理论算力(卖方手动填写) + */ + private BigDecimal theoryPower; + + /** + * 商品机器单机算力单位 + */ + private String unit; + + + /** + * 功耗 单位kw/h + */ + private BigDecimal powerDissipation; + + /** + * 默认价格$ [ 功耗 * 电费 * 24 * (1 + 收益率) ] + */ + private BigDecimal cost; + + + /** + * 电费 单位 $/度 + */ + //private BigDecimal electricityBill; + + /** + * 收益率 单位 % + */ + private BigDecimal incomeRate; + + private Integer maxLeaseDays; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShop.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShop.java new file mode 100644 index 0000000..ae53b46 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShop.java @@ -0,0 +1,74 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 店铺表 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseShop implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 店铺ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 店铺拥有者邮箱 + */ + private String userEmail; + + /** + * 店铺名称 + */ + private String name; + + /** + * 店铺图片路径 + */ + private String image; + + /** + * 店铺描述 + */ + private String description; + + /** + * 商铺状态 0 待审核 1 审核通过(店铺开启) 2 店铺关闭 10 店铺开启 + */ + private Integer state; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShopAddressConfig.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShopAddressConfig.java new file mode 100644 index 0000000..18799e8 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShopAddressConfig.java @@ -0,0 +1,52 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; + +/** + *

+ * 矿池nexa机器实时平均算力 - 商铺地址配置表 + *

+ * + * @author yyb + * @since 2025-09-04 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseShopAddressConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 买方账号id(邮箱) + */ + private String userId; + + /** + * 卖方收款钱包 每个买方对应一个地址(自动生成匹配) + */ + private String address; + + /** + * 商铺收款钱包二维码 + */ + private String qrcode; + + /** + * 商铺ID + */ + private Long shopId; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShopConfig.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShopConfig.java new file mode 100644 index 0000000..eaa6d95 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShopConfig.java @@ -0,0 +1,93 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 店铺商品配置表 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseShopConfig implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 配置ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 商铺ID + */ + private Long shopId; + + /** + * 商品 ID (商品id为0代表适用于店铺中所有商品) + */ + private Long productId; + + /** + * 链名称 + */ + private String chain; + + /** + * nexa rxd dgbo dgbq dgbs alph enx grs mona usdt + */ + private String payCoin; + + /** + * 币种图标 + */ + private String payCoinImage; + + /** + * 币种类型 0 虚拟币 1 稳定币 + */ + private Integer payType; + + /** + * 卖方对应收款钱包 + */ + private String payAddress; + + /** + * 支付二维码 + */ + private String qrcode; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + @TableField(exist = false) + private BigDecimal price; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShoppingCart.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShoppingCart.java new file mode 100644 index 0000000..0869570 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShoppingCart.java @@ -0,0 +1,49 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 购物车表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseShoppingCart implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 购物车 ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户 ID(邮箱) + */ + private String userId; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShoppingCartInfo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShoppingCartInfo.java new file mode 100644 index 0000000..bddee81 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseShoppingCartInfo.java @@ -0,0 +1,64 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 购物车详情表 + *

+ * + * @author yyb + * @since 2025-07-24 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseShoppingCartInfo implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 购物车ID + */ + private Long cartId; + + /** + * 商品 ID + */ + private Long productId; + + /** + * 商品机器ID + */ + private Long productMachineId; + + /** + * 租期 + */ + private Integer leaseTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUser.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUser.java new file mode 100644 index 0000000..6955012 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUser.java @@ -0,0 +1,55 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 用户表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseUser implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户ID(邮箱) + */ + private String userId; + + /** + * 密码 + */ + private String password; + + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUserOwnedProduct.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUserOwnedProduct.java new file mode 100644 index 0000000..853aac5 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUserOwnedProduct.java @@ -0,0 +1,143 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 用户拥有商品详情表 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseUserOwnedProduct implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户ID(暂时使用租赁者钱包地址) + */ + private String userId; + + private Long orderId; + + + /** + * 挖矿机器 对应的矿工账号 + */ + private String user; + + /** + * 挖矿机器编号 + */ + private String miner; + + + /** + * 商品对应的机器id + */ + private Long productMachineId; + + /** + * 订单明细 ID,关联订单中的购买记录 + */ + private Long orderItemId; + + + + /** + * 商品开始使用时间(购买当天24点生效) + */ + private LocalDateTime startTime; + + /** + * 商品使用结束时间 + */ + private LocalDateTime endTime; + + /** + * 挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + private String coin; + + /** + * 购买算力的量,当 type 为 1 时有效 + */ + private BigDecimal purchasedComputingPower; + + + /** + * 预估商品结束时的总收益 单位币种 + */ + private BigDecimal estimatedEndIncome; + + + /** + * 预估商品结束时的总收益 单位usdt + */ + private BigDecimal estimatedEndUsdtIncome; + + /** + * 当前收益(根据购买机器到现在的平均算力计算得到) 单位币种 + */ + private BigDecimal currentIncome; + + + /** + * 当前收益(根据购买机器到现在的平均算力计算得到)单位usdt + */ + private BigDecimal currentUsdtIncome; + + private BigDecimal settleIncome ; + + private BigDecimal settleUsdtIncome ; + + /** + * 商品状态,0 表示运行中,1 表示已过期 + */ + private Integer status; + + /** + * 商品类型,0 表示挖矿机器,1 表示算力套餐 + */ + private Integer type; + + /** + * 卖方钱包地址 + */ + private String address; + + /** + * 购买时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 逻辑删除字段 + */ + private Boolean del; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUserWalletData.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUserWalletData.java new file mode 100644 index 0000000..49b92b4 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/entity/LeaseUserWalletData.java @@ -0,0 +1,111 @@ +package com.m2pool.lease.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.sun.org.apache.xpath.internal.operations.Bool; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 用户钱包信息表 + *

+ * + * @author 根据实际情况填写 + * @since 2025-09-08 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LeaseUserWalletData implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + + /** + * 钱包唯一id(用于充值功能) + */ + private String queueId; + /** + * 用户id(邮箱) + */ + private String userId; + + /** + * 充值钱包地址(我们提供) + */ + private String fromAddress; + + /** + * 收款钱包地址(用户自己填写) + */ + private String toAddress; + + /** + * 币种 + */ + private String toSymbol; + + /** + * 链名称 + */ + private String toChain; + + + /** + * 币种 + */ + private String fromSymbol; + + /** + * 链名称 + */ + private String fromChain; + + /** + * 余额 + */ + private BigDecimal balance; + + /** + * 冻结余额(用户购买机器完成租约所需金额) + */ + private BigDecimal blockedBalance; + + /** + * 支付地址二维码 + */ + private String qrcode; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 删除标识 + */ + private Boolean del; + + @TableField(exist = false) + private Long shopId; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/GlobalExceptionHandler.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..c0d046f --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/GlobalExceptionHandler.java @@ -0,0 +1,49 @@ +package com.m2pool.lease.exception; + +import com.m2pool.lease.dto.Result; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 全局异常处理器,用于捕获并处理应用中抛出的异常。 + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + + /** + * 处理商品已出售异常,返回统一的错误结果。 + * + * @param e 商品已出售异常对象 + * @return 包含错误信息的统一结果对象 + */ + @ExceptionHandler(ProductSoldOutException.class) + public Result handleProductSoldOutException(ProductSoldOutException e) { + return Result.fail(e.getMessage()); + } + + @ExceptionHandler(PaymentException.class) + public Result handlePaymentException(PaymentException e) { + return Result.fail(e.getMessage()); + } + + @ExceptionHandler(OrderException.class) + public Result handleOrderException(OrderException e) { + return Result.fail(e.getMessage()); + } + + @ExceptionHandler(PayRechargeException.class) + public Result handleOrderException(PayRechargeException e) { + return Result.fail(e.getMessage()); + } + + /** + * 处理其他未明确捕获的异常,返回统一的错误结果。 + * + * @param e 异常对象 + * @return 包含错误信息的统一结果对象 + */ + @ExceptionHandler(Exception.class) + public Result handleException(Exception e) { + return Result.fail("系统异常,请稍后再试: " + e.getMessage()); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/OrderException.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/OrderException.java new file mode 100644 index 0000000..a0efa10 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/OrderException.java @@ -0,0 +1,10 @@ +package com.m2pool.lease.exception; + +/** + * 订单异常 + */ +public class OrderException extends RuntimeException { + public OrderException(String message) { + super(message); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/PayRechargeException.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/PayRechargeException.java new file mode 100644 index 0000000..3732663 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/PayRechargeException.java @@ -0,0 +1,10 @@ +package com.m2pool.lease.exception; + +/** + * 支付异常 + */ +public class PayRechargeException extends RuntimeException { + public PayRechargeException(String message) { + super(message); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/PaymentException.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/PaymentException.java new file mode 100644 index 0000000..fb33400 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/PaymentException.java @@ -0,0 +1,10 @@ +package com.m2pool.lease.exception; + +/** + * 支付异常 + */ +public class PaymentException extends RuntimeException { + public PaymentException(String message) { + super(message); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/ProductSoldOutException.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/ProductSoldOutException.java new file mode 100644 index 0000000..40f1c02 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/exception/ProductSoldOutException.java @@ -0,0 +1,10 @@ +package com.m2pool.lease.exception; + +/** + * 商品已出售异常类,用于表示在添加订单时商品已被出售的异常情况。 + */ +public class ProductSoldOutException extends RuntimeException { + public ProductSoldOutException(String message) { + super(message); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseAutoAddressMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseAutoAddressMapper.java new file mode 100644 index 0000000..e44af86 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseAutoAddressMapper.java @@ -0,0 +1,25 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.UserWalletDataDto; +import com.m2pool.lease.entity.LeaseAutoAddress; +import org.apache.ibatis.annotations.MapKey; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface LeaseAutoAddressMapper extends BaseMapper { + /** + * 获取一个未使用的地址 + * @return + */ + LeaseAutoAddress getOneStatusIsNoUse(); + + + /** + * 获取所有有效的地址 + * @return + */ + List getValidAddress(); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseNexaMachineAvgPowerMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseNexaMachineAvgPowerMapper.java new file mode 100644 index 0000000..260808b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseNexaMachineAvgPowerMapper.java @@ -0,0 +1,37 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.UserMinerDto; +import com.m2pool.lease.entity.LeaseNexaMachineAvgPower; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 矿池nexa机器实时平均算力 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-29 + */ +@Mapper +public interface LeaseNexaMachineAvgPowerMapper extends BaseMapper { + + /** + * 批量插入数据 + * + * @param list + * @return + */ + boolean insertBatchDatas(@Param("list") List list); + + /** + * 根据用户和矿工查询数据 + * + * @param userMinerList + * @return + */ + List selectListByUserAndMiner(@Param("list") List userMinerList); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseNexaMachinePowerMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseNexaMachinePowerMapper.java new file mode 100644 index 0000000..d4de42b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseNexaMachinePowerMapper.java @@ -0,0 +1,46 @@ +package com.m2pool.lease.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.common.datasource.annotation.HashRateDB; +import com.m2pool.lease.dto.ProductMachineDto; +import com.m2pool.lease.entity.LeaseNexaMachinePower; +import com.m2pool.lease.entity.LeaseProductMachine; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 已售商品矿工实时算力表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-25 + */ +@Mapper +public interface LeaseNexaMachinePowerMapper extends BaseMapper { + + /** + * 获取指定时间段内指定表内指定矿工的实时算力 + * @param leaseProductMachines + * @param pointDate + * @param tableName + * @return + */ + @HashRateDB + List getMachinePowerInHashRateById(@Param("leaseProductMachines") List leaseProductMachines, @Param("pointDate")Date pointDate, @Param("tableName") String tableName); + + /** + * 获取3天内算力总和 + * @param leaseProductMachines + * @param coin + * @return + */ + @HashRateDB + List getMachineThreePower(@Param("leaseProductMachines") List leaseProductMachines, @Param("coin") String coin); + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseOrderInfoMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseOrderInfoMapper.java new file mode 100644 index 0000000..220449d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseOrderInfoMapper.java @@ -0,0 +1,58 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.common.datasource.annotation.Pool2DB; +import com.m2pool.lease.dto.OrderInfoDto; +import com.m2pool.lease.entity.LeaseOrderInfo; +import com.m2pool.lease.entity.LeaseUserOwnedProduct; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 订单表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseOrderInfoMapper extends BaseMapper { + + /** + * 根据订单状态查询订单(买家) + * + * @param status 订单状态 + * @return 订单列表 + */ + List getOrdersByStatus(@Param("userId") String userId, @Param("status") Integer status); + + + /** + * 根据订单状态查询订单(卖家) + * + * @param status 订单状态 + * @param ids 订单id集合 + * @return 订单列表 + */ + List getOrdersByStatusForSeller( @Param("status") Integer status,@Param("ids") List ids); + + /** + * 根据机器id集合查看订单详情信息 + * @param ids + * @return + */ + List getOrderItemsByMachineId(@Param("ids") List ids); + + /** + * 获取需要付款的订单列表 状态为7 订单进行中的订单 + * @return + */ + List getNeedPayOrderList(); + + @Pool2DB + BigDecimal getCoinPrice(@Param("coin") String coin); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseOrderItemMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseOrderItemMapper.java new file mode 100644 index 0000000..34b6412 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseOrderItemMapper.java @@ -0,0 +1,54 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.OrderStatusDto; +import com.m2pool.lease.entity.LeaseOrderItem; +import com.m2pool.lease.entity.LeasePaymentRecord; +import org.apache.ibatis.annotations.MapKey; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 订单明细表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseOrderItemMapper extends BaseMapper { + + /** + * 获取订单状态为支付中的订单机器id + * + * @param list + * @return + */ + List getMachineByOrderStatusIsPayInData(@Param("list") List list); + + /** + *通过订单详情id找到订单id + * @param orderItemIds + * @return + */ + List getOrderIds(@Param("orderItemIds") List orderItemIds); + + + + List getOrderInfoStatus(@Param("orderIds") List orderIds); + + + + /** + * 通过订单详情id找到订单id + * @param itemIds + * @return + */ + List selectOrderInfoIds(@Param("itemIds") Set itemIds); + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayRechargeMessageMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayRechargeMessageMapper.java new file mode 100644 index 0000000..aab431b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayRechargeMessageMapper.java @@ -0,0 +1,76 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeasePayRechargeMessage; +import com.m2pool.lease.entity.LeaseUserWalletData; +import org.apache.ibatis.annotations.MapKey; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 充值业务mapper层 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Mapper +public interface LeasePayRechargeMessageMapper extends BaseMapper { + + /** + * 获取充值记录列表 + * + * @param walletList 钱包集合 + * @param status + * @return + */ + @Deprecated + List balanceRechargeList(@Param("walletList") List walletList, @Param("status") Integer status); + + /** + * 获取近半年是否有充值记录 + * + * @param fromAddress + * @return + */ + boolean checkRechargeOperator(@Param("fromAddress") String fromAddress); + + /** + * 批量获取近半年是否有充值记录 + * + * @param fromAddressList + * @return + */ + @MapKey("fromAddress") + Map checkRechargeOperatorBatch(@Param("list") List fromAddressList); + + /** + * 交易流水---充值 + * + * @param walletList + * @return + */ + List transactionRecord(@Param("walletList") List walletList); + + + /** + * 最近交易 + * + * @param walletList + * @return + */ + List getRecentlyTransaction(@Param("walletList") List walletList); + + /** + * 根据唯一索引修改或删除 + * + * @param leasePayRechargeMessage + * @return + */ + int saveOrUpdateByIndex(@Param("leasePayRechargeMessage") LeasePayRechargeMessage leasePayRechargeMessage); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayRecordMessageMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayRecordMessageMapper.java new file mode 100644 index 0000000..6972983 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayRecordMessageMapper.java @@ -0,0 +1,82 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeasePayRecordMessage; +import com.m2pool.lease.entity.LeaseShopConfig; +import com.m2pool.lease.entity.LeaseUserWalletData; +import org.apache.ibatis.annotations.MapKey; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * LeasePayRecordMessageMapper 接口 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Mapper +public interface LeasePayRecordMessageMapper extends BaseMapper { + /** + * 检查用户半年内是否有支付操作 + * @param fromAddress + * @return + */ + boolean checkPayOperator(@Param("fromAddress") String fromAddress); + + + /** + * 检查用户批量是否有支付操作 + * @param fromAddressList + * @return + */ + @MapKey("fromAddress") + Map checkPayOperatorBatch(@Param("list") List fromAddressList); + + /** + * 批量查询用户余额支付列表 + * @param walletList + * @param status + * @return + */ + + List balancePayList(@Param("walletList") List walletList, @Param("status") Integer status); + + /** + * 交易流水---支付 + * @param walletList + * @return + */ + List transactionRecord(@Param("walletList") List walletList); + + + /** + * 最近交易 + * @param walletList + * @return + */ + List getRecentlyTransaction(@Param("walletList") List walletList); + + + /** + * 根据订单id 查询当天支付状态 + * @param orderInfoIds + * @return + */ + @MapKey("orderId") + Map selectOrderInfoMap(@Param("orderInfoIds") Set orderInfoIds); + + + /** + * 保存或者更新根据txHash + * @param leasePayRecordMessage + * @return + */ + int updateByTxHash(@Param("leasePayRecordMessage") LeasePayRecordMessage leasePayRecordMessage,@Param("txHash") String txHash); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayWithdrawMessageMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayWithdrawMessageMapper.java new file mode 100644 index 0000000..07da8d4 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePayWithdrawMessageMapper.java @@ -0,0 +1,77 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeasePayWithdrawMessage; +import com.m2pool.lease.entity.LeaseUserWalletData; +import org.apache.ibatis.annotations.MapKey; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 提现mapper层 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Mapper +public interface LeasePayWithdrawMessageMapper extends BaseMapper { + + /** + * 获取提现记录列表 + * + * @param walletList 钱包集合 + * @param status + * @return + */ + @Deprecated + List balanceWithdrawList(@Param("walletList") List walletList, + @Param("status") Integer status); + + + /** + * 检查用户半年内是否有提现操作 + * @param fromAddress + * @return + */ + boolean checkWithdrawOperator(@Param("fromAddress") String fromAddress); + + + /** + * 检查用户半年内是否有提现操作 + * @param fromAddressList + * @return + */ + @MapKey("fromAddress") + Map checkWithdrawOperatorBatch(@Param("list") List fromAddressList); + + /** + * 交易流水---提现 + * + * @param walletList + * @return + */ + List transactionRecord(@Param("walletList") List walletList); + + /** + * 最近交易 + * + * @param walletList + * @return + */ + List getRecentlyTransaction(@Param("walletList") List walletList); + + + /** + * 获取最近一条数据的提现状态 + * + * @param fromAddress + * @return + */ + Integer getRecentlyOneData(@Param("fromAddress") String fromAddress,@Param("chain")String chain); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePaymentRecordMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePaymentRecordMapper.java new file mode 100644 index 0000000..b09368e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeasePaymentRecordMapper.java @@ -0,0 +1,48 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.mq.message.RabbitmqOrderMessage; +import com.m2pool.lease.entity.LeasePaymentRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 支付记录表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeasePaymentRecordMapper extends BaseMapper { + + /** + * 检查订单支付状态 + * + * @param message + * @return + */ + List checkPaymentRecordStatus(@Param("list") List message); + + /** + * 批量更新订单支付状态 + * + * @param list + * @return + */ + int updateBatchStatusForOderIdAndShopId(@Param("list") List list); + + + /** + * 查询最近15分钟处于支付中的订单 + * @return + */ + List getIsPayInData(); + + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductIncomeMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductIncomeMapper.java new file mode 100644 index 0000000..a0154c1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductIncomeMapper.java @@ -0,0 +1,18 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.entity.LeaseProductIncome; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 商品收益表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseProductIncomeMapper extends BaseMapper { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductMachineMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductMachineMapper.java new file mode 100644 index 0000000..60b1edb --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductMachineMapper.java @@ -0,0 +1,105 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.common.datasource.annotation.HashRateDB; +import com.m2pool.common.datasource.annotation.Pool2DB; +import com.m2pool.lease.dto.PriceDto; +import com.m2pool.lease.dto.ProductMachineDto; +import com.m2pool.lease.dto.UserMinerDto; +import com.m2pool.lease.entity.LeaseProductMachine; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品表对应的物品机器表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseProductMachineMapper extends BaseMapper { + + + /** + * 获取当前账户对应的挖矿账户 + * + * @param userId 账户ID + * @return 挖矿账户集合 + */ + @Pool2DB + List getUserMinersList(@Param("userId") String userId, @Param("coin") String coin); + + /** + * 根据机器ID集合获取机器信息 + * + * @param machineIds 机器ID集合 + * @return 机器信息集合 + */ + List getMachinesByIds(@Param("machineIds") List machineIds); + + /** + * 创建订单业务----修改乐观锁(sale_state 改为 2 售出中) + * @param machineIds + * @return + */ + int updateLockState(@Param("machineIds") List machineIds); + + /** + * 获取当前账户对应的挖矿账户的机器矿工集合 (1天内有过算力的才能上架) + * + * @param user 账户ID + * @param coin 币种 + * @return 挖矿账户的机器矿工集合 + */ + @Pool2DB + List getMinerMachines(@Param("user") String user, @Param("coin") String coin); + + /** + * 获取当前账户对应的挖矿账户的已经上架正在售出或已售出的机器矿工 + * + * @param user 账户ID + * @param coin 币种 + * @return 挖矿账户的机器矿工集合 + */ + List getMinerMachinesIsSale(@Param("user") String user, @Param("coin") String coin); + + /** + * 获取商品价格范围 + * + * @param productId 商品ID + * @return 商品价格范围 + */ + PriceDto getPriceRange(@Param("productId") Long productId); + + + @Pool2DB + List getRecentlyFiveMinutesData(@Param("leaseProductMachines") List leaseProductMachines, @Param("coin") String coin); + + + + int saveOrUpdateBatchs(@Param("leaseProductMachines") List leaseProductMachines); + + + /** + * 检测当前商铺是否有已售出机器 + * + * @param shopId 商家ID + * @return 检测结果 + */ + int checkHasSaleMachineByShopId(@Param("shopId") Long shopId); + + /** + * 检测当前商品是否存在已售出机器 + * + * @param productId 商品ID + * @return 检测结果 + */ + int checkHasSaleMachineByProductId(@Param("productId") Long productId); + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductMapper.java new file mode 100644 index 0000000..c545eaa --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseProductMapper.java @@ -0,0 +1,59 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.common.datasource.annotation.Pool2DB; +import com.m2pool.lease.dto.ProductDto; +import com.m2pool.lease.entity.LeaseProduct; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 商品表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseProductMapper extends BaseMapper { + + /** + * 获取近三天币种对应的全网算力 + * @param coin + * @return + */ + @Pool2DB + BigDecimal getCoinNetPower(@Param("coin") String coin); + + + /** + * 获取近三天的全网实际报块数 + * @param coin + * @return + */ + @Pool2DB + BigDecimal getNetBlocks(@Param("coin") String coin); + + + /** + * 获取商品列表(弃用) + * @param coin + * @param algorithm + * @return + */ + List getProductList(@Param("coin") String coin , @Param("algorithm") String algorithm); + + + /** + * 用户个人中心 和 首页商城 商品列表获取 + * @param coin 用于商城首页 + * @param algorithm 用于商城首页 + * @param shopId 用于个人中心商品列表 + * @return + */ + List getProductListForShopAndUserCenter(@Param("coin") String coin , @Param("algorithm") String algorithm,@Param("shopId") Long shopId); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopAddressConfigMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopAddressConfigMapper.java new file mode 100644 index 0000000..4bfc126 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopAddressConfigMapper.java @@ -0,0 +1,10 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.entity.LeaseShopAddressConfig; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface LeaseShopAddressConfigMapper extends BaseMapper { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopConfigMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopConfigMapper.java new file mode 100644 index 0000000..4b7d5fd --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopConfigMapper.java @@ -0,0 +1,42 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeaseShopConfig; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 店铺商品配置表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +public interface LeaseShopConfigMapper extends BaseMapper { + /** + * 获取链和币种 + * @return + */ + List getChainAndList(@Param("chain") String chain); + + List getChainAndListForSeller(@Param("shopId") Long shopId); + + /** + * 更具链名称和币种名称获取币种图标 + * @param chain + * @param coinList + * @return + */ + List getCoinIconByChainAndCoin(@Param("chain") String chain, @Param("coinList") List coinList); + + /** + * 根据店铺id和链名称和币种获取店铺配置(包含已删除的配置) + * @param list + * @return + */ + List selectShopConfigByShopIdAndSymbolAndChain(@Param("list") List list); + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopMapper.java new file mode 100644 index 0000000..71d232e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShopMapper.java @@ -0,0 +1,52 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.PayConfigDto; +import com.m2pool.lease.entity.LeaseProductMachine; +import com.m2pool.lease.entity.LeaseShop; +import com.m2pool.lease.entity.LeaseShopConfig; +import com.m2pool.lease.vo.OrderInfoVo; +import com.m2pool.lease.vo.OrderItemVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + *

+ * 店铺表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Mapper +public interface LeaseShopMapper extends BaseMapper { + + /** + * 获取买家自定义的支付地址和支付币种和链 + * @param shopIds + * @param coin + * @param chain + * @return + */ + List getPayAddressAndPayCoin(@Param("shopIds") Set shopIds,@Param("coin") String coin,@Param("chain") String chain); + + + /** + * 获取单个店铺钱包信息 + * @param shopId + * @return + */ + List getShopWalletInfo(@Param("shopId") Long shopId); + + + /** + * 获取多个店铺钱包信息 + * @param shopIds + * @return + */ + List getShopWalletInfoList(@Param("shopIds") List shopIds); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShoppingCartInfoMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShoppingCartInfoMapper.java new file mode 100644 index 0000000..ec7842e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShoppingCartInfoMapper.java @@ -0,0 +1,38 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.ShoppingCartInfoDto; +import com.m2pool.lease.entity.LeaseShoppingCartInfo; +import com.m2pool.lease.vo.ProductAndMachineVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 购物车详情表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-24 + */ +@Mapper +public interface LeaseShoppingCartInfoMapper extends BaseMapper { + + /** + * 查询购物车详情列表 + * @return + */ + List getCartInfoList(@Param("cartId") Long cartId); + + + + /** + * 批量删除购物车详情数据 + * @param cartId + * @param productAndMachineVos + * @return + */ + int deleteBatchData(@Param("cartId") Long cartId,@Param("productAndMachineVos") List productAndMachineVos); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShoppingCartMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShoppingCartMapper.java new file mode 100644 index 0000000..ea3518e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseShoppingCartMapper.java @@ -0,0 +1,18 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.entity.LeaseShoppingCart; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 购物车表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseShoppingCartMapper extends BaseMapper { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserMapper.java new file mode 100644 index 0000000..500fc0e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserMapper.java @@ -0,0 +1,22 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.common.datasource.annotation.GAuth; +import com.m2pool.lease.entity.GoogleInfo; +import com.m2pool.lease.entity.LeaseUser; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseUserMapper extends BaseMapper { + @GAuth + public GoogleInfo getGoogleInfoByEmail(@Param("email") String email); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserOwnedProductMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserOwnedProductMapper.java new file mode 100644 index 0000000..6be0e85 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserOwnedProductMapper.java @@ -0,0 +1,61 @@ +package com.m2pool.lease.mapper; + +import cn.hutool.core.date.DateTime; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.common.datasource.annotation.Pool2DB; +import com.m2pool.lease.dto.HourIncomeDto; +import com.m2pool.lease.dto.UserMinerDto; +import com.m2pool.lease.dto.UserMinerPowerDto; +import com.m2pool.lease.entity.LeaseUserOwnedProduct; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 用户拥有商品详情表 Mapper 接口 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Mapper +public interface LeaseUserOwnedProductMapper extends BaseMapper { + /** + * 获取已生效商品机器id集合 + * @param beginOfDay + * @return + */ + List getProductMachineIds(@Param("beginOfDay") DateTime beginOfDay); + + + /** + * 获取小时收益列表 + * @param coin + * @param start + * @param end + * @return + */ + @Pool2DB + List getHourIncomeList(@Param("list") List list,@Param("coin") String coin, @Param("start") LocalDateTime start, @Param("end") LocalDateTime end); + + + /** + * 批量更新收益 + * @param list + * @return + */ + int updateBatchIncome(@Param("list") List list); + + + /** + * 获取矿机实时算力(30m) + * @param list + * @param coin + * @return + */ + @Pool2DB + List getUserMinerPower(@Param("list")List list,@Param("coin") String coin); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserWalletDataMapper.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserWalletDataMapper.java new file mode 100644 index 0000000..8c02bc2 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mapper/LeaseUserWalletDataMapper.java @@ -0,0 +1,43 @@ +package com.m2pool.lease.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.m2pool.lease.dto.UserWalletDataDto; +import com.m2pool.lease.entity.LeaseUserWalletData; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.util.List; + +@Mapper +public interface LeaseUserWalletDataMapper extends BaseMapper { + + /** + * 根据用户 ID 查询钱包信息 + * @param userId 用户 ID + * @return 钱包信息 + */ + List selectByUserId(@Param("userId") String userId); + + /** + * 根据钱包地址查询钱包信息 + * @param address 钱包地址 + * @return 钱包信息 + */ + UserWalletDataDto getWalletInfoByAddress(@Param("address") String address,@Param("symbol") String symbol,@Param("userId") String userId); + + /** + * 根据链查询钱包信息 + * @param chain 链 + * @return 钱包信息 + */ + List getWalletInfoByChain(@Param("chain") String chain,@Param("userId") String userId); + + + /** + * 获取余额为 不为0 的钱包地址 + * @param chain 链 + * @return 钱包地址 + */ + List getWalletForBalanceIsZero(@Param("list") List addressList); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/MessageReceiver.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/MessageReceiver.java new file mode 100644 index 0000000..71ebddf --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/MessageReceiver.java @@ -0,0 +1,483 @@ +package com.m2pool.lease.mq; + +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.constant.RabbitmqConstant; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.exception.PayRechargeException; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.mq.message.*; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service +public class MessageReceiver { + + @Resource + private LeasePayWithdrawMessageMapper leasePayWithdrawMessageMapper; + @Resource + private LeasePayRechargeMessageMapper leasePayRechargeMessageMapper; + @Resource + private LeaseUserWalletDataMapper leaseUserWalletDataMapper; + @Resource + private LeasePayRecordMessageMapper leasePayRecordMessageMapper; + @Resource + private LeaseAutoAddressMapper leaseAutoAddressMapper; + + @Resource + private RabbitTemplate rabbitTemplate; + ///** + // * 订单超时 消费者 + // */ + //@RabbitListener(queues = RabbitmqConstant.DEAD_LETTER_QUEUE_NAME) + //@Transactional(rollbackFor = Exception.class) + //public void orderOvertimeMessage(@Payload List message /**,Message amqpMessage */) { + // List leasePaymentRecords = leasePaymentRecordMapper.checkPaymentRecordStatus(message); + // List collect = leasePaymentRecords.stream() + // .filter(record -> record.getStatus() == 6) + // .peek(record-> record.setStatus(5)) + // .collect(Collectors.toList()); + // System.out.println("订单超时消费者"+collect); + // if (!collect.isEmpty()){ + // //1. 修改支付订单状态为 6支付中 状态改为 5 订单已超时 + // boolean b = leasePaymentRecordService.updateBatchById(collect); + // //2. 修改普通订单状态 6支付中 状态改为 5 订单已超时(普通订单和支付订单是同时创建的,所以用的同一个消息) + // Long orderId = collect.get(0).getOrderId(); + // int i = leaseOrderInfoMapper.updateById(LeaseOrderInfo.builder().id(orderId).status(5).build()); + // //3.修改该订单下状态为售出中的机器为可售出状态 + // List orderStatusIsPayInData = leaseOrderItemMapper.getMachineByOrderStatusIsPayInData(leasePaymentRecords); + // //这里只更新机器售出状态为2 售出中的机器 + // int update = leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(), + // new LambdaQueryWrapper() + // .eq(LeaseProductMachine::getSaleState, 2).in(LeaseProductMachine::getId, orderStatusIsPayInData)); + // + // } + // //try { + // // // 手动确认消息 + // // channel.basicAck(amqpMessage.getMessageProperties().getDeliveryTag(), false); + // //} catch (Exception e) { + // // try { + // // // 拒绝消息,不重新入队 + // // channel.basicReject(amqpMessage.getMessageProperties().getDeliveryTag(), false); + // // } catch (IOException ioException) {} + // //} + //} + + + /** + * 支付 消费者 + * @param payAutoReturnMessage + */ + @RabbitListener(queues = RabbitmqConstant.PAY_AUTO_RETURN_QUEUE,containerFactory ="rabbitListenerContainerFactory") + @Transactional(rollbackFor = Exception.class) + public void listenerPayBalanceStatusQueueMessage(@Payload RabbitmqPayAutoReturnMessage payAutoReturnMessage) { + System.out.println("支付消费者"+JSONUtil.toJsonPrettyStr(payAutoReturnMessage)); + //查找到数据库对应的充值记录 + List leasePayRecordMessages = leasePayRecordMessageMapper. + selectList(new LambdaQueryWrapper() + .eq(LeasePayRecordMessage::getQueueId, payAutoReturnMessage.getQueue_id())); + Map collect = leasePayRecordMessages.stream() + .collect(Collectors.toMap(LeasePayRecordMessage::getOrderId, Function.identity())); + //买家钱包 + List transactions = payAutoReturnMessage.getTransactions(); + RabbitmqPayAutoReturnInfoMessage rabbitmqPayAutoReturnInfoMessage = transactions.get(0); + LeaseUserWalletData buyer = leaseUserWalletDataMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getFromAddress,rabbitmqPayAutoReturnInfoMessage.getFrom_address()) + .eq(LeaseUserWalletData::getFromChain, rabbitmqPayAutoReturnInfoMessage.getChain()) + .eq(LeaseUserWalletData::getFromSymbol, rabbitmqPayAutoReturnInfoMessage.getSymbol()) + .eq(LeaseUserWalletData::getDel, false) + ); + //获取初始余额和冻结余额 + BigDecimal initBalance = buyer.getBalance(); + BigDecimal initBlockBalance = buyer.getBlockedBalance(); + + transactions.forEach(transaction -> { + LeasePayRecordMessage leasePayRecordMessage = collect.get(transaction.getOrder_id()); + + if (leasePayRecordMessage != null){ + BigDecimal balance = buyer.getBalance().subtract(transaction.getAmount()); + BigDecimal blockBalance = buyer.getBlockedBalance().subtract(leasePayRecordMessage.getBlockAmount()); + + leasePayRecordMessage.setUpdateTime(LocalDateTime.now()); + leasePayRecordMessage.setBlockHeight(transaction.getBlock_height()); + leasePayRecordMessage.setRealAmount(transaction.getAmount()); + //当天已存在支付的信息 + leasePayRecordMessage.setStatus(transaction.getStatus()); + leasePayRecordMessage.setTxHash(transaction.getTx_hash()); + if(transaction.getStatus() == 1){ + //支付成功 买家 钱包总余额 + 冻结余额 减少 卖家 钱包总余额增加 + buyer.setBalance(balance); + buyer.setBlockedBalance(blockBalance); + } + if (transaction.getStatus() == 0){ + buyer.setBlockedBalance(blockBalance); + } + //修改支付记录状态 + //int i = leasePayRecordMessageMapper.updateByTxHash(leasePayRecordMessage,transaction.getTx_hash()); + System.out.println("支付成功"+JSONUtil.toJsonPrettyStr(leasePayRecordMessage) + transaction.getTx_hash()); + int i = leasePayRecordMessageMapper.updateById(leasePayRecordMessage); + if (i < 1){ + throw new PayRechargeException("支付失败,该支付记录已修改,消息重试!!!"); + } + } + + }); + //使用乐观锁防止余额少减少 + int update = leaseUserWalletDataMapper.update(buyer, new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getId, buyer.getId()) + .eq(LeaseUserWalletData::getBalance, initBalance) + .eq(LeaseUserWalletData::getBlockedBalance, initBlockBalance) + ); + if (update < 1){ + throw new PayRechargeException("支付失败,余额金额错误,消息重试!!!"); + } + } + + + + /** + * 余额充值 消费者 (正常流程一笔充值会有两个消息 2 充值中 1充值成功) + * @param payRechargeReturnMessage + */ + @RabbitListener(queues = RabbitmqConstant.PAY_RECHARGE_RETURN_QUEUE,containerFactory ="rabbitListenerContainerFactory") + @Transactional(rollbackFor = Exception.class) + public void listenerPayRechargeStatusQueueMessage(@Payload RabbitmqPayRechargeReturnMessage payRechargeReturnMessage) { + System.out.println("充值消费者---"+JSONUtil.toJsonPrettyStr(payRechargeReturnMessage)); + + //获取到需要操作的钱包 + List leaseUserWalletDataList = leaseUserWalletDataMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getFromAddress, payRechargeReturnMessage.getAddress()) + .eq(LeaseUserWalletData::getDel, false) + ); + LeaseUserWalletData leaseUserWalletData = null; + for (LeaseUserWalletData item : leaseUserWalletDataList) { + if (item.getFromSymbol().equals(payRechargeReturnMessage.getSymbol())){ + leaseUserWalletData = item; + break; + } + } + //需要新增该币种的钱包 + if (leaseUserWalletData == null){ + LeaseUserWalletData leaseUserWalletData1 = leaseUserWalletDataList.get(0); + leaseUserWalletData = LeaseUserWalletData.builder() + .queueId(payRechargeReturnMessage.getQueue_id()) + .userId(leaseUserWalletData1.getUserId()) + .fromAddress(payRechargeReturnMessage.getAddress()) + .fromChain(payRechargeReturnMessage.getChain()) + .fromSymbol(payRechargeReturnMessage.getSymbol()) + .balance(BigDecimal.ZERO) + .blockedBalance(BigDecimal.ZERO) + .qrcode(leaseUserWalletData1.getQrcode()) + .build(); + leaseUserWalletDataMapper.insert(leaseUserWalletData); + } + LeasePayRechargeMessage leasePayRechargeMessage = leasePayRechargeMessageMapper.selectOne(new LambdaQueryWrapper() + .eq(LeasePayRechargeMessage::getTxHash, payRechargeReturnMessage.getTx_hash())); + BigDecimal balance = leaseUserWalletData.getBalance(); + //处理支付中消息 + if(payRechargeReturnMessage.getStatus() == 2 || leasePayRechargeMessage == null){ + if (leasePayRechargeMessage != null){ + return; + } + LeasePayRechargeMessage build = LeasePayRechargeMessage.builder() + .queueId(payRechargeReturnMessage.getQueue_id()) + .chain(payRechargeReturnMessage.getChain()) + .symbol(payRechargeReturnMessage.getSymbol()) + .amount(payRechargeReturnMessage.getAmount()) + .address(payRechargeReturnMessage.getAddress()) + .txHash(payRechargeReturnMessage.getTx_hash()) + .status(payRechargeReturnMessage.getStatus()) + .build(); + leasePayRechargeMessageMapper.saveOrUpdateByIndex(build); + }else { + //已存在已完成充值的消息 + if (leasePayRechargeMessage.getStatus() == 1){ + return; + } + leasePayRechargeMessage.setStatus(payRechargeReturnMessage.getStatus()); + leasePayRechargeMessage.setUpdateTime(LocalDateTime.now()); + leasePayRechargeMessageMapper.updateById(leasePayRechargeMessage); + } + //处理支付成功消息 + if (payRechargeReturnMessage.getStatus() == 1){ + System.out.println("余额"+balance); + leaseUserWalletData.setBalance(balance.add(payRechargeReturnMessage.getAmount())); + //使用乐观锁防止余额少加 + int update = leaseUserWalletDataMapper.update(leaseUserWalletData, new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getId, leaseUserWalletData.getId()) + .eq(LeaseUserWalletData::getBalance, balance) + ); + if (update < 1){ + throw new PayRechargeException("余额充值失败,余额已被修改"); + } + } + } + + + /** + * 余额提现 消费者 + * @param payWithdrawReturnMessage + */ + @RabbitListener(queues = RabbitmqConstant.PAY_WITHDRAW_RETURN_QUEUE,containerFactory ="rabbitListenerContainerFactory") + @Transactional(rollbackFor = Exception.class) + public void listenerPayWithdrawStatusQueueMessage(@Payload RabbitmqPayWithdrawReturnMessage payWithdrawReturnMessage) { + System.out.println("提现消费者----"+ JSONUtil.toJsonPrettyStr(payWithdrawReturnMessage)); + List leasePayWithdrawMessageList = leasePayWithdrawMessageMapper.selectList(new LambdaQueryWrapper() + .eq(LeasePayWithdrawMessage::getQueueId, payWithdrawReturnMessage.getQueue_id())); + + LeasePayWithdrawMessage leasePayWithdrawMessage = leasePayWithdrawMessageList.get(0); + //获取对应的提现钱包 + LeaseUserWalletData leaseUserWalletData = leaseUserWalletDataMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getFromAddress, leasePayWithdrawMessage.getFromAddress()) + .eq(LeaseUserWalletData::getFromChain, leasePayWithdrawMessage.getFromChain()) + .eq(LeaseUserWalletData::getFromSymbol, leasePayWithdrawMessage.getFromSymbol()) + .eq(LeaseUserWalletData::getDel,false)); + + BigDecimal balance = leaseUserWalletData.getBalance() + .subtract(payWithdrawReturnMessage.getAmount()) + .subtract(leasePayWithdrawMessage.getServiceCharge()); + BigDecimal blockBalance = leaseUserWalletData.getBlockedBalance() + .subtract(payWithdrawReturnMessage.getAmount()) + .subtract(leasePayWithdrawMessage.getServiceCharge()); + + if (leasePayWithdrawMessageList.size() == 1){ + //这种情况下说明不是同一笔交易了,但是它又提现了,但是数据库里面没有该提现记录 需要去新增这笔记录并只减去钱包余额 + if (StringUtils.isNotEmpty(leasePayWithdrawMessage.getTxHash()) && leasePayWithdrawMessage.getStatus() == 1 && !leasePayWithdrawMessage.getTxHash().equals(payWithdrawReturnMessage.getTx_hash())){ + leasePayWithdrawMessageMapper.insert(LeasePayWithdrawMessage.builder() + .toChain(leasePayWithdrawMessage.getToChain()) + .toSymbol(leasePayWithdrawMessage.getToSymbol()) + .fromChain(leasePayWithdrawMessage.getFromChain()) + .fromSymbol(leasePayWithdrawMessage.getFromSymbol()) + .fromAddress(leasePayWithdrawMessage.getFromAddress()) + .serviceCharge(leasePayWithdrawMessage.getServiceCharge()) + .toAddress(leasePayWithdrawMessage.getToAddress()) + .status(payWithdrawReturnMessage.getStatus()) + .amount(payWithdrawReturnMessage.getAmount().add(payWithdrawReturnMessage.getFee())) + .queueId(payWithdrawReturnMessage.getQueue_id()) + .txHash(payWithdrawReturnMessage.getTx_hash()) + .build()); + blockBalance = leaseUserWalletData.getBlockedBalance(); + }else{ + //要修改的钱包状态为1 且提现的状态为1 则不处理 + if (leasePayWithdrawMessage.getStatus() == 1 && payWithdrawReturnMessage.getStatus() == 1){ + return; + } + leasePayWithdrawMessageMapper.updateById(LeasePayWithdrawMessage.builder() + .id(leasePayWithdrawMessage.getId()) + .amount(payWithdrawReturnMessage.getAmount().add(payWithdrawReturnMessage.getFee())) + .status(payWithdrawReturnMessage.getStatus()) + .txHash(payWithdrawReturnMessage.getTx_hash()) + .build()); + } + updateWalletInfo(payWithdrawReturnMessage.getStatus(), leaseUserWalletData, balance, blockBalance); + }else if(leasePayWithdrawMessageList.size() >= 2){ + //极少情况 连续三次以上发送相同queueid 的消息 + LeasePayWithdrawMessage with = null; + for (LeasePayWithdrawMessage withdraw : leasePayWithdrawMessageList) { + if (withdraw.getTxHash().equals(payWithdrawReturnMessage.getTx_hash()) ){ + with = withdraw; + } + } + if(with == null){ + leasePayWithdrawMessageMapper.insert(LeasePayWithdrawMessage.builder() + .queueId(payWithdrawReturnMessage.getQueue_id()) + .txHash(payWithdrawReturnMessage.getTx_hash()) + .toChain(leasePayWithdrawMessage.getToChain()) + .toSymbol(leasePayWithdrawMessage.getToSymbol()) + .fromChain(leasePayWithdrawMessage.getFromChain()) + .fromSymbol(leasePayWithdrawMessage.getFromSymbol()) + .fromAddress(leasePayWithdrawMessage.getFromAddress()) + .serviceCharge(payWithdrawReturnMessage.getFee()) + .toAddress(leasePayWithdrawMessage.getToAddress()) + .amount(payWithdrawReturnMessage.getAmount().add(payWithdrawReturnMessage.getFee())) + .build()); + blockBalance =leaseUserWalletData.getBlockedBalance(); + updateWalletInfo(payWithdrawReturnMessage.getStatus(), leaseUserWalletData, balance, blockBalance); + }else{ + leasePayWithdrawMessageMapper.updateById(LeasePayWithdrawMessage.builder() + .id(with.getId()) + .amount(payWithdrawReturnMessage.getAmount().add(payWithdrawReturnMessage.getFee())) + .status(payWithdrawReturnMessage.getStatus()) + .txHash(payWithdrawReturnMessage.getTx_hash()) + .build()); + if (with.getStatus() != 1 && payWithdrawReturnMessage.getStatus() == 1){ + updateWalletInfo(payWithdrawReturnMessage.getStatus(), leaseUserWalletData, balance, blockBalance); + } + } + + + } + + + } + + /** + * 更新钱包余额信息 + * @param status + * @param leaseUserWalletData + * @param balance + * @param blockBalance + */ + public void updateWalletInfo(Integer status,LeaseUserWalletData leaseUserWalletData,BigDecimal balance,BigDecimal blockBalance){ + BigDecimal initBalance = leaseUserWalletData.getBalance(); + BigDecimal initBlockBalance = leaseUserWalletData.getBlockedBalance(); + //余额 和 冻结余额 减去提现金额 + 手续费 状态为3不做任何操作 + if (status == 1){ + leaseUserWalletData.setBalance(balance); + leaseUserWalletData.setBlockedBalance(blockBalance); + }else if (status == 0 ){ + //余额提现失败 冻结金额 需要减去提现手续费和提现金额 + leaseUserWalletData.setBlockedBalance(blockBalance); + } + leaseUserWalletData.setUpdateTime(LocalDateTime.now()); + //使用乐观锁防止余额少加 + int update = leaseUserWalletDataMapper.update(leaseUserWalletData, new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getId, leaseUserWalletData.getId()) + .eq(LeaseUserWalletData::getBalance, initBalance) + .eq(LeaseUserWalletData::getBlockedBalance, initBlockBalance) + ); + if (update < 1){ + System.out.println("余额提现/支付失败"); + throw new PayRechargeException("余额提现失败,余额已被修改"); + } + System.out.println("余额提现/支付成功"); + } + + @RabbitListener(queues = RabbitmqConstant.DELETE_WALLET_RETURN_QUEUE,containerFactory ="rabbitListenerContainerFactory") + @Transactional(rollbackFor = Exception.class) + public void listenerDeleteWalletQueue(@Payload RabbitmqDeleteWalletReturnMessage rabbitmqDeleteWalletReturnMessage) { + System.out.println("钱包监听删除----删除钱包地址"+rabbitmqDeleteWalletReturnMessage.getAddress()); + LeaseAutoAddress build; + if (rabbitmqDeleteWalletReturnMessage.getStatus() == 1){ + //设置钱包使用状态为2 已过期 + build = LeaseAutoAddress.builder().status(2).build(); + }else{ + //设置钱包使用状态为3 删除监听失败 + build = LeaseAutoAddress.builder().status(3).build(); + } + int i = leaseAutoAddressMapper.update(build, new LambdaUpdateWrapper() + .eq(LeaseAutoAddress::getAddress, rabbitmqDeleteWalletReturnMessage.getAddress()) + .eq(LeaseAutoAddress::getFromChain, rabbitmqDeleteWalletReturnMessage.getChain()) + .eq(LeaseAutoAddress::getFromSymbol, rabbitmqDeleteWalletReturnMessage.getSymbol()) + ); + int update = leaseUserWalletDataMapper.update(LeaseUserWalletData.builder().del(true).build(), new LambdaUpdateWrapper() + .eq(LeaseUserWalletData::getFromAddress, rabbitmqDeleteWalletReturnMessage.getAddress()) + .eq(LeaseUserWalletData::getFromChain, rabbitmqDeleteWalletReturnMessage.getChain()) + .eq(LeaseUserWalletData::getFromSymbol, rabbitmqDeleteWalletReturnMessage.getSymbol()) + ); + if (i > 0 && update > 0 ){ + System.out.println("钱包监听删除成功:"+rabbitmqDeleteWalletReturnMessage.getAddress()); + } + } + + + //测试 开发环境 支付回调测试 + //@RabbitListener(queues = RabbitmqConstant.PAY_AUTO_QUEUE,containerFactory ="rabbitListenerContainerFactory") + //@Transactional(rollbackFor = Exception.class) + //public void listenerPayBalanceStatusQueueMessage(@Payload RabbitmqPayAutoMessage payAutoReturnMessage) { + // //消费消息 + // System.out.println("自动支付功能queueId"+payAutoReturnMessage.getQueue_id()); + // List collect = payAutoReturnMessage.getTransactions().stream() + // .map(transaction -> RabbitmqPayAutoReturnInfoMessage.builder() + // .order_id(transaction.getOrder_id()) + // .from_address(payAutoReturnMessage.getFrom_address()) + // .to_address(transaction.getTo_address()) + // .chain(payAutoReturnMessage.getChain()) + // .symbol(payAutoReturnMessage.getSymbol()) + // .amount(transaction.getAmount()) + // .tx_hash(payAutoReturnMessage.getQueue_id()+"第一笔") + // .block_height(10000L) + // .status(1) + // .build()).collect(Collectors.toList()); + // + // RabbitmqPayAutoReturnMessage rabbitmqPayAutoReturnMessage = RabbitmqPayAutoReturnMessage.builder() + // .queue_id(payAutoReturnMessage.getQueue_id()) + // .pay_status(1) + // .fromAddress(payAutoReturnMessage.getFrom_address()) + // .transactions(collect) + // .build(); + // + // 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) { + // //发送充值消息 + // 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(payAutoReturnMessage.getQueue_id()+"第四笔") + // .build(); + // rabbitTemplate.convertAndSend(RabbitmqConstant.PAY_RECHARGE_RETURN_QUEUE,rabbitmqPayRechargeReturnMessage); + // + // + // //发送充值消息 + // RabbitmqPayRechargeReturnMessage rabbitmqPayRechargeReturnMessage1 = RabbitmqPayRechargeReturnMessage.builder() + // .queue_id(payAutoReturnMessage.getQueue_id()) + // .status(1) + // .amount(BigDecimal.valueOf(20)) + // .chain(payAutoReturnMessage.getChain()) + // .symbol(payAutoReturnMessage.getSymbol()) + // .address(payAutoReturnMessage.getAddress()) + // .tx_hash(payAutoReturnMessage.getQueue_id()+"第四笔") + // .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) { + // //发送充值消息 + // RabbitmqPayWithdrawReturnMessage rabbitmqPayRechargeReturnMessage = RabbitmqPayWithdrawReturnMessage.builder() + // .queue_id(payAutoReturnMessage.getQueue_id()) + // .status(1) + // .amount(payAutoReturnMessage.getAmount()) + // .chain(payAutoReturnMessage.getChain()) + // .symbol(payAutoReturnMessage.getSymbol()) + // .tx_hash(payAutoReturnMessage.getQueue_id()+"第一笔") + // .fee(payAutoReturnMessage.getFee()) + // .build(); + // rabbitTemplate.convertAndSend(RabbitmqConstant.PAY_WITHDRAW_RETURN_QUEUE,rabbitmqPayRechargeReturnMessage); + //} + + + ////测试 开发环境 删除钱包测试 + //@RabbitListener(queues = RabbitmqConstant.DELETE_WALLET_QUEUE,containerFactory ="rabbitListenerContainerFactory") + //@Transactional(rollbackFor = Exception.class) + //public void listenerDeleteWalletQueueMessage(@Payload RabbitmqDeleteWalletMessage payAutoReturnMessage) { + // //发送充值消息 + // RabbitmqDeleteWalletReturnMessage rabbitmqDeleteWalletReturnMessage = RabbitmqDeleteWalletReturnMessage.builder() + // .queue_id(payAutoReturnMessage.getQueue_id()) + // .status(1) + // .chain(payAutoReturnMessage.getChain()) + // .symbol(payAutoReturnMessage.getSymbol()) + // .address(payAutoReturnMessage.getAddress()) + // .build(); + // rabbitTemplate.convertAndSend(RabbitmqConstant.DELETE_WALLET_RETURN_QUEUE,rabbitmqDeleteWalletReturnMessage); + //} + // + + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqDeleteWalletMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqDeleteWalletMessage.java new file mode 100644 index 0000000..6e55f4b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqDeleteWalletMessage.java @@ -0,0 +1,49 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 钱包半年内无操作 取消监听消息 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqDeleteWalletMessage { + /** + * 方法 默认值0 就行了 + */ + private Integer msg_type; + + private String queue_id; + /** + * 链 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + + /** + * 钱包地址 + */ + private String address; + + /** + * 时间戳 + */ + private Long timestamp; + + /** + * 签名 时间戳+m2pool + */ + private String sign; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqDeleteWalletReturnMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqDeleteWalletReturnMessage.java new file mode 100644 index 0000000..f032576 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqDeleteWalletReturnMessage.java @@ -0,0 +1,45 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 钱包半年内无操作 取消监听消息 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqDeleteWalletReturnMessage { + /** + * 方法 默认值0 就行了 + */ + private Integer msg_type; + + private String queue_id; + + /** + * 链 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + + /** + * 钱包地址 + */ + private String address; + + /** + * 状态 0 失败 1成功 2 校验中 3 校验失败 + */ + private Integer status; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqOrderMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqOrderMessage.java new file mode 100644 index 0000000..be2faa5 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqOrderMessage.java @@ -0,0 +1,28 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description ZMQ消息对象 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqOrderMessage { + /** + * 订单id + */ + private Long orderId; + + /** + * 店铺id + */ + private Long shopId; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoInfoMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoInfoMessage.java new file mode 100644 index 0000000..62ef07d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoInfoMessage.java @@ -0,0 +1,60 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @Description 支付 生产者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayAutoInfoMessage { + + /** + * 卖家充值地址 + */ + private String to_address; + + /** + * 支付金额 + */ + private BigDecimal amount; + + /** + * 订单号 + */ + private String order_id; + + + + + //下面五个不需要传输,只存数据库 + /** + * 买方钱包冻结金额 + */ + private BigDecimal blockAmount; + + /** + * 实际应支付金额 + */ + private BigDecimal needAmount; + /** + * 店铺ID + */ + private Long shopId; + + /** + * 用户邮箱 + */ + private String userId; + + private BigDecimal fee; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoMessage.java new file mode 100644 index 0000000..40ac0da --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoMessage.java @@ -0,0 +1,64 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * @Description 支付 生产者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayAutoMessage { + /** + * 消息ID + */ + private String queue_id; + + /** + * 买家充值地址 + */ + private String from_address; + + /** + * 链名称 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + + /** + * 订单总金额 + */ + private BigDecimal total_amount; + + /** + * 时间戳 + */ + private Long timestamp; + + /** + * 签名 时间戳+m2pool + */ + private String sign; + + + private BigDecimal totalFee; + /** + * 收款方信息 + */ + private List transactions; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoReturnInfoMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoReturnInfoMessage.java new file mode 100644 index 0000000..f111027 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoReturnInfoMessage.java @@ -0,0 +1,66 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @Description rabbitmq 支付 消费者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayAutoReturnInfoMessage { + + /** + * 订单号 + */ + private String order_id; + + + + /** + * 买家 + */ + private String from_address; + + /** + * 卖家 + */ + private String to_address; + + /** + * 链名称 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + /** + * 支付金额 + */ + private BigDecimal amount; + + /** + * 支付结果 + */ + private Integer status; + + /** + * 交易id + */ + private String tx_hash; + + /** + * 块高 + */ + private Long block_height; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoReturnMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoReturnMessage.java new file mode 100644 index 0000000..1ce0df9 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayAutoReturnMessage.java @@ -0,0 +1,43 @@ +package com.m2pool.lease.mq.message; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @Description rabbitmq 支付 消费者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayAutoReturnMessage{ + + /** + * 消息ID + */ + private String queue_id; + + /** + * 支付结果 + */ + private Integer pay_status; + + /** + * 买家支付地址 + */ + private String fromAddress; + + /** + * 收款方信息 + */ + private List transactions; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayRechargeMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayRechargeMessage.java new file mode 100644 index 0000000..d8d45be --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayRechargeMessage.java @@ -0,0 +1,46 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description rabbitmq 余额充值 生产者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayRechargeMessage { + + /** + * 链名称 + */ + private String chain; + + private String queue_id; + + /** + * 币种 + */ + private String symbol; + + /** + * 充值地址 + */ + private String address; + + /** + * 时间戳 + */ + private Long timestamp; + + /** + * 签名 时间戳+m2pool + */ + private String sign; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayRechargeReturnMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayRechargeReturnMessage.java new file mode 100644 index 0000000..995c1b6 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayRechargeReturnMessage.java @@ -0,0 +1,56 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @Description rabbitmq 余额充值 消费者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayRechargeReturnMessage { + /** + * 消息ID + */ + private String queue_id; + + + /** + * 充值地址 + */ + private String address; + + /** + * 充值是否成功 + */ + private Integer status; + + /** + * 链名称 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + + /** + * 充值金额 + */ + private BigDecimal amount; + + /** + * 交易ID + */ + private String tx_hash; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayWithdrawMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayWithdrawMessage.java new file mode 100644 index 0000000..874b256 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayWithdrawMessage.java @@ -0,0 +1,68 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @Description rabbitmq 余额提现 生产者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayWithdrawMessage { + /** + * 消息ID + */ + private String queue_id; + + /** + * 用户充值地址 + */ + private String from_address; + + /** + * 提现地址(用户自定义) + */ + private String to_address; + + + /** + * 提现金额 + */ + private BigDecimal amount; + + + /** + * 链名称 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + + + /** + * 时间戳 + */ + private Long timestamp; + + /** + * 签名 时间戳+m2pool + */ + private String sign; + + /** + * 手续费 + */ + private BigDecimal fee; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayWithdrawReturnMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayWithdrawReturnMessage.java new file mode 100644 index 0000000..8668c0b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPayWithdrawReturnMessage.java @@ -0,0 +1,58 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @Description rabbitmq 余额提现 消费者 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPayWithdrawReturnMessage { + /** + * 消息ID + */ + private String queue_id; + + + /** + * 提现结果 + */ + private Integer status; + + + /** + * 提现金额 + */ + private BigDecimal amount; + + + /** + * 链名称 + */ + private String chain; + + /** + * 币种 + */ + private String symbol; + + /** + * 交易ID + */ + private String tx_hash; + + /** + * 手续费 + */ + private BigDecimal fee; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPoolProxyMessage.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPoolProxyMessage.java new file mode 100644 index 0000000..b455b36 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/mq/message/RabbitmqPoolProxyMessage.java @@ -0,0 +1,37 @@ +package com.m2pool.lease.mq.message; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description ZMQ消息对象 + * @Date 2025/7/31 10:42 + * @Author yyb + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RabbitmqPoolProxyMessage { + /** + * 方法ID 0 add 1 delete + */ + private Integer MethodID; + + /** + * user-miner + */ + private String ID; + + /** + * 转发目标地址 + */ + private String Address; + + /** + * 转发矿池的mining.authorize方法配置参数 + */ + private String Msg; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseNexaMachineAvgPowerService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseNexaMachineAvgPowerService.java new file mode 100644 index 0000000..e0c56d4 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseNexaMachineAvgPowerService.java @@ -0,0 +1,16 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeaseNexaMachineAvgPower; + +/** + *

+ * 矿池nexa机器实时平均算力 服务类 + *

+ * + * @author yyb + * @since 2025-07-29 + */ +public interface LeaseNexaMachineAvgPowerService extends IService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseNexaMachinePowerService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseNexaMachinePowerService.java new file mode 100644 index 0000000..e373713 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseNexaMachinePowerService.java @@ -0,0 +1,16 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeaseNexaMachinePower; + +/** + *

+ * 已售商品矿工实时算力表 服务类 + *

+ * + * @author yyb + * @since 2025-07-25 + */ +public interface LeaseNexaMachinePowerService extends IService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseOrderInfoService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseOrderInfoService.java new file mode 100644 index 0000000..bb90748 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseOrderInfoService.java @@ -0,0 +1,72 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.OrderInfoDto; +import com.m2pool.lease.dto.PageResult; +import com.m2pool.lease.dto.PaymentRecordDto; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.entity.LeaseOrderInfo; +import com.m2pool.lease.vo.*; +import org.springframework.web.bind.annotation.RequestBody; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 订单表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseOrderInfoService extends IService { + /** + * 添加订单 + * @param orderAndCodeVo + * @return + */ + Result addOrders(OrderAndCodeVo orderAndCodeVo); + + + /** + * 再次购买 + * @param orderInfoVoList + * @return + */ + Result> buyAgain(List orderInfoVoList); + /** + * 根据订单状态查询订单列表(买家) + * @param orderInfoStateVo + * @return + */ + PageResult getOrdersByStatus(OrderInfoStateVo orderInfoStateVo); + + /** + * 根据订单状态查询订单列表(卖家) + * @param orderInfoStateVo + * @return + */ + PageResult getOrdersByStatusForSeller(OrderInfoStateVo orderInfoStateVo); + + /** + * 根据订单id查询订单 + * @param orderVo + * @return + */ + Result getOrdersByIds( OrderVo orderVo); + + /** + * 取消订单 + * @param orderVo + * @return + */ + Result cancelOrder(OrderVo orderVo); + + /** + * 获取用户选择的支付币种 获取实时币价 + * @param coinVo + * @return + */ + Result getCoinPrice(CoinVo coinVo); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseOrderItemService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseOrderItemService.java new file mode 100644 index 0000000..4e213ba --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseOrderItemService.java @@ -0,0 +1,16 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeaseOrderItem; + +/** + *

+ * 订单明细表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseOrderItemService extends IService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeasePayRecordMessageService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeasePayRecordMessageService.java new file mode 100644 index 0000000..c752e2e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeasePayRecordMessageService.java @@ -0,0 +1,15 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeasePayRecordMessage; + +/** + *

+ * service层支付 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +public interface LeasePayRecordMessageService extends IService { +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeasePaymentRecordService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeasePaymentRecordService.java new file mode 100644 index 0000000..22b83b0 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeasePaymentRecordService.java @@ -0,0 +1,66 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.PaymentCallbackDto; +import com.m2pool.lease.dto.PaymentRecordDto; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.entity.LeasePaymentRecord; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.CheckPayStatusVo; +import com.m2pool.lease.vo.OrderVo; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 支付记录表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeasePaymentRecordService extends IService { + + + /** + * 创建支付订单 + * + * @param orderVo + * @return + */ + Result> addPayOrder(OrderVo orderVo); + + /** + * 根据订单id查询支付订单 + * + * @param orderVo + * @return + */ + Result> getPayOrderByOrderId( OrderVo orderVo); + /** + * 支付回调结果---校验支付是否成功(批量校验) + * + * @param checkPayStatusVoList + * @return + */ + Result> paymentCallbackBatch(List checkPayStatusVoList); + + + /** + * 支付回调结果----根据支付订单id校验支付是否成功(单个校验) + * @param checkPayStatusVo + * @return + */ + Result paymentCallbackByPayId(CheckPayStatusVo checkPayStatusVo); + + + + /** + * 支付回调结果-----用于定时任务 + * @param leasePaymentRecordList + * @return + */ + void paymentCallbackTask(List leasePaymentRecordList); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductIncomeService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductIncomeService.java new file mode 100644 index 0000000..6a661fb --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductIncomeService.java @@ -0,0 +1,16 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeaseProductIncome; + +/** + *

+ * 商品收益表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseProductIncomeService extends IService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductMachineService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductMachineService.java new file mode 100644 index 0000000..7915ca8 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductMachineService.java @@ -0,0 +1,77 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.PageResult; +import com.m2pool.lease.dto.ProductUpdateMachineDto; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.dto.UserMinerDto; +import com.m2pool.lease.entity.LeaseProductMachine; +import com.m2pool.lease.vo.*; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + *

+ * 商品表对应的物品机器表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseProductMachineService extends IService { + + + /** + * 获取当前账户对应的挖矿账户 + * @return + */ + Result>> getUserMinersList(UserMinerVo userMinerVo); + + /** + * 获取当前账户对应的挖矿账户的机器矿工集合 + * @param userMinerVo + * @return + */ + Result> getUserMachineList(UserMinerVo userMinerVo); + + + /** + * 根据商品id查询商品矿机列表---用于卖方修改矿机信息 + * @param productForUpdateMachineVo + * @return + */ + PageResult getMachineListForUpdate(ProductForUpdateMachineVo productForUpdateMachineVo); + + /** + * 新增商品库存---实际需出售机器 + * @param productMachineParamsVoList + * @return + */ + Result addSingleOrBatchMachine(ProductMachineParamsVo productMachineParamsVoList); + + + /** + * 编辑商品 + 商品上下架---实际需出售机器 + * @param productUpdateMachineVoList + * @return + */ + Result updateMachine(List productUpdateMachineVoList); + + + /** + * 删除商品---实际需出售机器 + * @param baseVo + * @return + */ + Result deleteMachine(BaseVo baseVo); + + + /** + * 计算价格 + * @param priceCalculateVo + * @return + */ + Result calculatePrice(PriceCalculateVo priceCalculateVo); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductService.java new file mode 100644 index 0000000..1152d66 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseProductService.java @@ -0,0 +1,69 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeaseProduct; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.ProductPageVo; +import com.m2pool.lease.vo.ProductURDVo; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +/** + *

+ * 商品表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseProductService extends IService { + /** + * 查询商品列表 + * + * @return Result> 封装后的商品 DTO 列表 + */ + PageResult getProductList(ProductPageVo productPageVo); + + + /** + * 根据商品 ID 查询商品详情 + * + * @param BaseVo 商品 ID + * @return Result 封装后的商品 DTO + */ + Result getMachineInfoById( BaseVo baseVo); + + /** + * 根据商品 ID 查询商品详情 + * + * @param productId 商品 ID + * @return Result 封装后的商品 DTO + */ + Result getProductMachineInfo(Long productId); + + /** + * 新增商品 + * + * @param productURDVo 商品 DTO + * @return Result 操作结果 + */ + Result addProduct(ProductURDVo productURDVo); + + /** + * 编辑商品 + * + * @param productURDVo 商品 DTO + * @return Result 操作结果 + */ + Result updateProduct(ProductURDVo productURDVo); + + + /** + * 删除商品 + * @param id + * @return + */ + Result deleteProduct(Long id); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShopConfigService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShopConfigService.java new file mode 100644 index 0000000..3ebca23 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShopConfigService.java @@ -0,0 +1,16 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeaseShopConfig; + +/** + *

+ * 店铺商品配置表 服务类 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +public interface LeaseShopConfigService extends IService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShopService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShopService.java new file mode 100644 index 0000000..f59866a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShopService.java @@ -0,0 +1,117 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeaseShop; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.ShopConfigVo; +import com.m2pool.lease.vo.ShopVo; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 店铺表 服务类 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +public interface LeaseShopService extends IService { + + + /** + * 新增店铺 + * @param shopVo + * @return + */ + Result addShop(ShopVo shopVo); + + + /** + * 修改店铺 + * @param shopVo + * @return + */ + Result updateShop( ShopVo shopVo); + + /** + * 关闭店铺 + * @param baseVo + * @return + */ + Result closeShop( BaseVo baseVo); + + + /** + * 根据用户邮箱查询店铺 + * @return + */ + Result getShopByUserEmail(); + + /** + * 根据店铺id查询店铺 + * @param baseVo + * @return + */ + Result getShopById(BaseVo baseVo); + + + /** + * 删除店铺 + * @param baseVo + * @return + */ + Result deleteShop(BaseVo baseVo); + + + /** + * 根据店铺id 获取店铺配置信息列表 + * @param baseVo + * @return + */ + Result> getShopConfig(BaseVo baseVo); + + /** + * 根据 店铺id 获取店铺商品列表 + * @param baseVo + * @return + */ + Result> getProductListById(BaseVo baseVo); + + /** + * 新增商铺配置 + * @param shopConfigVo + * @return + */ + Result addShopConfig( ShopConfigVo shopConfigVo); + + + /** + * 修改商铺配置 + * @param shopConfigVo + * @return + */ + Result updateShopConfig( ShopConfigVo shopConfigVo); + + /** + * 删除商铺配置 + * @param baseVo + * @return + */ + Result deleteShopConfig(BaseVo baseVo); + + /** + * 获取链和链列表 + * @return + */ + Result> getChainAndList(); + + + Result> getChainAndListForSeller( BaseVo baseVo); + + + Result getChainAndCoin(BaseVo baseVo); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShoppingCartInfoService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShoppingCartInfoService.java new file mode 100644 index 0000000..0ec949e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShoppingCartInfoService.java @@ -0,0 +1,17 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.entity.LeaseShoppingCartInfo; + +/** + *

+ * 购物车详情表 服务类 + *

+ * + * @author yyb + * @since 2025-07-24 + */ +public interface LeaseShoppingCartInfoService extends IService { + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShoppingCartService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShoppingCartService.java new file mode 100644 index 0000000..f0d5b35 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseShoppingCartService.java @@ -0,0 +1,59 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.ShopCartDto; +import com.m2pool.lease.dto.ShoppingCartInfoDto; +import com.m2pool.lease.dto.PageResult; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.entity.LeaseShoppingCart; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.PageVo; +import com.m2pool.lease.vo.ProductAndMachineVo; +import com.m2pool.lease.vo.ShoppingCartInfoURDVo; + +import java.util.List; + +/** + *

+ * 购物车表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseShoppingCartService extends IService { + /** + * 添加购物车 + * @param shoppingCartInfoURDVoList + * @return + */ + Result addGoods(List shoppingCartInfoURDVoList); + + + /** + * 获取购物车列表 + * @param pageVo + * @return + */ + PageResult getGoodsList(PageVo pageVo); + + /** + * 批量删除购物车 + * @param baseVoList + * @return + */ + Result deleteBatchGoods(List baseVoList); + /** + * 删除购物车 + * @param baseVo + * @return + */ + Result deleteGoods(BaseVo baseVo); + + + /** + * 批量删除购物车中已下架商品 + * @return + */ + Result deleteBatchGoodsForIsDelete(); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseUserOwnedProductService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseUserOwnedProductService.java new file mode 100644 index 0000000..5edea6e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseUserOwnedProductService.java @@ -0,0 +1,49 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.PageResult; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.dto.UserOwnedProductDto; +import com.m2pool.lease.entity.LeaseOrderItem; +import com.m2pool.lease.entity.LeasePaymentRecord; +import com.m2pool.lease.entity.LeaseUserOwnedProduct; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.UserOwnedProductVo; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +/** + *

+ * 用户拥有商品详情表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseUserOwnedProductService extends IService { + + /** + * 用户查询当前自身已购商品列表 + * + * @param userOwnedProductVo + * @return + */ + PageResult getOwnedList(UserOwnedProductVo userOwnedProductVo); + + + /** + * 根据id查询当前自身已购商品详情 + * + * @param baseVo + * @return + */ + Result getOwnedById(BaseVo baseVo); + + /** + * 支付验证成功后去修改订单等信息 + * @param leaseOrderItems + * @return + */ + boolean afterPaySuccessTodoSomeEvent(List leaseOrderItems); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseUserService.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseUserService.java new file mode 100644 index 0000000..0295ed7 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/LeaseUserService.java @@ -0,0 +1,93 @@ +package com.m2pool.lease.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeaseUser; +import com.m2pool.lease.vo.*; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +public interface LeaseUserService extends IService { + + /** + * 用户登录/注册 + * @param userURDVo + * @return + */ + Result login(UserURDVo userURDVo); + + + /** + * 绑定钱包 + * @param chainAndCoinVo + * @return + */ + Result bindWallet( ChainAndCoinVo chainAndCoinVo); + + /** + * 获取用户相关钱包信息 + * @return + */ + Result> getWalletInfo(); + + + /** + * 余额提现 + * @return + */ + Result withdrawBalance(BalanceVo balanceVo); + + + /** + * 获取余额提现记录列表 + * @param balancePageVo + * @return + */ + PageResult balanceWithdrawList(BalancePageVo balancePageVo); + + /** + * 获取余额充值记录列表 + * @param balancePageVo + * @return + */ + PageResult balanceRechargeList(BalancePageVo balancePageVo); + + + /** + * 卖家:获取钱包交易(收款)记录表 + * @param balancePageVo + * @return + */ + PageResult balancePayList(BalancePageVo balancePageVo); + + /** + * 卖家:获取钱包交易(收款)记录表 + * @param recordTypePageVo + * @return + */ + PageResult transactionRecord( RecordTypePageVo recordTypePageVo); + + /** + * 最近5条交易 + * @return + */ + Result> getRecentlyTransaction(); + + + /** + * 获取手续费 + * @return + */ + Result> getCharge(); + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseNexaMachineAvgPowerServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseNexaMachineAvgPowerServiceImpl.java new file mode 100644 index 0000000..0052d83 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseNexaMachineAvgPowerServiceImpl.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeaseNexaMachineAvgPower; +import com.m2pool.lease.mapper.LeaseNexaMachineAvgPowerMapper; +import com.m2pool.lease.service.LeaseNexaMachineAvgPowerService; +import org.springframework.stereotype.Service; + +/** + *

+ * 矿池nexa机器实时平均算力 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-29 + */ +@Service +public class LeaseNexaMachineAvgPowerServiceImpl extends ServiceImpl implements LeaseNexaMachineAvgPowerService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseNexaMachinePowerServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseNexaMachinePowerServiceImpl.java new file mode 100644 index 0000000..81b411a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseNexaMachinePowerServiceImpl.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeaseNexaMachinePower; +import com.m2pool.lease.mapper.LeaseNexaMachinePowerMapper; +import com.m2pool.lease.service.LeaseNexaMachinePowerService; +import org.springframework.stereotype.Service; + +/** + *

+ * 已售商品矿工实时算力表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-25 + */ +@Service +public class LeaseNexaMachinePowerServiceImpl extends ServiceImpl implements LeaseNexaMachinePowerService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseOrderInfoServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseOrderInfoServiceImpl.java new file mode 100644 index 0000000..0b2e33c --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseOrderInfoServiceImpl.java @@ -0,0 +1,604 @@ +package com.m2pool.lease.service.impl; + +import cn.hutool.json.JSONUtil; +import com.baomidou.dynamic.datasource.annotation.DSTransactional; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +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; +import com.m2pool.common.redis.service.RedisService; +import com.m2pool.common.security.utils.SecurityUtils; +import com.m2pool.lease.constant.RedisKey; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.exception.OrderException; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.service.*; +import com.m2pool.lease.utils.QrCodeUtils; +import com.m2pool.lease.utils.UuidGeneratorUtil; +import com.m2pool.lease.vo.*; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + *

+ * 订单表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseOrderInfoServiceImpl extends ServiceImpl implements LeaseOrderInfoService { + + + @Resource + private LeaseOrderInfoMapper leaseOrderInfoMapper; + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Resource + private LeaseOrderItemService leaseOrderItemService; + + @Resource + private LeaseOrderItemMapper leaseOrderItemMapper; + + @Resource + private LeaseShopMapper leaseShopMapper; + + @Resource + private LeasePaymentRecordMapper leasePaymentRecordMapper; + + @Resource + private LeaseShoppingCartMapper leaseShoppingCartMapper; + + @Resource + private LeaseShoppingCartInfoMapper leaseShoppingCartInfoMapper; + + @Resource + private LeaseProductMapper leaseProductMapper; + + @Resource + private LeaseProductService leaseProductService; + + @Resource + private LeasePaymentRecordService leasePaymentRecordService; + + @Resource + private LeaseShopAddressConfigMapper leaseShopAddressConfigMapper; + + @Resource + private LeaseAutoAddressMapper leaseAutoAddressMapper; + + @Resource + private LeaseUserWalletDataMapper leaseUserWalletDataMapper; + + @Resource + private LeaseUserOwnedProductService leaseUserOwnedProductService; + + @Resource + private LeaseUserMapper leaseUserMapper; + + @Resource + private LeasePayRecordMessageMapper leasePayRecordMessageMapper; + + /** + * 计算订单总价格 + * @param orderInfoVoList 订单信息 + * @param machinesList 订单对应的矿机信息(这里面获取的价格单位固定是usdt) + * @return + */ + public BigDecimal calculateOrderPrice(List orderInfoVoList,List machinesList){ + Map machineListMap = machinesList.stream() + .collect(Collectors.toMap(LeaseProductMachine::getId, Function.identity())); + return orderInfoVoList.stream() + .map(orderInfoVo -> { + LeaseProductMachine machine = machineListMap.get(orderInfoVo.getMachineId()); + return (machine != null) ? + machine.getPrice().multiply(BigDecimal.valueOf(orderInfoVo.getLeaseTime())) : + BigDecimal.ZERO; + }) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } + + /** + * 修改订单支付地址,目前测试环境适用于自营(后续可能删除) + * @param shopConfigMap + */ + public void updatePayAddressForSelf( Map shopConfigMap){ + List leaseShopAddressConfigs = leaseShopAddressConfigMapper.selectList( + new LambdaQueryWrapper() + .eq(LeaseShopAddressConfig::getUserId, SecurityUtils.getUsername())); + Map shopAddressConfigMap = leaseShopAddressConfigs.stream().collect(Collectors.toMap(LeaseShopAddressConfig::getShopId, Function.identity())); + for (Long shopId : shopConfigMap.keySet()) { + if (!shopAddressConfigMap.containsKey(shopId)) { + LeaseAutoAddress oneStatusIsNoUse = leaseAutoAddressMapper.getOneStatusIsNoUse(); + if (oneStatusIsNoUse == null) { + throw new OrderException("订单生成失败,该商家可用的地址已使用完"); + } + String address = oneStatusIsNoUse.getAddress(); + String qrcode = QrCodeUtils.creatRrCode(address,200,200); + LeaseShopAddressConfig build = LeaseShopAddressConfig.builder() + .address(address) + .userId(SecurityUtils.getUsername()) + .shopId(shopId) + .qrcode(qrcode) + .build(); + leaseShopAddressConfigMapper.insert(build); + LeaseShopConfig leaseShopConfig = shopConfigMap.get(shopId); + leaseShopConfig.setQrcode(qrcode); + leaseShopConfig.setPayAddress(address); + } else { + LeaseShopAddressConfig leaseShopAddressConfig = shopAddressConfigMap.get(shopId); + LeaseShopConfig leaseShopConfig = shopConfigMap.get(shopId); + leaseShopConfig.setQrcode(leaseShopAddressConfig.getQrcode()); + leaseShopConfig.setPayAddress(leaseShopAddressConfig.getAddress()); + } + } + } + + /** + * 获取本次订单需总支付金额 + * + * @param leaseOrderItems + * @return + */ + public BigDecimal createPaymentOrders(List leaseOrderItems,Map shopConfigMap,LocalDateTime now,LeaseOrderInfo build){ + //按店铺id分组 + Map> shopMap = leaseOrderItems.stream().collect(Collectors.groupingBy(LeaseOrderItem::getShopId)); + List paymentRecordDTOs = new ArrayList<>(); + List paymentRecords = shopMap.values().stream() + .map(items -> { + LeaseOrderItem firstItem = items.get(0); + LeaseShopConfig leaseShopConfig = shopConfigMap.get(firstItem.getShopId()); + BigDecimal totalAmount = BigDecimal.ZERO; + for (LeaseOrderItem item : items) { + totalAmount = totalAmount.add(item.getPrice().multiply(BigDecimal.valueOf(item.getLeaseTime()))); + } + Long orderId = build.getId(); + Long productId = firstItem.getProductId(); + String payCoin = firstItem.getPayCoin(); + String address = firstItem.getAddress(); + + + paymentRecordDTOs.add(PaymentRecordDto.builder() + .payCoin(payCoin) + .amount(totalAmount) + .payAddress(address) + .img(leaseShopConfig.getQrcode()) + .build()); + + return LeasePaymentRecord.builder() + .orderId(orderId) + .shopId(firstItem.getShopId()) + .productId(productId) + .payCoin(payCoin) + .amount(totalAmount) + .payAddress(address) + .qrcode(leaseShopConfig.getQrcode()) + .createTime(now) + .build(); + }) + .collect(Collectors.toList()); + + + //4.保存支付订单 + //boolean saved = leasePaymentRecordService.saveBatch(paymentRecords); + //List rabbitmqOrderMessageList = paymentRecords.stream() + // .map(paymentRecord -> RabbitmqOrderMessage.builder().orderId(paymentRecord.getOrderId()).shopId(paymentRecord.getShopId()).build()) + // .collect(Collectors.toList()); + // + ////5.发送订单mq超时消息 + //rabbitTemplate.convertAndSend( + // ORDER_OVERTIME_EXCHANGE_NAME, + // ORDER_OVERTIME_ROUTING_KEY, + // rabbitmqOrderMessageList); + + + + + //返回总支付金额 + return paymentRecordDTOs.stream().map(PaymentRecordDto::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + + //throw new PaymentException("添加支付订单失败"); + } + + + + @Override + @DSTransactional + public Result addOrders(OrderAndCodeVo orderAndCodeVo ) { + BigDecimal price = orderAndCodeVo.getPrice(); + if (price.compareTo(BigDecimal.ZERO) <= 0){ + return Result.fail("获取的支付币种币价失败"); + } + List orderInfoVoList = orderAndCodeVo.getOrderInfoVoList(); + GoogleInfo googleInfo = leaseUserMapper.getGoogleInfoByEmail(SecurityUtils.getUsername()); + //校验当前用户是否存在该币种的钱包 + LeaseUserWalletData walletData = leaseUserWalletDataMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getUserId, SecurityUtils.getUsername()) + .eq(LeaseUserWalletData::getFromChain, orderAndCodeVo.getChain()) + .eq(LeaseUserWalletData::getFromSymbol, orderAndCodeVo.getCoin()) + .eq(LeaseUserWalletData::getDel, false) + ); + if (walletData == null){ + return Result.fail("余额不足,无法下单!您还没有绑定该链和币种钱包!"); + } + //TODO 开发环境 + //if(googleInfo == null || StringUtils.isBlank(googleInfo.getSecret())){ + // //未绑定定谷歌验证器 + // return Result.fail("您的账号未开启双重验证,请先开启验证!"); + //} + //if(!GoogleAuthenticator.checkCode(googleInfo.getSecret(), orderAndCodeVo.getCode(), System.currentTimeMillis())){ + // return Result.fail("谷歌验证码错误"); + //} + + if ("usdt".equalsIgnoreCase(orderAndCodeVo.getCoin())){ + orderAndCodeVo.setPrice(BigDecimal.ONE); + } + LocalDateTime now = LocalDateTime.now(); + List machineIds = new ArrayList<>(); + Set shopIds = new HashSet<>(); + Set productIds = new HashSet<>(); + + for (OrderInfoVo vo : orderInfoVoList) { + machineIds.add(vo.getMachineId()); + shopIds.add(vo.getShopId()); + productIds.add(vo.getProductId()); + } + //查询需要生成订单的矿机信息 + LeaseShoppingCart leaseShoppingCart = leaseShoppingCartMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShoppingCart::getUserId, SecurityUtils.getUsername())); + List machinesList = leaseProductMachineMapper.selectBatchIds(machineIds); + for (LeaseProductMachine leaseProductMachine : machinesList) { + if (leaseProductMachine.getState() == 1 || leaseProductMachine.getDel()){ + throw new OrderException("生成订单失败,订单矿机中存在已下架矿机"); + } + } + //删除购物车中矿机 + int delete = leaseShoppingCartInfoMapper.delete(new LambdaUpdateWrapper() + .eq(LeaseShoppingCartInfo::getCartId, leaseShoppingCart.getId()).in(LeaseShoppingCartInfo::getProductMachineId, machineIds)); + if (delete < 1){ + throw new OrderException("生成订单失败,购物车中不存在该矿机商品"); + } + //获取本次生成订单中所有矿机的总价(单位固定usdt) + BigDecimal totalPrice = calculateOrderPrice(orderInfoVoList, machinesList); + // 获取卖家店铺钱包配置(注意:目前同时只能结算一个店铺的,这里多个防止后续改成可以结算多个) + List payAddressAndPayCoin = leaseShopMapper.getPayAddressAndPayCoin(shopIds,orderAndCodeVo.getCoin(),orderAndCodeVo.getChain()); + Map shopConfigMap = payAddressAndPayCoin.stream() + .collect(Collectors.toMap(LeaseShopConfig::getShopId, Function.identity())); + + //订单主信息新增 + String userEmail = SecurityUtils.getUsername(); + String orderNumber = UuidGeneratorUtil.generateUuidWithoutHyphen(); + LeaseOrderInfo build = LeaseOrderInfo.builder() + .orderNumber(orderNumber) + .userId(userEmail) + .totalPrice(totalPrice) + .createTime(now) + .build(); + boolean save = save(build); + if (!save){ + throw new OrderException("订单生成失败"); + } + Map machineMap = orderInfoVoList.stream().collect(Collectors.toMap(OrderInfoVo::getMachineId, Function.identity())); + List leaseProducts = leaseProductMapper.selectBatchIds(productIds); + Map productMap = leaseProducts.stream().collect(Collectors.toMap(LeaseProduct::getId, Function.identity())); + List leaseOrderItems = new ArrayList<>(); + + //创建订单明细 + for (LeaseProductMachine leaseProductMachine : machinesList) { + LeaseShopConfig leaseShopConfig = shopConfigMap.get(leaseProductMachine.getShopId()); + if (leaseShopConfig == null){ + throw new OrderException("卖方未绑定钱包"); + } + OrderInfoVo orderInfoVo = machineMap.get(leaseProductMachine.getId()); + LeaseProduct leaseProduct = productMap.get(leaseProductMachine.getProductId()); + leaseProduct.setSaleNumber(leaseProduct.getSaleNumber() + 1); + leaseOrderItems.add( LeaseOrderItem.builder() + .userId(userEmail) + .orderId(build.getId()) + .productId(leaseProductMachine.getProductId()) + .productMachineId(leaseProductMachine.getId()) + //这里需要实时计算支付币种的个数 + .price(leaseProductMachine.getPrice().divide(orderAndCodeVo.getPrice(),6, RoundingMode.HALF_UP)) + .user(leaseProductMachine.getUser()) + .miner(leaseProductMachine.getMiner()) + .theoryIncome(leaseProductMachine.getTheoryIncome().multiply(BigDecimal.valueOf(orderInfoVo.getLeaseTime()))) + .coin(leaseProduct.getCoin()) + .leaseTime(orderInfoVo.getLeaseTime()) + .payCoin(leaseShopConfig.getPayCoin()) + .address(leaseShopConfig.getPayAddress()) + .chain(leaseShopConfig.getChain()) + .symbol(leaseShopConfig.getPayCoin()) + .name(leaseProduct.getName()) + .image(leaseProduct.getImage()) + .shopId(leaseProductMachine.getShopId()) + .fromAddress(walletData.getFromAddress()) + .fromChain(walletData.getFromChain()) + .fromSymbol(walletData.getFromSymbol()) + .type(leaseProduct.getType()) + .build()); + } + + boolean a = leaseProductService.updateBatchById(leaseProducts); + boolean b = leaseOrderItemService.saveBatch(leaseOrderItems); + //新增上述矿机到用户已购机器表中 + boolean c = leaseUserOwnedProductService.afterPaySuccessTodoSomeEvent(leaseOrderItems); + + //开始生成支付订单并返回 + if (a && b && c){ + BigDecimal totalPay = createPaymentOrders(leaseOrderItems, shopConfigMap, now, build); + BigDecimal subtract = totalPay.subtract(walletData.getBalance().subtract(walletData.getBlockedBalance())); + if (subtract.compareTo(BigDecimal.ZERO) <= 0 ){ + //修改商品矿机售出状态 以商品机器sale_state作为乐观锁 + int i = leaseProductMachineMapper.updateLockState(machineIds); + walletData.setBlockedBalance(walletData.getBlockedBalance().add(totalPay)); + leaseUserWalletDataMapper.updateById(walletData); + if (i != machineIds.size()){ + throw new OrderException("订单中已有商品售出,请刷新购物车删除已售出商品,重新结算生成订单"); + } + return Result.success("订单生成成功"); + }else{ + throw new OrderException("订单生成失败:未冻结余额不足,缺少" + subtract +"UDST 满足支付需求"); + } + } + throw new OrderException("订单生成失败"); + } + + @Override + public Result> buyAgain(List orderInfoVoList) { + //LocalDateTime now = LocalDateTime.now(); + //List machineIds = new ArrayList<>(); + //Set shopIds = new HashSet<>(); + //Set productIds = new HashSet<>(); + // + //for (OrderInfoVo vo : orderInfoVoList) { + // machineIds.add(vo.getMachineId()); + // shopIds.add(vo.getShopId()); + // productIds.add(vo.getProductId()); + //} + //List machinesList = leaseProductMachineMapper.selectBatchIds(machineIds); + //BigDecimal totalPrice = calculateOrderPrice(orderInfoVoList, machinesList); + ////获取商铺配置信息(支付地址,支付币种) 目前配置里面的支付地址 改为从leaseShopAddressConfig 获取 + //List payAddressAndPayCoin = leaseShopMapper.getPayAddressAndPayCoin(shopIds); + //Map shopConfigMap = payAddressAndPayCoin.stream().collect(Collectors.toMap(LeaseShopConfig::getShopId, Function.identity())); + //// 这里修改店铺配置的地址为我们自营的地址 + //updatePayAddressForSelf(shopConfigMap); + ////为商品机器加锁 以商品机器sale_state作为乐观锁 + //int i = leaseProductMachineMapper.updateLockState(machineIds); + //if (i != machineIds.size()){ + // throw new ProductSoldOutException("订单中已有商品售出,不能再次购买"); + //} + ////订单主信息新增 + //String orderNumber = UuidGeneratorUtil.generateUuidWithoutHyphen(); + //LeaseOrderInfo build = LeaseOrderInfo.builder() + // .orderNumber(orderNumber) + // .userId(SecurityUtils.getUsername()) + // .totalPrice(totalPrice) + // .createTime(now) + // .build(); + //boolean save = save(build); + //if (!save){ + // return Result.fail("添加订单失败"); + //} + // + ////创建订单明细 + //Map machineMap = orderInfoVoList.stream().collect(Collectors.toMap(OrderInfoVo::getMachineId, Function.identity())); + //List leaseProducts = leaseProductMapper.selectBatchIds(productIds); + //Map productMap = leaseProducts.stream().collect(Collectors.toMap(LeaseProduct::getId, Function.identity())); + //List leaseOrderItems = new ArrayList<>(); + //for (LeaseProductMachine leaseProductMachine : machinesList) { + // LeaseShopConfig leaseShopConfig = shopConfigMap.get(leaseProductMachine.getShopId()); + // OrderInfoVo orderInfoVo = machineMap.get(leaseProductMachine.getId()); + // LeaseProduct leaseProduct = productMap.get(leaseProductMachine.getProductId()); + // leaseOrderItems.add( LeaseOrderItem.builder() + // .orderId(build.getId()) + // .productId(leaseProductMachine.getProductId()) + // .productMachineId(leaseProductMachine.getId()) + // .price(leaseProductMachine.getPrice()) + // .user(leaseProductMachine.getUser()) + // .miner(leaseProductMachine.getMiner()) + // .theoryIncome(leaseProductMachine.getTheoryIncome().multiply(BigDecimal.valueOf(orderInfoVo.getLeaseTime()))) + // .coin(leaseProduct.getCoin()) + // .leaseTime(orderInfoVo.getLeaseTime()) + // .payCoin(leaseShopConfig.getPayCoin()) + // .address(leaseShopConfig.getPayAddress()) + // .name(leaseProduct.getName()) + // .image(leaseProduct.getImage()) + // .shopId(leaseProductMachine.getShopId()) + // .build()); + //} + //boolean b = leaseOrderItemService.saveBatch(leaseOrderItems); + ////开始生成支付订单并返回 + //if (b){ + // return Result.success(createPaymentOrders(leaseOrderItems, shopConfigMap, now, build)); + //} + //return Result.fail("生成支付订单失败"); + return null; + } + + @Override + public PageResult getOrdersByStatus(OrderInfoStateVo orderInfoStateVo) { + PageHelper.startPage(orderInfoStateVo.getPageNum(), orderInfoStateVo.getPageSize()); + + //获取订单信息 + List ordersByStatus = leaseOrderInfoMapper.getOrdersByStatus(SecurityUtils.getUsername(),orderInfoStateVo.getStatus()); + PageInfo pageInfo = new PageInfo<>(ordersByStatus); + List ids = ordersByStatus.stream().map(OrderInfoDto::getId).collect(Collectors.toList()); + if (ids.isEmpty()){ + return PageResult.fail(new ArrayList<>(),"不存在订单"); + } + //获取订单对应的订单详情列表 + List leaseOrderItems = leaseOrderItemMapper.selectList(new QueryWrapper() + .in("order_id",ids)); + + //设置订单详情集合,已支付金额,待支付金额 + setPayAmountAndItems(leaseOrderItems,ordersByStatus,ids); + + PageResult success = PageResult.success(ordersByStatus); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + + + @Override + public PageResult getOrdersByStatusForSeller(OrderInfoStateVo orderInfoStateVo) { + LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShop::getUserEmail, SecurityUtils.getUsername())); + + //查询到商铺的所有订单 + List orderItemList = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseOrderItem::getShopId, leaseShop.getId())); + if (orderItemList.isEmpty()){ + return PageResult.fail(new ArrayList<>(),"不存在订单"); + } + List orderInfoIds = orderItemList.stream().map(LeaseOrderItem::getOrderId).distinct().collect(Collectors.toList()); + PageHelper.startPage(orderInfoStateVo.getPageNum(), orderInfoStateVo.getPageSize()); + //获取订单信息 + List ordersByStatus = leaseOrderInfoMapper.getOrdersByStatusForSeller(orderInfoStateVo.getStatus(), orderInfoIds); + PageInfo pageInfo = new PageInfo<>(ordersByStatus); + setPayAmountAndItems(orderItemList,ordersByStatus,orderInfoIds); + PageResult success = PageResult.success(ordersByStatus); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + + } + + public void setPayAmountAndItems(List leaseOrderItems,List ordersByStatus,List ids){ + Map> collect = leaseOrderItems.stream().map(leaseOrderItem -> + OrderItemDto.builder() + .shopId(leaseOrderItem.getShopId()) + .orderId(leaseOrderItem.getOrderId()) + .productId(leaseOrderItem.getProductId()) + .productMachineId(leaseOrderItem.getProductMachineId()) + .leaseTime(leaseOrderItem.getLeaseTime()) + .address(leaseOrderItem.getAddress()) + .payCoin(leaseOrderItem.getPayCoin()) + .name(leaseOrderItem.getName()) + .price(leaseOrderItem.getPrice()) + .image(leaseOrderItem.getImage()) + .build() + ).collect(Collectors.groupingBy(OrderItemDto::getOrderId)); + + //获取订单已支付 和待支付金额 + List leasePayRecordMessages = leasePayRecordMessageMapper.selectList(new LambdaQueryWrapper().in(LeasePayRecordMessage::getOrderId, ids)); + Map collect1 = new HashMap<>(); + leasePayRecordMessages.forEach(leasePayRecordMessage -> { + HasPayTotalDto hasPayTotalDto = collect1.get(leasePayRecordMessage.getOrderId()); + if (hasPayTotalDto == null){ + collect1.put(leasePayRecordMessage.getOrderId(),HasPayTotalDto.builder() + .totalAmount(leasePayRecordMessage.getAmount()) + .totalRealAmount(leasePayRecordMessage.getRealAmount()) + .build()); + }else{ + hasPayTotalDto.setTotalAmount(hasPayTotalDto.getTotalAmount().add(leasePayRecordMessage.getAmount())); + hasPayTotalDto.setTotalRealAmount(hasPayTotalDto.getTotalRealAmount().add(leasePayRecordMessage.getRealAmount())); + collect1.put(leasePayRecordMessage.getOrderId(),hasPayTotalDto); + } + }); + + ordersByStatus.forEach(orderInfoDto -> { + List orderItems = collect.get(orderInfoDto.getId()); + HasPayTotalDto hasPayTotalDto = collect1.get(orderInfoDto.getId().toString()); + BigDecimal hasPayAmount = hasPayTotalDto == null ? BigDecimal.ZERO: hasPayTotalDto.getTotalAmount(); + BigDecimal hasPayRealAmount = hasPayTotalDto == null ? BigDecimal.ZERO: hasPayTotalDto.getTotalRealAmount(); + OrderItemDto orderItemDto = orderItems.get(0); + orderInfoDto.setOrderItemDtoList(orderItems); + orderInfoDto.setShopId(orderItemDto.getShopId()); + orderInfoDto.setNoPayAmount(orderInfoDto.getTotalPrice().subtract(hasPayAmount).doubleValue()); + orderInfoDto.setPayAmount(hasPayRealAmount.doubleValue()+"/"+hasPayAmount.doubleValue()); + }); + } + + @Override + public Result getOrdersByIds(OrderVo orderVo) { + + //获取订单主信息 + LeaseOrderInfo leaseOrderInfo = leaseOrderInfoMapper.selectById(orderVo.getOrderId()); + if (leaseOrderInfo == null){ + return Result.fail("未找到该订单"); + } + //获取订单对应的订单详情列表 + List leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseOrderItem::getOrderId, orderVo.getOrderId())); + + List collect1 = leaseOrderItems.stream().map(leaseOrderItem -> OrderItemDto.builder() + .orderId(leaseOrderItem.getOrderId()) + .productId(leaseOrderItem.getProductId()) + .productMachineId(leaseOrderItem.getProductMachineId()) + .leaseTime(leaseOrderItem.getLeaseTime()) + .address(leaseOrderItem.getAddress()) + .payCoin(leaseOrderItem.getPayCoin()) + .name(leaseOrderItem.getName()) + .image(leaseOrderItem.getImage()) + .price(leaseOrderItem.getPrice()) + .build()).collect(Collectors.toList()); + + OrderInfoDto orderInfoDto = OrderInfoDto.builder() + .id(leaseOrderInfo.getId()) + .orderNumber(leaseOrderInfo.getOrderNumber()) + .userId(leaseOrderInfo.getUserId()) + .totalPrice(leaseOrderInfo.getTotalPrice()) + .status(leaseOrderInfo.getStatus()) + .createTime(leaseOrderInfo.getCreateTime()) + .orderItemDtoList(collect1) + .build(); + + return Result.success(orderInfoDto); + } + + + @Override + public Result cancelOrder(OrderVo orderVo) { + int i = leaseOrderInfoMapper.updateById(LeaseOrderInfo.builder().id(orderVo.getOrderId()).status(2).build()); + if (i > 0){ + //删除支付订单 + int update = leasePaymentRecordMapper.update(LeasePaymentRecord.builder().del(false).build(), new LambdaQueryWrapper().eq(LeasePaymentRecord::getOrderId, orderVo.getOrderId())); + return Result.success("取消订单成功"); + } + return Result.fail("取消订单失败"); + } + + @Resource + private RedisService redisService; + + @Override + public Result getCoinPrice(CoinVo coinVo) { + BigDecimal coinPrice = getCoinPrice(coinVo.getCoin()); + return Result.success(coinPrice); + } + + public BigDecimal getCoinPrice(String coin) { + coin = coin.toLowerCase(); + String priceKey = RedisKey.getPiceKey(coin); + if (priceKey == null){ + return BigDecimal.ZERO; + } + BigDecimal price = redisService.getCacheBigDecimal(priceKey); + if (price != null){ + return price; + } + price = leaseOrderInfoMapper.getCoinPrice(coin); + //从数据库中获取最后一次存储的币价(可能不够实时) + if (price == null){ + return BigDecimal.ZERO; + } + return price; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseOrderItemServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseOrderItemServiceImpl.java new file mode 100644 index 0000000..8a30225 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseOrderItemServiceImpl.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeaseOrderItem; +import com.m2pool.lease.mapper.LeaseOrderItemMapper; +import com.m2pool.lease.service.LeaseOrderItemService; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单明细表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseOrderItemServiceImpl extends ServiceImpl implements LeaseOrderItemService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeasePayRecordMessageServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeasePayRecordMessageServiceImpl.java new file mode 100644 index 0000000..d1e6f97 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeasePayRecordMessageServiceImpl.java @@ -0,0 +1,19 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeasePayRecordMessage; +import com.m2pool.lease.mapper.LeasePayRecordMessageMapper; +import com.m2pool.lease.service.LeasePayRecordMessageService; +import org.springframework.stereotype.Service; + +/** + *

+ * service层支付 + *

+ * + * @author yyb + * @since 2025-09-10 + */ +@Service +public class LeasePayRecordMessageServiceImpl extends ServiceImpl implements LeasePayRecordMessageService { +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeasePaymentRecordServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeasePaymentRecordServiceImpl.java new file mode 100644 index 0000000..ae7fb42 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeasePaymentRecordServiceImpl.java @@ -0,0 +1,497 @@ +package com.m2pool.lease.service.impl; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.constant.PaymentStatus; +import com.m2pool.lease.dto.PaymentCallbackDto; +import com.m2pool.lease.dto.PaymentRecordDto; +import com.m2pool.lease.mq.message.RabbitmqPoolProxyMessage; +import com.m2pool.lease.dto.Result; +import com.m2pool.lease.entity.LeaseOrderInfo; +import com.m2pool.lease.entity.LeaseOrderItem; +import com.m2pool.lease.entity.LeasePaymentRecord; +import com.m2pool.lease.exception.PaymentException; +import com.m2pool.lease.mapper.LeaseOrderInfoMapper; +import com.m2pool.lease.mapper.LeaseOrderItemMapper; +import com.m2pool.lease.mapper.LeasePaymentRecordMapper; +import com.m2pool.lease.service.LeasePaymentRecordService; +import com.m2pool.lease.service.LeaseUserOwnedProductService; +import com.m2pool.lease.utils.HttpPayUtils; +import com.m2pool.lease.vo.CheckPayStatusVo; +import com.m2pool.lease.vo.OrderVo; +import com.m2pool.lease.vo.PayVo; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.ZoneId; +import java.util.*; +import java.util.stream.Collectors; + +import static com.m2pool.lease.constant.OrderStatus.FULLY_PAID; +import static com.m2pool.lease.constant.OrderStatus.PARTIALLY_PAID; +import static com.m2pool.lease.constant.PaymentStatus.*; +import static com.m2pool.lease.constant.RabbitmqConstant.POOL_PROXY_QUEUE_NAME; +import static com.m2pool.lease.utils.HttpPayUtils.PAY_ETH; + + +/** + *

+ * 支付记录表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeasePaymentRecordServiceImpl extends ServiceImpl implements LeasePaymentRecordService { + + + + @Resource + private RabbitTemplate rabbitTemplate; + + @Resource + private LeaseOrderItemMapper leaseOrderItemMapper; + + @Resource + private LeasePaymentRecordMapper leasePaymentRecordMapper; + + @Resource + private ThreadPoolTaskExecutor customThreadPool; + + @Resource + private LeaseOrderInfoMapper leaseOrderInfoMapper; + + @Resource + private LeaseUserOwnedProductService leaseUserOwnedProductService; + + @Override + @Transactional + public Result> addPayOrder(OrderVo orderVo) { + //1.根据订单id查询订单详情信息 + List leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseOrderItem::getOrderId, orderVo.getOrderId())); + + //2.按商品ID分组,并生成支付订单列表 + Map> productItemsMap = leaseOrderItems.stream() + .collect(Collectors.groupingBy(LeaseOrderItem::getProductId)); + //3.生成支付订单列表 + 封装返回对象 + List paymentRecordDTOs = new ArrayList<>(); + + List paymentRecords = productItemsMap.values().stream() + .map(items -> { + LeaseOrderItem firstItem = items.get(0); + BigDecimal totalAmount = items.stream() + .map(LeaseOrderItem::getPrice) + .reduce(BigDecimal.ZERO, BigDecimal::add); + Long orderId = orderVo.getOrderId(); + Long productId = firstItem.getProductId(); + String payCoin = firstItem.getPayCoin(); + String address = firstItem.getAddress(); + paymentRecordDTOs.add(PaymentRecordDto.builder() + .payCoin(payCoin) + .amount(totalAmount) + .payAddress(address) + .build()); + + return LeasePaymentRecord.builder() + .orderId(orderId) + .productId(productId) + .payCoin(payCoin) + .amount(totalAmount) + .payAddress(address) + .build(); + }) + .collect(Collectors.toList()); + + //4.保存支付订单 + boolean saved = saveBatch(paymentRecords); + if (saved) { + return Result.success(paymentRecordDTOs); + } else { + return Result.fail("生成支付订单失败"); + } + } + + @Override + public Result> getPayOrderByOrderId(OrderVo orderVo) { + List leasePaymentRecords = leasePaymentRecordMapper.selectList(new LambdaQueryWrapper() + .eq(LeasePaymentRecord::getOrderId, orderVo.getOrderId()) + .eq(LeasePaymentRecord::getDel, false)); + List collect = leasePaymentRecords.stream() + .map(record -> PaymentRecordDto.builder() + .id(record.getId()) + .payCoin(record.getPayCoin()) + .amount(record.getAmount()) + .payAddress(record.getPayAddress()) + .status(record.getStatus()) + .img(record.getQrcode()) + .build()).collect(Collectors.toList()); + return Result.success(collect); + } + + + @Override + @Transactional + public Result> paymentCallbackBatch(List checkPayStatusVoList) { + List paymentCallbackDTOs = new ArrayList<>(); + //1.查询处于待支付中状态(2)的订单 + List payIds = checkPayStatusVoList.stream().map(CheckPayStatusVo::getId).collect(Collectors.toList()); + List leasePaymentRecords = leasePaymentRecordMapper.selectList(new LambdaQueryWrapper() + .in(LeasePaymentRecord::getId, payIds) + .eq(LeasePaymentRecord::getDel, true) + .nested(wrapper -> wrapper + .eq(LeasePaymentRecord::getStatus, 2) + .or() + .eq(LeasePaymentRecord::getStatus, 10))); + + List orderIds = leasePaymentRecords.stream().map(LeasePaymentRecord::getOrderId).collect(Collectors.toList()); + //2.根据订单id查询订单详情信息 + List leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .in(LeaseOrderItem::getOrderId, orderIds)); + //3.按商店id分组 + Map> productItemsMap = leaseOrderItems.stream() + .collect(Collectors.groupingBy(LeaseOrderItem::getShopId)); + + //记录是否所有都支付成功 + int isAll = 0; + //4.按店铺分组---->合并店铺下所有支付订单----> 按所有总交易金额 去填充这些订单---->填充慢则表示这一笔订单支付成功----> 发货 + for (LeasePaymentRecord record : leasePaymentRecords) { + //4.1 调用三方api校验支付是否成功 + PaymentCallbackDto paymentCallbackDto = paymentCallback(record); + + if (paymentCallbackDto.getIsPayAll() == 1){ + //4.2 修改商品售出状态 + 新增机器到已购表中 (为了保证成功需要通过消息中间件达成最终一致性 demo暂时不修改) + List leaseOrderItemList = productItemsMap.get(record.getShopId()); + boolean isSuccess = leaseUserOwnedProductService.afterPaySuccessTodoSomeEvent(leaseOrderItemList); + if (!isSuccess){ + return Result.fail("支付校验成功√-->货款已付清√-->发货失败×。请提交工单发送订单给客服或者通过聊天系统联系客服解决"); + } + record.setStatus(1); + int i = leasePaymentRecordMapper.updateById(record); + isAll += i; + //4.3 发送rabbitmq消息给矿池代理 + sendRabbitmqMessage(leaseOrderItemList); + }else if (paymentCallbackDto.getIsPayAll() == 10){ + //支付了部分货款改状态---但是不发货 + leasePaymentRecordMapper.updateById(LeasePaymentRecord.builder().id(record.getId()).status(10).build()); + } + paymentCallbackDto.setTotalAmount(record.getAmount()); + paymentCallbackDTOs.add(paymentCallbackDto); + } + //5.修改订单状态为 1全部已支付 10部分已支付 + int status = isAll == leasePaymentRecords.size() ? 1 : 10; + Long orderId = leasePaymentRecords.get(0).getOrderId(); + int i = leaseOrderInfoMapper.updateById(LeaseOrderInfo.builder().id(orderId).status(status).build()); + if (i > 0){ + return Result.success(paymentCallbackDTOs); + }else { + return Result.fail("校验失败"); + } + } + + + @Override + @Transactional + public Result paymentCallbackByPayId(CheckPayStatusVo baseVo) { + LeasePaymentRecord record = leasePaymentRecordMapper.selectById(baseVo.getId()); + record.setFrom(baseVo.getForm()); + record.setHash(baseVo.getHash()); + //支付状态为2 待支付 或者 10 支付成功--已支付部分货款 两种状态可校验 + if (record.getStatus() == 10 || record.getStatus() == 2){ + //1.根据订单id + 店铺id 查询订单详情信息 (支付订单按shop分的,不再按商品分) + List leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseOrderItem::getOrderId, record.getOrderId()).eq(LeaseOrderItem::getShopId, record.getShopId())); + + //2.调用三方api校验支付是否成功 + PaymentCallbackDto paymentCallbackDto = paymentCallback(record); + if (paymentCallbackDto.getIsPayAll() == 1){ + boolean isSuccess = leaseUserOwnedProductService.afterPaySuccessTodoSomeEvent(leaseOrderItems); + if (!isSuccess){ + return Result.fail("支付校验成功√-->货款已付清√-->发货失败×。请提交工单发送订单给客服或者通过聊天系统联系客服解决"); + } + record.setStatus(1); + leasePaymentRecordMapper.updateById(record); + //2.1 发送rabbitmq消息给矿池代理 + sendRabbitmqMessage(leaseOrderItems); + } else if (paymentCallbackDto.getIsPayAll() == 10){ + //2.2 支付了部分货款改状态---但是不发货 + leasePaymentRecordMapper.updateById(LeasePaymentRecord.builder().id(record.getId()).status(10).build()); + } + //3.查询订单是否下所有支付订单都已支付完成 + Long l = leasePaymentRecordMapper.selectCount(new LambdaQueryWrapper() + .eq(LeasePaymentRecord::getOrderId, record.getOrderId()) + .eq(LeasePaymentRecord::getDel, true) + .ne(LeasePaymentRecord::getStatus,1)); + //4.修改订单为全部已支付 + if (l == 0){ + leaseOrderInfoMapper.updateById(LeaseOrderInfo.builder().id(record.getOrderId()).status(1).build()); + } + return Result.success(paymentCallbackDto); + } + return Result.fail("验证失败,该订单状态不为支付成功未验证状态"); + } + + @Override + @Transactional + public void paymentCallbackTask(List leasePaymentRecordList) { + List orderIds = leasePaymentRecordList.stream().map(LeasePaymentRecord::getOrderId).distinct().collect(Collectors.toList()); + //1---根据订单id查询订单详情信息 + List leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .in(LeaseOrderItem::getOrderId, orderIds)); + //2---按商店id - 订单id 分组 + Map> productItemsMap = leaseOrderItems.stream() + .collect(Collectors.groupingBy( + item -> item.getShopId() + "-" + item.getOrderId() + )); + //3---支付订单按支付地址分组 校验 + Map> shopMaps = leasePaymentRecordList.stream().collect(Collectors.groupingBy(LeasePaymentRecord::getPayAddress)); + + List afterCheckPaymentList = shopMaps.entrySet().stream() + .map(entry -> { + String key = entry.getKey(); + List values = entry.getValue(); + // 查找已经支付的金额 + BigDecimal paySuccessAmount = values.stream().map(LeasePaymentRecord::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal alreadyPayAmount = getAlreadyPayAmount(key, values).subtract(paySuccessAmount); + + // 在迭代过程中修改列表,使用 fori 循环避免 ConcurrentModificationException + for (int i = 0; i < values.size(); i++) { + LeasePaymentRecord leasePaymentRecord = values.get(i); + BigDecimal needPayAmount = leasePaymentRecord.getAmount(); + BigDecimal payAmount = leasePaymentRecord.getPayAmount(); + // 如果该支付订单已支付了部分金额 剩下需支付需减去该值 + if (payAmount.compareTo(BigDecimal.ZERO) != 0) { + needPayAmount = needPayAmount.subtract(payAmount); + } + // 已支付金额 不等于 需支付总金额 + if (payAmount.compareTo(needPayAmount) != 0) { + if (needPayAmount.compareTo(alreadyPayAmount) < 0) { + // 条件1: 交易记录金额大于需要支付的金额------> 该订单状态可改为 1全部已支付 + alreadyPayAmount = alreadyPayAmount.subtract(needPayAmount); + leasePaymentRecord.setStatus(PAYMENT_SUCCESS_FULL.getCode()); + leasePaymentRecord.setPayAmount(leasePaymentRecord.getAmount()); + } else if (needPayAmount.compareTo(alreadyPayAmount) > 0 && alreadyPayAmount.compareTo(BigDecimal.ZERO) != 0) { + // 条件2: 交易记录金额小于需要支付的金额 ,但是交易记录金额不为0 ------> 该订单可改为状态 10部分已支付 + alreadyPayAmount = BigDecimal.ZERO; + leasePaymentRecord.setStatus(PAYMENT_SUCCESS_PARTIAL.getCode()); + leasePaymentRecord.setPayAmount(alreadyPayAmount); + } else if (PAYMENT_SUCCESS_PARTIAL.getCode() == leasePaymentRecord.getStatus()) { + // 条件3: 走到这里说明,交易金额已经分配完毕。 如果本身为部分已支付,直接去除 + values.remove(i); + i--; + } + } else { + // 已支付金额 等于 需支付总金额 直接剔除 + values.remove(i); + i--; + } + } + return values; + }) + .flatMap(List::stream) // 展开嵌套的列表 + .collect(Collectors.toList()); + + + List rabbitmqMessages = new ArrayList<>(); + //4---更新支付状态变化的支付订单 + 支付订单为完成支付的 订单开始 发货 + for (LeasePaymentRecord record : afterCheckPaymentList) { + //4.1全部支付成功的才能发货 + if (PaymentStatus.PAYMENT_SUCCESS_FULL.getCode() == record.getStatus()){ + String key = record.getShopId() + "-" + record.getOrderId(); + List leaseOrderItemList = productItemsMap.get(key); + leaseUserOwnedProductService.afterPaySuccessTodoSomeEvent(leaseOrderItemList); + rabbitmqMessages.addAll(leaseOrderItemList); + } + //4.2 修改支付订单的状态 + leasePaymentRecordMapper.updateById(record); + } + + + + //5---发送rabbitmq消息给矿池代理 + sendRabbitmqMessage(rabbitmqMessages); + + //6---修改普通订单状态 + //统计每个普通订单对应的支付订单数量 + Map orderIdCountMap = leasePaymentRecordList.stream() + .collect(Collectors.groupingBy(LeasePaymentRecord::getOrderId, Collectors.counting())); + // 统计每个订单对应的支付已全部完成的数量 + Map fullPaidCountMap = leasePaymentRecordList.stream() + .filter(record -> record.getStatus() == PAYMENT_SUCCESS_FULL.getCode()) + .collect(Collectors.groupingBy(LeasePaymentRecord::getOrderId, Collectors.counting())); + // 统计每个订单对应的部分已完成的数量 + Map partialPaidCountMap = leasePaymentRecordList.stream() + .filter(record -> record.getStatus() == PAYMENT_SUCCESS_PARTIAL.getCode()) + .collect(Collectors.groupingBy(LeasePaymentRecord::getOrderId, Collectors.counting())); + + // 遍历 orderIdCountMap,更新订单状态 + for (Map.Entry entry : orderIdCountMap.entrySet()) { + Long orderId = entry.getKey(); + Long totalCount = entry.getValue(); + Long fullPaidCount = fullPaidCountMap.getOrDefault(orderId, 0L); + Long partialPaidCount = partialPaidCountMap.getOrDefault(orderId, 0L); + if (Objects.equals(fullPaidCount, totalCount)) { + // 全部已完成 + leaseOrderInfoMapper.updateById(LeaseOrderInfo.builder().id(orderId).status(FULLY_PAID.getCode()).build()); + //TODO 长连接联系前端支付已完成 + } else if (partialPaidCount > 0) { + // 部分已完成 + leaseOrderInfoMapper.updateById(LeaseOrderInfo.builder().id(orderId).status(PARTIALLY_PAID.getCode()).build()); + } + } + + + + } + + + /** + * 获取当前用户已支付的金额 + * @param leasePaymentRecordList + * @return + */ + private BigDecimal getAlreadyPayAmount(String payAddress,List leasePaymentRecordList) { + LeasePaymentRecord leasePaymentRecord = leasePaymentRecordList.get(0); + PayVo build = PayVo.builder() + .ts(leasePaymentRecord.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond()) + .address(payAddress) + .build(); + HttpPayUtils.PaymentDto paymentDto = HttpPayUtils.doPost(PAY_ETH, JSONUtil.toJsonStr(build)); + + BigDecimal totalAmount = BigDecimal.ZERO; + List paymentData = handlerResponse(paymentDto); + for (HttpPayUtils.PaymentData result : paymentData){ + String valueStr = result.getValue(); + BigDecimal divisor = BigDecimal.TEN.pow(6); + BigDecimal resultAmount = new BigDecimal(valueStr).divide(divisor,6, RoundingMode.HALF_UP); + totalAmount = totalAmount.add(resultAmount); + } + + return totalAmount; + } + + + /** + * 调用三方api 进行支付校验 + * @param record + * @return + */ + private PaymentCallbackDto paymentCallback(LeasePaymentRecord record) { + PayVo build = PayVo.builder() + .ts(record.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond()) + .coin(record.getPayCoin()) + .amount(record.getAmount()) + .address(record.getPayAddress()) + .build(); + HttpPayUtils.PaymentDto paymentDto = HttpPayUtils.doPost(PAY_ETH, JSONUtil.toJsonStr(build)); + + List paymentData = handlerResponse(paymentDto); + if (paymentData != null && !paymentData.isEmpty()){ + return payIsSuccess(record, paymentData); + }else{ + throw new PaymentException("验证失败,卖方不存在转账记录"); + } + } + + /** + * 校验代码 + * @param record + * @param paymentData + * @return + */ + private PaymentCallbackDto payIsSuccess(LeasePaymentRecord record,List paymentData){ + //待支付状态为2 + int isPayAll = 2; + BigDecimal noPayAmount = record.getAmount(); + for (HttpPayUtils.PaymentData result : paymentData){ + String valueStr = result.getValue(); + BigDecimal divisor = BigDecimal.TEN.pow(6); + BigDecimal resultAmount = new BigDecimal(valueStr).divide(divisor,6, RoundingMode.HALF_UP); + long timeStamp = Long.parseLong(result.getTimeStamp()); + long ts = record.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + //交易hash 和 买家钱包地址 有一个校验通过即可(只适用于自营校验) + if (timeStamp >= ts && (result.getFrom().equals(record.getFrom()) || result.getHash().equals(record.getHash()))){ + noPayAmount = noPayAmount.subtract(resultAmount); + //全部货款已支付 + if (noPayAmount.compareTo(BigDecimal.ZERO) == 0){ + isPayAll = 1; + break; + } + } + + + } + //已支付部分货款 + if (noPayAmount.compareTo(record.getAmount()) != 0 && noPayAmount.compareTo(BigDecimal.ZERO) != 0){ + isPayAll = 10; + } + + return PaymentCallbackDto.builder().isPayAll(isPayAll).noPayAmount(noPayAmount).build(); + } + + /** + * 三方api调用异常 + * @param paymentDto + * @return + */ + private List handlerResponse(HttpPayUtils.PaymentDto paymentDto){ + if (paymentDto != null){ + if (paymentDto.isResult() && paymentDto.getCode() == 0) { + // 支付成功,处理返回的交易数据 + List transactions = paymentDto.getData(); + return transactions; + } else { + // 支付失败,根据 code 处理不同错误 + switch (paymentDto.getCode()) { + case -1: + throw new PaymentException("未转账"); + case -2: + throw new PaymentException("coin参数不支持"); + default: + throw new PaymentException("支付未知错误"); + } + } + }else { + return null; + } + + } + + /** + * 发送rabbitmq消息给矿机代理 + * @param leaseOrderItems + */ + public void sendRabbitmqMessage( List leaseOrderItems) { + leaseOrderItems.forEach(item -> { + customThreadPool.execute(()->{ + RabbitmqPoolProxyMessage rabbitmqPoolProxyMessage = RabbitmqPoolProxyMessage.builder() + .MethodID(0) + .Msg("") + .ID(item.getUser() + "-" + item.getMiner()) + .Address(item.getAddress()) + .build(); + try { + rabbitTemplate.convertAndSend(POOL_PROXY_QUEUE_NAME, rabbitmqPoolProxyMessage); + } catch (Exception e) { + System.err.println("发送失败: " + e.getMessage()); + } + }); + }); + + } + + + + + + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductIncomeServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductIncomeServiceImpl.java new file mode 100644 index 0000000..ebb6c95 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductIncomeServiceImpl.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeaseProductIncome; +import com.m2pool.lease.mapper.LeaseProductIncomeMapper; +import com.m2pool.lease.service.LeaseProductIncomeService; +import org.springframework.stereotype.Service; + +/** + *

+ * 商品收益表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseProductIncomeServiceImpl extends ServiceImpl implements LeaseProductIncomeService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductMachineServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductMachineServiceImpl.java new file mode 100644 index 0000000..d68f31f --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductMachineServiceImpl.java @@ -0,0 +1,315 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DSTransactional; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.m2pool.common.redis.service.RedisService; +import com.m2pool.common.security.utils.SecurityUtils; +import com.m2pool.lease.constant.BlockInterval; +import com.m2pool.lease.constant.RedisKey; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeaseProduct; +import com.m2pool.lease.entity.LeaseProductMachine; +import com.m2pool.lease.mapper.LeaseNexaMachinePowerMapper; +import com.m2pool.lease.mapper.LeaseProductMachineMapper; +import com.m2pool.lease.mapper.LeaseProductMapper; +import com.m2pool.lease.service.LeaseProductMachineService; +import com.m2pool.lease.utils.PowerUnitUtils; +import com.m2pool.lease.vo.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 商品表对应的物品机器表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseProductMachineServiceImpl extends ServiceImpl implements LeaseProductMachineService { + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Resource + private LeaseProductMapper leaseProductMapper; + + @Resource + private ApplicationContext applicationContext; + + @Resource + private RedisService redisService; + + + @Override + public Result> > getUserMinersList(UserMinerVo userMinerVo) { + String userId = SecurityUtils.getUsername(); + + //测试 挖矿账号 + //userId = "Eudora.law@outlook.com"; + List userMinersList = leaseProductMachineMapper.getUserMinersList(userId,userMinerVo.getCoin()); + Map> collect = userMinersList.stream().collect(Collectors.groupingBy(UserMinerDto::getCoin)); + return Result.success(collect); + } + + @Override + public Result> getUserMachineList(UserMinerVo userMinerVo) { + //获取1天内的存在算力的机器(这里user 和coin 组成了表的唯一键,不用担心查询到其他用户相同的user和coin的矿机) + List minerMachines = leaseProductMachineMapper.getMinerMachines(userMinerVo.getUser(), userMinerVo.getCoin()); + //根据矿工账号查询已经新增到商品机器表中的机器 + List minerMachinesIsSale = leaseProductMachineMapper.getMinerMachinesIsSale(userMinerVo.getUser(), userMinerVo.getCoin()); + // 过滤 minerMachines 集合,只保留 miner 字段值不在 existingMiners 中的元素 + minerMachines = minerMachines.stream() + .filter(dto -> !minerMachinesIsSale.contains(dto.getMiner())) + .peek(dto -> { + dto.setRealPower(dto.getRealPower().divide(BigDecimal.valueOf(24 * 60 * 60),2, RoundingMode.HALF_UP)); + dto.setRealPower(dto.getRealPower().setScale(2, RoundingMode.HALF_UP)); + }) + .collect(Collectors.toList()); + return Result.success(minerMachines); + } + + @Override + public PageResult getMachineListForUpdate(ProductForUpdateMachineVo productForUpdateMachineVo) { + PageHelper.startPage(productForUpdateMachineVo.getPageNum(), productForUpdateMachineVo.getPageSize()); + List leaseProductMachines = leaseProductMachineMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseProductMachine::getProductId, productForUpdateMachineVo.getId()).eq(LeaseProductMachine::getDel,false)); + PageInfo pageInfo = new PageInfo<>(leaseProductMachines); + + List productUpdateMachineDtos = leaseProductMachines.stream().map(leaseProductMachine -> + ProductUpdateMachineDto.builder() + .id(leaseProductMachine.getId()) + .user(leaseProductMachine.getUser()) + .type(leaseProductMachine.getType()) + .miner(leaseProductMachine.getMiner()) + .price(leaseProductMachine.getPrice()) + .computingPower(leaseProductMachine.getComputingPower().setScale(2, RoundingMode.HALF_UP)) + .theoryPower(leaseProductMachine.getTheoryPower()) + .unit(leaseProductMachine.getUnit()) + .maxLeaseDays(leaseProductMachine.getMaxLeaseDays()) + .state(leaseProductMachine.getState()) + .saleState(leaseProductMachine.getSaleState()) + .powerDissipation(leaseProductMachine.getPowerDissipation()) + .build() + ).collect(Collectors.toList()); + PageResult success = PageResult.success(productUpdateMachineDtos); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + @Override + @DSTransactional + public Result addSingleOrBatchMachine(ProductMachineParamsVo productMachineParamsVo) { + LeaseProduct product = leaseProductMapper.selectById(productMachineParamsVo.getProductId()); + + String coin = product.getCoin(); + if (coin == null){ + return Result.fail("商品币种不能为空"); + } + //封装需要添加的商品的机器 + List leaseProductMachines = new ArrayList<>(); + List productMachineURDVos = productMachineParamsVo.getProductMachineURDVos(); + + productMachineURDVos.forEach(machine -> { + leaseProductMachines.add(LeaseProductMachine.builder() + .shopId(product.getShopId()) + .productId(productMachineParamsVo.getProductId()) + .type(machine.getType() == null ? productMachineParamsVo.getType() : machine.getType()) + .theoryPower(machine.getTheoryPower() == null ? productMachineParamsVo.getTheoryPower() : machine.getTheoryPower()) + .powerDissipation(productMachineParamsVo.getPowerDissipation()) + .cost(productMachineParamsVo.getCost()) + .price(machine.getPrice() == null ? productMachineParamsVo.getCost() : machine.getPrice()) + .incomeRate(BigDecimal.ZERO) + .maxLeaseDays(machine.getMaxLeaseDays() == null ? productMachineParamsVo.getMaxLeaseDays() : machine.getMaxLeaseDays()) + .unit(machine.getUnit() == null ? productMachineParamsVo.getUnit() : machine.getUnit()) + .powerDissipation(machine.getPowerDissipation() == null ? productMachineParamsVo.getPowerDissipation() : machine.getPowerDissipation()) + .user(machine.getUser()) + .miner(machine.getMiner()) + .coin(coin) + .state(machine.getState()) + .del( false) + .saleState(0) + .build()); + }); + + + + //计算对应user+miner 一天的总算力 + List nexaMinersv2 = leaseProductMachineMapper.getRecentlyFiveMinutesData(leaseProductMachines, product.getCoin()); + // 创建一个 Map 用于存储 user 和 miner 组合对应的 ProductMachineDto 对象 + Map machineDtoMap = nexaMinersv2.stream() + .collect(Collectors.toMap( + dto -> dto.getUser() + "-" + dto.getMiner(), + dto -> dto + )); + String priceKey = RedisKey.getPiceKey(product.getCoin()); + String rewardKey = RedisKey.getRewardKey(product.getCoin()); + String mhsKey = RedisKey.getMhsKey(product.getCoin()); + + if (priceKey == null || rewardKey == null || mhsKey == null){ + return Result.fail("添加商品失败,该币种挖矿机器暂时不支持"); + } + + BigDecimal price = redisService.getCacheBigDecimal(priceKey) == null ? BigDecimal.ZERO : redisService.getCacheBigDecimal(priceKey); + BigDecimal reward = redisService.getCacheBigDecimal(rewardKey) == null ? BigDecimal.ZERO : redisService.getCacheBigDecimal(rewardKey); + //全网算力单位是MH/s + BigDecimal netPower = redisService.getCacheBigDecimal(mhsKey) == null ? BigDecimal.ZERO : redisService.getCacheBigDecimal(mhsKey); + + if (price == null){ + return Result.fail("添加商品失败,未获取到"+product.getCoin()+"币的币价,请稍后重试"); + } + if (reward == null){ + return Result.fail("添加商品失败,未获取到"+product.getCoin()+"币的报快奖励,请稍后重试"); + } + if (netPower == null){ + return Result.fail("添加商品失败,未获取到"+product.getCoin()+"币的全网算力,请稍后重试"); + } + + + + List collect = leaseProductMachines.stream().peek(productMachineURDVo -> { + //获取单机实际算力 + String key = productMachineURDVo.getUser() + "-" + productMachineURDVo.getMiner(); + ProductMachineDto productMachineDto = machineDtoMap.get(key); + BigDecimal singleTheoryMachineIncome = BigDecimal.ZERO; + BigDecimal computingPower = BigDecimal.ZERO; + + if (productMachineDto != null && productMachineDto.getComputingPower() != null){ + //计算矿机一天内实际每秒平均算力 + computingPower = PowerUnitUtils.getPower(productMachineURDVo.getUnit(), productMachineDto.getComputingPower() + .multiply(BigDecimal.valueOf(1000 * 1000)) + .divide(BigDecimal.valueOf(24 * 60 * 60), 2, RoundingMode.HALF_UP)); + BigDecimal power = PowerUnitUtils.getPower(productMachineURDVo.getUnit(), netPower.multiply(BigDecimal.valueOf(1000 * 1000))); + //理论收益 = 矿机算力/全网算力 * 24h /出块间隔秒数 * 单块奖励(redis中nexa:reward) + singleTheoryMachineIncome = computingPower.divide( power,6, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(24 * 60 * 60) + .divide(BlockInterval.getBlockCountByCoinName(product.getCoin()), 6, RoundingMode.HALF_UP)) + .multiply(reward) + ; + + } + productMachineURDVo.setShopId(product.getShopId()); + productMachineURDVo.setComputingPower(computingPower); + productMachineURDVo.setTheoryIncome(singleTheoryMachineIncome); + }).collect(Collectors.toList()); + //新增矿机 + int i = leaseProductMachineMapper.saveOrUpdateBatchs(collect); + if (i >= 1){ + //修改商品的价格范围 及商品下机器库存数量 + updatePriceRange(product.getId()); + return Result.success("添加成功,添加矿机数:"+collect.size()); + } + return Result.fail("添加失败"); + } + + @Override + @Transactional + public Result updateMachine(List productUpdateMachineVoList) { + + List ids = new ArrayList<>(); + List leaseProductMachines = new ArrayList<>(); + productUpdateMachineVoList.forEach(machine -> { + leaseProductMachines.add( LeaseProductMachine.builder() + .id(machine.getId()) + .type(machine.getType()) + .theoryPower(machine.getTheoryPower()) + .unit(machine.getUnit()) + .powerDissipation(machine.getPowerDissipation()) + //.electricityBill(machine.getElectricityBill()) + .incomeRate(machine.getIncomeRate()) + .price(machine.getPrice()) + .maxLeaseDays(machine.getMaxLeaseDays()) + .user(machine.getUser()) + .miner(machine.getMiner()) + .state(machine.getState()) + .build()); + if (machine.getState() == 1){ + ids.add(machine.getId()); + } + }); + if (!ids.isEmpty()){ + List leaseProductMachines1 = leaseProductMachineMapper.selectBatchIds(ids); + long count = leaseProductMachines1.stream().filter(leaseProductMachine -> leaseProductMachine.getSaleState() == 1).count(); + if (count >= 1){ + return Result.fail("商品修改失败,部分矿机租约已存在,不能下架"); + } + } + + + + boolean b = updateBatchById(leaseProductMachines); + if (b){ + LeaseProductMachine leaseProductMachine = leaseProductMachineMapper.selectById(productUpdateMachineVoList.get(0).getId()); + //修改商品的价格范围 + updatePriceRange(leaseProductMachine.getProductId()); + return Result.success("修改成功"); + } + return Result.fail("修改失败"); + } + + + @Override + @Transactional + public Result deleteMachine(BaseVo baseVo) { + LeaseProductMachine leaseProductMachine = leaseProductMachineMapper.selectById(baseVo.getId()); + if (leaseProductMachine.getSaleState() != 0){ + return Result.fail("该商品已售出,暂时不能删除"); + } + //修改商品的价格范围 及商品下机器库存数量 + + boolean b = updateById(LeaseProductMachine.builder().id(baseVo.getId()).del(true).build()); + if (b){ + updatePriceRange(leaseProductMachine.getProductId()); + return Result.success("删除成功"); + } + return Result.fail("删除失败"); + } + + /** + * 修改商品价格范围 + * @param productId + */ + public void updatePriceRange(Long productId){ + + //修改商品的价格范围 + PriceDto priceDto = leaseProductMachineMapper.getPriceRange(productId); + BigDecimal maxPrice = BigDecimal.ZERO; + BigDecimal minPrice = BigDecimal.ZERO; + Integer totalMachineNumber = 0; + if (priceDto != null){ + totalMachineNumber = priceDto.getTotalMachineNumber(); + maxPrice = priceDto.getPriceMax(); + minPrice = priceDto.getPriceMin(); + } + LeaseProduct build = LeaseProduct.builder().id(productId) + .minPrice(minPrice) + .maxPrice(maxPrice) + .totalMachineNumber(totalMachineNumber ) + .build(); + leaseProductMapper.updateById(build); + } + + @Override + public Result calculatePrice(PriceCalculateVo priceCalculateVo) { + //TODO 第三方计算器 + + return null; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductServiceImpl.java new file mode 100644 index 0000000..971e3dc --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseProductServiceImpl.java @@ -0,0 +1,502 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.m2pool.common.redis.service.RedisService; +import com.m2pool.lease.constant.Algorithm; +import com.m2pool.lease.constant.BlockInterval; +import com.m2pool.lease.constant.RedisKey; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.LeaseProduct; +import com.m2pool.lease.entity.LeaseProductMachine; +import com.m2pool.lease.entity.LeaseShop; +import com.m2pool.lease.entity.LeaseShopConfig; +import com.m2pool.lease.exception.ProductSoldOutException; +import com.m2pool.lease.mapper.LeaseProductMachineMapper; +import com.m2pool.lease.mapper.LeaseProductMapper; +import com.m2pool.lease.mapper.LeaseShopConfigMapper; +import com.m2pool.lease.mapper.LeaseShopMapper; +import com.m2pool.lease.service.LeaseProductService; +import com.m2pool.lease.utils.PowerUnitUtils; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.ProductPageVo; +import com.m2pool.lease.vo.ProductURDVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + *

+ * 商品表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseProductServiceImpl extends ServiceImpl implements LeaseProductService { + + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Resource + private LeaseProductMapper leaseProductMapper; + + @Resource + private RedisService redisService; + + @Resource + private LeaseShopMapper leaseShopMapper; + + @Resource + private LeaseShopConfigMapper leaseShopConfigMapper; + + + @Override + public PageResult getProductList(ProductPageVo productPageVo) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper().eq(LeaseProduct::getDel, false); + Long shopId = 0L; + + System.out.println("用户邮箱参数:"+productPageVo.getUserEmail()); + //1.用户邮箱参数不为空,则表示个人中心的商品列表。这个时候能看到下架的商品 + if (productPageVo.getUserEmail() != null && !productPageVo.getUserEmail().isEmpty()){ + LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShop::getUserEmail, productPageVo.getUserEmail())); + if (leaseShop != null){ + shopId = leaseShop.getId(); + }else{ + throw new ProductSoldOutException("不存在出售商品"); + } + } + PageHelper.startPage(productPageVo.getPageNum(), productPageVo.getPageSize()); + List leaseProducts = leaseProductMapper.getProductListForShopAndUserCenter(productPageVo.getCoin(), productPageVo.getAlgorithm(), shopId); + PageInfo pageInfo = new PageInfo<>(leaseProducts); + if(leaseProducts.isEmpty()){ + throw new ProductSoldOutException("不存在出售商品"); + } + //获取商品列表 + List collect = new ArrayList<>(); + Set shopIds = new HashSet<>(); + for (LeaseProduct product : leaseProducts) { + collect.add( ProductDto.builder() + .id(product.getId()) + .name(product.getName()) + .image(product.getImage()) + .type(product.getType()) + .state(product.getState()) + .priceRange(product.getMaxPrice().equals(product.getMinPrice()) ? + product.getMaxPrice().toString() : + (product.getMinPrice().toString() +"-"+product.getMaxPrice().toString())) + .description(product.getDescription()) + .algorithm(product.getAlgorithm()) + .shopId(product.getShopId()) + .coinFullName(product.getCoinFullName()) + .saleNumber(product.getSaleNumber()) + .totalMachineNumber(product.getTotalMachineNumber()) + .coin(product.getCoin()) + .build()); + shopIds.add(product.getShopId()); + } + List leaseShops = leaseShopMapper.selectList(new LambdaQueryWrapper().eq(LeaseShop::getState, 1).in(LeaseShop::getId, shopIds)); + Map> idMapShop = leaseShops.stream().collect(Collectors.groupingBy(LeaseShop::getId)); + + List result = new ArrayList<>(); + for (ProductDto productDto : collect) { + if (idMapShop.containsKey(productDto.getShopId())){ + result.add(productDto); + } + } + PageResult success = PageResult.success(result); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + + @Override + public Result getMachineInfoById(BaseVo baseVo) { + LeaseProduct leaseProduct = leaseProductMapper.selectById(baseVo.getId()); + if (leaseProduct == null) { + return Result.fail("商品不存在"); + } + + String priceRange = leaseProduct.getMinPrice().equals(leaseProduct.getMaxPrice()) ? leaseProduct.getMinPrice().toString(): leaseProduct.getMinPrice() +"-"+leaseProduct.getMaxPrice(); + ProductDto productDto = ProductDto.builder() + .id(leaseProduct.getId()) + .shopId(leaseProduct.getShopId()) + .name(leaseProduct.getName()) + .image(leaseProduct.getImage()) + .type(leaseProduct.getType()) + .state(leaseProduct.getState()) + .priceRange(priceRange) + .description(leaseProduct.getDescription()) + .coin(leaseProduct.getCoin()) + .algorithm(leaseProduct.getAlgorithm()) + .build(); + return Result.success(productDto); + } + + @Override + public Result getProductMachineInfo(Long productId) { + LeaseProduct product = getById(productId); + ProductMachineInfoDto productMachineInfoDto = new ProductMachineInfoDto(); + //0.查询商品对应的收款钱包配置 + List shopWalletInfo = leaseShopMapper.getShopWalletInfo(product.getShopId()); + productMachineInfoDto.setPayConfigList(shopWalletInfo); + + //1.查询商品对应处于上架状态 以及未售出的 机器集合 + List leaseProductMachines = leaseProductMachineMapper.selectList( + new LambdaQueryWrapper().eq(LeaseProductMachine::getProductId, productId) + .eq(LeaseProductMachine::getDel,false) + //.eq(LeaseProductMachine::getSaleState, 0) + .eq(LeaseProductMachine::getState, 0) + .orderByDesc(LeaseProductMachine::getSaleState) + + ); + + if (leaseProductMachines.isEmpty()){ + return Result.fail("该商品暂时没有可出售矿机"); + } + + //2.理论收益 = 矿机算力/全网算力 * 24h 秒数 /出块间隔秒数 * 单块奖励(redis中nexa:reward) + //查询矿机一天范围内的实际平均算力 单位为MH/S + List nexaMinersv2 = leaseProductMachineMapper.getRecentlyFiveMinutesData(leaseProductMachines, product.getCoin()); + //币价 单位usdt + BigDecimal price = redisService.getCacheBigDecimal(RedisKey.getPiceKey(product.getCoin())) == null ? BigDecimal.ZERO : redisService.getCacheBigDecimal(RedisKey.getPiceKey(product.getCoin())); + //报块奖励 + BigDecimal reward =redisService.getCacheBigDecimal(RedisKey.getRewardKey(product.getCoin())) == null ? BigDecimal.ZERO : redisService.getCacheBigDecimal(RedisKey.getRewardKey(product.getCoin())) ; + //全网算力单位是MH/s + BigDecimal mhs = redisService.getCacheBigDecimal(RedisKey.getMhsKey(product.getCoin())) == null ? BigDecimal.ZERO : redisService.getCacheBigDecimal(RedisKey.getMhsKey(product.getCoin())); + + // 创建一个 Map 用于存储 user 和 miner 组合对应的 ProductMachineDto 对象 + Map machineDtoMap = nexaMinersv2.stream() + .collect(Collectors.toMap( + dto -> dto.getUser() + "-" + dto.getMiner(), + dto -> dto + )); + List productMachines = leaseProductMachines.stream() + .map(leaseProductMachine -> { + String key = leaseProductMachine.getUser() + "-" + leaseProductMachine.getMiner(); + ProductMachineDto productMachineDto = machineDtoMap.get(key); + //理论收益 + BigDecimal singleTheoryMachineIncome = BigDecimal.ZERO; + BigDecimal computingPower = BigDecimal.ZERO; + if (productMachineDto != null) { + // 矿机算力单位转换 + 计算单矿机平均算力(ComputingPower coin_mhs30m 平均算力) + computingPower = PowerUnitUtils.getPower(leaseProductMachine.getUnit(), + productMachineDto.getComputingPower() + .multiply(BigDecimal.valueOf(1000 * 1000)) + .divide(BigDecimal.valueOf(24 * 60 * 60 ), 2, RoundingMode.HALF_UP)); + + if (mhs == null || reward == null || price == null){ + singleTheoryMachineIncome = leaseProductMachine.getTheoryIncome(); + }else{ + //全网算力单位转换 + BigDecimal power = PowerUnitUtils.getPower(leaseProductMachine.getUnit(), mhs.multiply(BigDecimal.valueOf(1000 * 1000))); + //(理论收益 = 矿机算力/全网算力 * 24h /出块间隔秒数 * 单块奖励(redis中nexa:reward)) + singleTheoryMachineIncome = computingPower.divide( power,6, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(24 * 60 * 60) + .divide(BlockInterval.getBlockCountByCoinName(product.getCoin()), 6, RoundingMode.HALF_UP)) + .multiply(reward); + } + } + return ProductMachineDto.builder() + .id(leaseProductMachine.getId()) + .user(leaseProductMachine.getUser()) + .miner(leaseProductMachine.getMiner()) + .price(leaseProductMachine.getPrice()) + .type(leaseProductMachine.getType()) + .algorithm(product.getAlgorithm()) + .theoryPower(leaseProductMachine.getTheoryPower()) + .computingPower(computingPower) + .maxLeaseDays(leaseProductMachine.getMaxLeaseDays()) + .unit(leaseProductMachine.getUnit()) + .saleState(leaseProductMachine.getSaleState()) + .state(leaseProductMachine.getState()) + .powerDissipation(leaseProductMachine.getPowerDissipation()) + .theoryIncome(singleTheoryMachineIncome) + .theoryUsdtIncome(singleTheoryMachineIncome.multiply( price)) + .coin(leaseProductMachine.getCoin()) + .build(); + }) + //.filter(Objects::nonNull) + //.sorted(Comparator.comparing(ProductMachineDto::getPrice)) + .collect(Collectors.toList()); + + //所有机器按价格分组 + Map> productMachineDtoMap = productMachines.stream() + .sorted(Comparator.comparing(ProductMachineDto::getSaleState)) + .collect(Collectors.groupingBy(ProductMachineDto::getPrice)); + + //计算实际,理论算力功耗等范围值 + Map bigDecimalProductMachineRangeDtoMap = calculateRanges(productMachineDtoMap); + + List collect = bigDecimalProductMachineRangeDtoMap.entrySet().stream() + .map(entry -> { + BigDecimal key = entry.getKey(); + ProductMachineRangeGroupDto rangeDto = entry.getValue(); + List machines = productMachineDtoMap.get(key); + return ProductMachineRangeInfoDto.builder() + .productMachineRangeGroupDto(rangeDto) + .productMachines(machines) + .build(); + }) + // 按照 rangeDto 的 price 字段降序排序 + .sorted(Comparator.comparing(info -> info.getProductMachineRangeGroupDto().getPrice())) + .collect(Collectors.toList()); + productMachineInfoDto.setMachineRangeInfoList( collect); + return Result.success(productMachineInfoDto); + } + + /** + * 计算每个价格分组中商品机器的功耗、理论算力、实际算力范围,并返回对应的范围信息对象 + * @param productMachineDtoMap 按价格分组的商品机器列表 + * @return 每个价格对应的商品机器范围信息 + */ + public static Map calculateRanges(Map> productMachineDtoMap) { + // 使用 AtomicInteger 来实现 onlyKey 递增 + AtomicInteger onlyKey = new AtomicInteger(0); + return productMachineDtoMap.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> { + List productMachines = entry.getValue(); + int number = productMachines.size(); + BigDecimal price = entry.getKey(); + + // 计算功耗范围 + BigDecimal minPower = productMachines.stream() + .map(ProductMachineDto::getPowerDissipation) + .min(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + BigDecimal maxPower = productMachines.stream() + .map(ProductMachineDto::getPowerDissipation) + .max(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + String powerRange = minPower.equals(maxPower) ? String.valueOf(minPower) : minPower + " - " + maxPower; + + // 计算理论算力范围 + BigDecimal minTheoryPower = productMachines.stream() + .map(ProductMachineDto::getTheoryPower) + .min(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + BigDecimal maxTheoryPower = productMachines.stream() + .map(ProductMachineDto::getTheoryPower) + .max(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + String theoryPowerRange = minTheoryPower.equals(maxTheoryPower) ? String.valueOf(minTheoryPower) : minTheoryPower + " - " + maxTheoryPower; + + + // 计算实际算力范围 + BigDecimal minComputingPower = productMachines.stream() + .map(ProductMachineDto::getComputingPower) + .min(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + BigDecimal maxComputingPower = productMachines.stream() + .map(ProductMachineDto::getComputingPower) + .max(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + String computingPowerRange = minComputingPower.equals(maxComputingPower) ? String.valueOf(minComputingPower) : minComputingPower + " - " + maxComputingPower; + String unit = productMachines.get(0).getUnit(); + int onlyKey1 = onlyKey.incrementAndGet(); + return ProductMachineRangeGroupDto.builder() + .onlyKey(onlyKey1) + .powerRange(powerRange) + .theoryPowerRange(theoryPowerRange) + .computingPowerRange(computingPowerRange) + .number(number) + .price(price) + .unit(unit) + .build(); + } + )); + } + + + @Override + public Result addProduct(ProductURDVo productURDVo) { + //校验是否存在收款钱包,不存在无法创建商品 + + List leaseShopConfig = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, productURDVo.getShopId()).eq(LeaseShopConfig::getDel, 0)); + if (leaseShopConfig.isEmpty()){ + return Result.fail("添加商品失败,请先绑定收款钱包"); + } + + String algorithm = Algorithm.getAlgorithm(productURDVo.getCoin()); + String coinFullName = Algorithm.getCoinFullName(productURDVo.getCoin()); + LeaseProduct product = LeaseProduct.builder() + .image(productURDVo.getImage()) + .name(productURDVo.getName()) + .algorithm(algorithm) + .description(productURDVo.getDescription()) + .state(productURDVo.getState()) + .type(productURDVo.getType()) + .coin(productURDVo.getCoin()) + .shopId(productURDVo.getShopId()) + .coinFullName(coinFullName) + .build(); + boolean save = save(product); + if (!save){ + return Result.fail("新增商品失败"); + } + return Result.success("新增商品成功"); + } + + @Override + @Transactional + public Result updateProduct(ProductURDVo productURDVo) {; + PriceDto priceDto = leaseProductMachineMapper.getPriceRange(productURDVo.getId()); + BigDecimal maxPrice = BigDecimal.ZERO; + BigDecimal minPrice = BigDecimal.ZERO;; + if (priceDto != null){ + maxPrice = priceDto.getPriceMax(); + minPrice = priceDto.getPriceMin(); + } + + //校验商品是否能够上下架 + if (productURDVo.getState() == 1 && leaseProductMachineMapper.checkHasSaleMachineByProductId(productURDVo.getId()) >= 1){ + return Result.fail("商品下架失败,商品存在租约中矿机"); + } + + //修改商品主表 + String algorithm = Algorithm.getAlgorithm(productURDVo.getCoin()); + String coinFullName = Algorithm.getCoinFullName(productURDVo.getCoin()); + LeaseProduct product = LeaseProduct.builder() + .id(productURDVo.getId()) + .image(productURDVo.getImage()) + .name(productURDVo.getName()) + .description(productURDVo.getDescription()) + .state(productURDVo.getState()) + .algorithm(algorithm) + .maxPrice(maxPrice) + .minPrice(minPrice) + .type(productURDVo.getType()) + .coinFullName(coinFullName) + .build(); + + boolean b1 = updateById(product); + if (b1){ + return Result.success("修改商品成功"); + } + return Result.fail("修改商品失败"); + + ////修改商品对应库存矿机表 + //List collect = new ArrayList<>(); + //if (!BigDecimal.ZERO.equals(productURDVo.getPower())){ + // //如果修改了算力power 就需要对应修改该商品下的算力 + // List leaseProductMachines = leaseProductMachineMapper.selectList( + // new LambdaQueryWrapper().eq(LeaseProductMachine::getProductId, productURDVo.getId()) + // .eq(LeaseProductMachine::getDel,false)); + // + // //计算对应user+miner 近3天算力总和 + // List nexaMinersv2 = leaseNexaMachinePowerMapper.getRecentlyFiveMinutesData(leaseProductMachines, productURDVo.getCoin()); + // // 创建一个 Map 用于存储 user 和 miner 组合对应的 ProductMachineDto 对象 + // Map machineDtoMap = nexaMinersv2.stream() + // .collect(Collectors.toMap( + // dto -> dto.getUser() + "-" + dto.getMiner(), + // dto -> dto + // )); + // + // BigDecimal price = redisService.getCacheObject(RedisKey.getPiceKey(product.getCoin())); + // BigDecimal reward = redisService.getCacheObject(RedisKey.getRewardKey(product.getCoin())); + // //全网算力单位是MH/s + // BigDecimal mhs = redisService.getCacheObject(RedisKey.getMhsKey(product.getCoin())); + // if (price == null){ + // return Result.fail("修改商品失败,未获取到"+product.getCoin()+"币的币价,请稍后重试"); + // } + // if (reward == null){ + // return Result.fail("修改商品失败,未获取到"+product.getCoin()+"币的报快奖励,请稍后重试"); + // } + // if (mhs == null){ + // return Result.fail("修改商品失败,未获取到"+product.getCoin()+"币的全网算力,请稍后重试"); + // } + // + // + // ////得到3天内的全网算力平均值 + // //BigDecimal netPower = leaseProductMapper.getCoinNetPower(productURDVo.getCoin()); + // // + // ////获取近三天全网实际报块数 + // //BigDecimal actualNetBlocks = leaseProductMapper.getNetBlocks(productURDVo.getCoin()); + // // + // ////获取全网理论报块 + // //BigDecimal theoryNetBlocks = DailyBlockOutputConstant.getBlockCountByCoinName(productURDVo.getCoin()); + // // + // ////计算单机理论收益(商品对应的同类型机器都是这个固定值) + // //BigDecimal singleTheoryMachineIncome = productURDVo.getPower() + // // .divide(netPower, 8, RoundingMode.HALF_UP) + // // .multiply(theoryNetBlocks); + // + // collect = leaseProductMachines.stream().peek(productMachine-> { + // //获取单机实际算力 + // String key = productMachine.getUser() + "-" + productMachine.getMiner(); + // ProductMachineDto productMachineDto = machineDtoMap.get(key); + // + // BigDecimal singleActualMachineIncome = BigDecimal.ZERO; + // BigDecimal singleTheoryMachineIncome = BigDecimal.ZERO; + // if (productMachineDto != null){ + // //// 将 LocalDateTime 转换为 Instant 并使用 Duration 计算毫秒差 + // //Instant startInstant = productMachineDto.getStartTime().atZone(ZoneId.systemDefault()).toInstant(); + // //Instant endInstant = productMachineDto.getEndTime().atZone(ZoneId.systemDefault()).toInstant(); + // //Duration duration = Duration.between(startInstant, endInstant); + // //long millis = duration.toMillis(); + // //// 计算单矿机3天内平均算力 + // //BigDecimal actualPower = productMachineDto.getComputingPower() + // // .multiply(BigDecimal.valueOf(Math.pow(2, 32))) + // // //这里计算的是3天内 + // // .divide(BigDecimal.valueOf(millis), 2, RoundingMode.HALF_UP); + // ////计算预估实际收益 + // //singleActualMachineIncome = actualPower + // // .divide(netPower, 8, RoundingMode.HALF_UP) + // // .multiply(actualNetBlocks); + // + // //理论收益 = 矿机算力/全网算力 * 24h /出块间隔秒数 * 单块奖励(redis中nexa:reward) + // singleTheoryMachineIncome = mhs.divide( productMachineDto.getComputingPower(),6, RoundingMode.HALF_UP) + // .multiply(BigDecimal.valueOf(24 * 60 * 60).divide(BlockInterval.getBlockCountByCoinName(product.getCoin()), 6, RoundingMode.HALF_UP)) + // .multiply(reward); + // + // } + // //productMachine.setActualIncome(singleActualMachineIncome); + // productMachine.setTheoryIncome(singleTheoryMachineIncome); + // }).collect(Collectors.toList()); + // + //} + //if (collect.isEmpty() && b1){ + // return Result.success("修改成功"); + //} + //boolean b = leaseProductMachineService.updateBatchById(collect); + //if (b && b1){ + // return Result.success("修改成功"); + //} + //return Result.fail("修改失败"); + } + + @Override + @Transactional + public Result deleteProduct(Long id) { + int i = leaseProductMachineMapper.checkHasSaleMachineByProductId(id); + if(i >= 1){ + return Result.fail("删除失败,该商品存在租约中的机器"); + } + + boolean updateFather = updateById(LeaseProduct.builder().id(id).del(true).build()); + //int delete = leaseProductMachineMapper.delete(new LambdaQueryWrapper().eq(LeaseProductMachine::getProductId, id)); + int update = leaseProductMachineMapper.update(LeaseProductMachine.builder().del(true).build(), + new LambdaQueryWrapper().eq(LeaseProductMachine::getProductId, id)); + + if (updateFather || update > 0){ + return Result.success("删除成功"); + } + return Result.fail("删除失败"); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShopConfigServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShopConfigServiceImpl.java new file mode 100644 index 0000000..6443898 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShopConfigServiceImpl.java @@ -0,0 +1,20 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeaseShopConfig; +import com.m2pool.lease.mapper.LeaseShopConfigMapper; +import com.m2pool.lease.service.LeaseShopConfigService; +import org.springframework.stereotype.Service; + +/** + *

+ * 店铺商品配置表 服务实现类 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Service +public class LeaseShopConfigServiceImpl extends ServiceImpl implements LeaseShopConfigService { + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShopServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShopServiceImpl.java new file mode 100644 index 0000000..d9f2199 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShopServiceImpl.java @@ -0,0 +1,486 @@ +package com.m2pool.lease.service.impl; + +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.m2pool.common.security.utils.SecurityUtils; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.service.LeaseShopConfigService; +import com.m2pool.lease.service.LeaseShopService; +import com.m2pool.lease.utils.QrCodeUtils; +import com.m2pool.lease.utils.WalletRuleCheckUtils; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.ShopConfigVo; +import com.m2pool.lease.vo.ShopVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 店铺表 服务实现类 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Service +public class LeaseShopServiceImpl extends ServiceImpl implements LeaseShopService { + + @Resource + private LeaseShopMapper leaseShopMapper; + + @Resource + private LeaseShopConfigMapper leaseShopConfigMapper; + + @Resource + private LeaseOrderItemMapper leaseOrderItemMapper; + + @Resource + private LeaseShopConfigService leaseShopConfigService; + + @Resource + private LeaseProductMapper leaseProductMapper; + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Override + public Result addShop(ShopVo shopVo) { + LeaseShop leaseShop1 = leaseShopMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShop::getUserEmail, SecurityUtils.getUsername())); + + LeaseShop leaseShop = LeaseShop.builder() + .userEmail(SecurityUtils.getUsername()) + .name(shopVo.getName()) + .image(shopVo.getImage()) + .description(shopVo.getDescription()) + .state(shopVo.getState()) + .build(); + + if(leaseShop1 != null){ + if (!leaseShop1.getDel()){ + return Result.fail("当前已存在店铺,请勿重复添加"); + } + leaseShop.setId(leaseShop1.getId()); + leaseShop.setDel(false); + boolean b = updateById(leaseShop); + return b ? Result.success("新增店铺成功") : Result.fail("新增店铺失败"); + } + boolean save = save(leaseShop); + return save ? Result.success("新增店铺成功") : Result.fail("新增店铺失败"); + + } + + @Override + public Result updateShop(ShopVo shopVo) { + + if (shopVo.getId() == null || shopVo.getId() == 0){ + return Result.fail("id不能为空或0"); + } + + LeaseShop leaseShop = LeaseShop.builder() + .id(shopVo.getId()) + .userEmail(SecurityUtils.getUsername()) + .name(shopVo.getName()) + .image(shopVo.getImage()) + .description(shopVo.getDescription()) + .state(shopVo.getState()) + .build(); + LeaseShop byId = getById(shopVo.getId()); + if (byId.getDel()){ + return Result.fail("修改失败,店铺已被删除"); + } + boolean save = updateById(leaseShop); + if (save) { + return Result.success("修改店铺成功"); + } + return Result.fail("修改店铺失败"); + } + + @Override + public Result closeShop(BaseVo baseVo) { + LeaseShop leaseShop = getById(baseVo.getId()); + if (leaseShop == null) { + return Result.fail("店铺不存在"); + } + //校验是否存在已售出的矿机 + if (leaseProductMachineMapper.checkHasSaleMachineByShopId(baseVo.getId()) >= 1){ + return Result.fail("关闭店铺失败,店铺存在租约中矿机"); + } + if (leaseShop.getState() == 1){ + leaseShop.setState(2); + boolean b = updateById(leaseShop); + return b ? Result.success("关闭店铺成功") : Result.fail("关闭店铺失败"); + } + if (leaseShop.getState() == 2){ + leaseShop.setState(1); + boolean b = updateById(leaseShop); + return b ? Result.success("开启店铺成功") : Result.fail("开启店铺失败"); + } + return Result.fail("店铺正在审核中不能开启和关闭店铺"); + } + + @Override + public Result getShopByUserEmail() { + LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShop::getUserEmail, SecurityUtils.getUsername()) + .eq(LeaseShop::getDel, false)); + if (leaseShop != null){ + return Result.success(ShopDto.builder() + .id(leaseShop.getId()) + .name(leaseShop.getName()) + .image(leaseShop.getImage()) + .description(leaseShop.getDescription()) + .state(leaseShop.getState()) + .del(leaseShop.getDel()) + .build()); + } + return Result.fail("未找到商铺,请创建商铺"); + } + + @Override + public Result getShopById(BaseVo baseVo) { + LeaseShop leaseShop = leaseShopMapper.selectById(baseVo.getId()); + if (leaseShop != null && !leaseShop.getDel()){ + return Result.success(ShopDto.builder() + .id(leaseShop.getId()) + .name(leaseShop.getName()) + .image(leaseShop.getImage()) + .description(leaseShop.getDescription()) + .state(leaseShop.getState()) + .del(leaseShop.getDel()) + .build()); + } + return Result.fail("未找到商铺"); + } + + @Override + @Transactional + public Result deleteShop(BaseVo baseVo) { + LeaseShop byId = getById(baseVo.getId()); + if (byId.getDel()){ + return Result.fail("删除店铺失败,店铺已删除,请刷新页面"); + } + + //校验是否存在已售出的矿机 + if (leaseProductMachineMapper.checkHasSaleMachineByShopId(baseVo.getId()) >= 1){ + return Result.fail("删除店铺失败,店铺存在租约中矿机"); + } + leaseProductMapper.update(LeaseProduct.builder().del(true).build(), new LambdaUpdateWrapper() + .eq(LeaseProduct::getShopId, baseVo.getId())); + leaseProductMachineMapper.update(LeaseProductMachine.builder().del(true).build(), new LambdaUpdateWrapper() + .eq(LeaseProductMachine::getShopId, baseVo.getId())); + + boolean b = updateById(LeaseShop.builder().id(baseVo.getId()).del(true).build()); + if (b){ + return Result.success("删除成功"); + } + return Result.fail("删除失败"); + } + + + + + @Override + public Result> getProductListById(BaseVo baseVo) { + List leaseProducts = leaseProductMapper.selectList(new LambdaQueryWrapper().eq(LeaseProduct::getShopId, baseVo.getId()).eq(LeaseProduct::getDel, false)); + List collect = leaseProducts.stream().map(leaseProduct -> + ShopNameDto.builder() + .id(leaseProduct.getId()) + .name(leaseProduct.getName()).build() + ).collect(Collectors.toList()); + return Result.success(collect); + } + + @Override + public Result> getShopConfig(BaseVo baseVo) { + List leaseShopConfigs = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, baseVo.getId()) + .eq(LeaseShopConfig::getDel, false)); + if (leaseShopConfigs.isEmpty()){ + return Result.fail("店铺暂未设置收款钱包"); + } + Map> collect = leaseShopConfigs.stream().collect(Collectors.groupingBy(LeaseShopConfig::getChain)); + List shopConfigDtos = new ArrayList<>(); + collect.forEach((chain, list) -> { + LeaseShopConfig leaseShopConfig = list.get(0); + + List coinDtoList = list.stream().map(shopConfig -> { + ShopConfigDto.CoinDto coinDto = new ShopConfigDto.CoinDto(); + coinDto.setPayCoin(shopConfig.getPayCoin()); + coinDto.setImage(shopConfig.getPayCoinImage()); + return coinDto; + }).collect(Collectors.toList()); + + ShopConfigDto build = ShopConfigDto.builder() + .shopId(leaseShopConfig.getShopId()) + .chain(leaseShopConfig.getChain()) + .payType(leaseShopConfig.getPayType()) + .payAddress(leaseShopConfig.getPayAddress()) + .children(coinDtoList) + .build(); + build.setId(leaseShopConfig.getId()); + shopConfigDtos.add( build); + + }); + + return Result.success(shopConfigDtos); + } + + @Override + public Result addShopConfig(ShopConfigVo shopConfigVo) { + + //钱包地址校验 + if (!WalletRuleCheckUtils.checkAddress(shopConfigVo.getChain(),shopConfigVo.getPayAddress())){ + return Result.fail("提现地址格式不符合"+shopConfigVo.getChain()+"节点"); + } + LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShop::getUserEmail, SecurityUtils.getUsername())); + + List payCoinsList = new ArrayList<>(Arrays.asList(shopConfigVo.getPayCoin().split(","))); + + LeaseShopConfig configList = leaseShopConfigMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, leaseShop.getId()) + .eq(LeaseShopConfig::getPayCoin, shopConfigVo.getPayCoin()) + .eq(LeaseShopConfig::getChain, shopConfigVo.getChain()) + .eq(LeaseShopConfig::getDel, false) + ); + if (configList != null){ + return Result.fail("绑定钱包失败!已存在" + shopConfigVo.getChain()+"链"+ shopConfigVo.getPayCoin()+ "币种钱包"); + } + + //获取币种图标 + List shopConfigList = leaseShopConfigMapper.getCoinIconByChainAndCoin(shopConfigVo.getChain(), payCoinsList); + + String payAddress = shopConfigVo.getPayAddress(); + String qrCode = QrCodeUtils.creatRrCode(payAddress, 200, 200); + for (LeaseShopConfig leaseShopConfig : shopConfigList) { + leaseShopConfig.setShopId(leaseShop.getId()); + leaseShopConfig.setPayType(shopConfigVo.getPayType()); + leaseShopConfig.setChain(shopConfigVo.getChain()); + leaseShopConfig.setPayAddress(payAddress); + leaseShopConfig.setQrcode(qrCode); + } + boolean b = leaseShopConfigService.saveBatch(shopConfigList); + if (b){ + return Result.success("添加成功"); + } + return Result.fail("添加失败"); + } + + @Override + public Result updateShopConfig(ShopConfigVo shopConfigVo) { + if ( !WalletRuleCheckUtils.checkAddress(shopConfigVo.getChain(),shopConfigVo.getPayAddress())){ + return Result.fail("提现地址格式不符合"+shopConfigVo.getChain()+"节点"); + } + LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper().eq(LeaseShop::getUserEmail, SecurityUtils.getUsername())); + List payCoinsList = new ArrayList<>(Arrays.asList(shopConfigVo.getPayCoin().split(","))); + String payAddress = shopConfigVo.getPayAddress(); + String qrCode = QrCodeUtils.creatRrCode(payAddress, 200, 200); + List configList = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, leaseShop.getId()) + .eq(LeaseShopConfig::getChain, shopConfigVo.getChain()) + .eq(LeaseShopConfig::getDel, false) + ); + //比较已绑定币种 和 本次修改币种的差异 + List insertOrUpdateList = new ArrayList<>(); + List deleteList = new ArrayList<>(); + + for (LeaseShopConfig leaseShopConfig : configList) { + if(!payCoinsList.contains(leaseShopConfig.getPayCoin())){ + leaseShopConfig.setDel( true); + deleteList.add(leaseShopConfig); + }else if (shopConfigVo.getPayAddress().equalsIgnoreCase(leaseShopConfig.getPayAddress())){ + insertOrUpdateList.add(LeaseShopConfig.builder() + .id(leaseShopConfig.getId()) + .shopId(leaseShop.getId()) + .payType(shopConfigVo.getPayType()) + .chain(shopConfigVo.getChain()) + .qrcode(qrCode) + .payCoin(leaseShopConfig.getPayCoin()) + .payAddress(payAddress) + .build()); + }else{ + //如果修改了地址 那么就是新增一个 旧的删除 + insertOrUpdateList.add(LeaseShopConfig.builder() + .shopId(leaseShop.getId()) + .payType(shopConfigVo.getPayType()) + .chain(shopConfigVo.getChain()) + .qrcode(qrCode) + .payCoin(leaseShopConfig.getPayCoin()) + .payAddress(payAddress) + .build()); + leaseShopConfig.setDel( true); + deleteList.add(leaseShopConfig); + } + } + List alreadyExistCoinList = configList.stream().map(LeaseShopConfig::getPayCoin).collect(Collectors.toList()); + for (String coin : payCoinsList) { + //不存在新增 + if (!alreadyExistCoinList.contains(coin)){ + insertOrUpdateList.add(LeaseShopConfig.builder() + .shopId(leaseShop.getId()) + .payCoin(coin) + .payType(shopConfigVo.getPayType()) + .chain(shopConfigVo.getChain()) + .qrcode(qrCode) + .payAddress(payAddress) + .build()); + } + } + + if (!deleteList.isEmpty()){ + boolean delete = leaseShopConfigService.updateBatchById(deleteList); + } + List coinList = insertOrUpdateList.stream().map(LeaseShopConfig::getPayCoin).collect(Collectors.toList()); + //获取币种对应的图片 + List coinIconByChainAndCoin = leaseShopConfigMapper.getCoinIconByChainAndCoin(shopConfigVo.getChain(), coinList); + + for (LeaseShopConfig leaseShopConfig : insertOrUpdateList) { + for (LeaseShopConfig configImage : coinIconByChainAndCoin) { + if (leaseShopConfig.getPayCoin().equals(configImage.getPayCoin())){ + leaseShopConfig.setPayCoinImage(configImage.getPayCoinImage()); + } + } + + } + + boolean save = leaseShopConfigService.saveOrUpdateBatch(insertOrUpdateList); + if (save){ + return Result.success("修改成功"); + } + return Result.fail("修改失败"); + } + + @Override + public Result deleteShopConfig(BaseVo baseVo) { + LeaseShopConfig config = leaseShopConfigMapper.selectById(baseVo.getId()); + Long configNums = leaseShopConfigMapper.selectCount(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, config.getShopId()).eq(LeaseShopConfig::getDel, false)); + Long productNums = leaseProductMapper.selectCount(new LambdaQueryWrapper() + .eq(LeaseProduct::getShopId, config.getShopId()) + .eq(LeaseProduct::getDel, false)); + if (configNums <= 1 && productNums != 0){ + return Result.fail("删除失败,店铺若存在商品,至少需要一个收款钱包"); + } + //校验是否能够删除 + Long l = leaseOrderItemMapper.selectCount(new LambdaQueryWrapper() + .eq(LeaseOrderItem::getPayCoin, config.getPayCoin()) + .eq(LeaseOrderItem::getChain, config.getChain()) + .ne(LeaseOrderItem::getStatus, 0) + ); + if (l > 0){ + return Result.fail("删除钱包失败,该钱包存在交易中的订单"); + } + + List leaseShopConfigs = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, config.getShopId()) + .eq(LeaseShopConfig::getChain, config.getChain()) + .eq(LeaseShopConfig::getDel, false)); + List collect = leaseShopConfigs.stream().peek(leaseShopConfig -> leaseShopConfig.setDel(true)).collect(Collectors.toList()); + boolean b = leaseShopConfigService.updateBatchById(collect); + if (b){ + return Result.success("删除成功"); + } + return Result.fail("删除失败"); + } + + @Override + public Result> getChainAndList() { + //LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper().eq(LeaseShop::getUserEmail, SecurityUtils.getUsername()) + // .eq(LeaseShop::getDel, false)); + //获取本系统支持的所有链和币种 + List chainAndList = leaseShopConfigMapper.getChainAndList(null); + //获取卖家已绑定的币种 + //List leaseShopConfigs = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + // .eq(LeaseShopConfig::getShopId, leaseShop.getId()) + //); + //for (CoinFullDto coinFullDto : chainAndList) { + // for (LeaseShopConfig leaseShopConfig : leaseShopConfigs) { + // if (coinFullDto.getChainValue().equals(leaseShopConfig.getChain()) && coinFullDto.getCoinValue().equals(leaseShopConfig.getPayCoin())){ + // coinFullDto.setHasBind(1); + // } + // } + //} + return Result.success(buildChainList(chainAndList)); + } + + + @Override + public Result> getChainAndListForSeller(BaseVo baseVo) { + //LeaseShop leaseShop = leaseShopMapper.selectById(baseVo.getId()); + if (baseVo.getId() == null){ + return Result.fail("未检测到该店铺"); + } + List chainAndListForSeller = leaseShopConfigMapper.getChainAndListForSeller(baseVo.getId()); + return Result.success(buildChainList(chainAndListForSeller)); + } + + + @Override + public Result getChainAndCoin(BaseVo baseVo) { + LeaseShopConfig config = leaseShopConfigMapper.selectOne(new LambdaQueryWrapper().eq(LeaseShopConfig::getId, baseVo.getId())); + if (config == null){ + return Result.fail("未检测到该币种"); + } + //商家链已绑定的币种 + List leaseShopConfigs = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getChain, config.getChain()) + .eq(LeaseShopConfig::getShopId, config.getShopId()) + ); + //获取本系统该链支持的所有币种 + List chainAndList = leaseShopConfigMapper.getChainAndList(config.getChain()); + for (CoinFullDto coinFullDto : chainAndList) { + for (LeaseShopConfig leaseShopConfig : leaseShopConfigs) { + if (coinFullDto.getChainValue().equals(leaseShopConfig.getChain()) && coinFullDto.getCoinValue().equals(leaseShopConfig.getPayCoin())){ + coinFullDto.setHasBind(1); + } + } + } + ChainListDto chainListDto = buildChainList(chainAndList).get(0); + chainListDto.setAddress(config.getPayAddress()); + return Result.success(chainListDto); + } + + private List buildChainList(List chainAndList){ + Map> chainGroup = chainAndList.stream() + .collect(Collectors.groupingBy(CoinFullDto::getChainValue)); + + List result = new ArrayList<>(); + for (Map.Entry> entry : chainGroup.entrySet()) { + String chainValue = entry.getKey(); + List group = entry.getValue(); + // 取第一个元素获取链标签 + String chainLabel = group.get(0).getChainLabel(); + + List coinList = group.stream() + .map(coinFullDto -> { + ChainListDto.CoinListDto coinDto = new ChainListDto.CoinListDto(); + coinDto.setValue(coinFullDto.getCoinValue()); + coinDto.setLabel(coinFullDto.getCoinLabel()); + coinDto.setHasBind(coinFullDto.getHasBind()); + return coinDto; + }) + .collect(Collectors.toList()); + + ChainListDto chainListDto = ChainListDto.builder() + .value(chainValue) + .label(chainLabel) + .children(coinList) + .build(); + result.add(chainListDto); + } + return result; + } + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShoppingCartServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShoppingCartServiceImpl.java new file mode 100644 index 0000000..516063e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShoppingCartServiceImpl.java @@ -0,0 +1,347 @@ +package com.m2pool.lease.service.impl; + +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; +import com.m2pool.common.redis.service.RedisService; +import com.m2pool.common.security.utils.SecurityUtils; +import com.m2pool.lease.constant.PowerUnit; +import com.m2pool.lease.constant.RedisKey; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.service.LeaseShoppingCartInfoService; +import com.m2pool.lease.service.LeaseShoppingCartService; +import com.m2pool.lease.utils.PowerUnitUtils; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.PageVo; +import com.m2pool.lease.vo.ProductAndMachineVo; +import com.m2pool.lease.vo.ShoppingCartInfoURDVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.m2pool.lease.constant.PowerUnit.MH_UNIT; + +/** + *

+ * 购物车表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseShoppingCartServiceImpl extends ServiceImpl implements LeaseShoppingCartService { + + @Resource + private LeaseShoppingCartMapper leaseShoppingCartMapper; + + @Resource + private LeaseShoppingCartInfoMapper leaseShoppingCartInfoMapper; + + @Resource + private LeaseShoppingCartInfoService leaseShoppingCartInfoService; + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Resource + private LeaseUserOwnedProductMapper leaseUserOwnedProductMapper; + + @Resource + private LeaseShopMapper leaseShopMapper; + + @Resource + private RedisService redisService; + @Override + @Transactional + public Result addGoods(List shoppingCartInfoURDVoList) { + //String userId = SecurityUtils.getUsername(); + //if (shoppingCartInfoURDVoList.isEmpty()){ + // return Result.fail("请选择商品"); + //} + //LeaseShoppingCart leaseShoppingCart = leaseShoppingCartMapper + // .selectOne(new LambdaQueryWrapper().eq(LeaseShoppingCart::getUserId, userId)); + //if (leaseShoppingCart == null){ + // leaseShoppingCart = LeaseShoppingCart.builder().userId(userId).build(); + // int insert = leaseShoppingCartMapper.insert(leaseShoppingCart); + // if (insert <= 0){ + // return Result.fail("添加购物车失败"); + // } + //} + //Long cartId = leaseShoppingCart.getId(); + //List productMachineIds = shoppingCartInfoURDVoList.stream().map(ShoppingCartInfoURDVo::getProductMachineId).collect(Collectors.toList()); + //List leaseShoppingCartInfos = leaseShoppingCartInfoMapper.selectList(new LambdaQueryWrapper() + // .eq(LeaseShoppingCartInfo::getCartId, cartId).in(LeaseShoppingCartInfo::getProductMachineId, productMachineIds)); + // + //if (!leaseShoppingCartInfos.isEmpty()){ + // return Result.fail("购物车中已存在该机器,不能重复添加"); + //} + //List collect = shoppingCartInfoURDVoList.stream().map(shoppingCartInfoURDVo -> + // LeaseShoppingCartInfo.builder() + // .leaseTime(shoppingCartInfoURDVo.getLeaseTime()) + // .cartId(cartId) + // .productId(shoppingCartInfoURDVo.getProductId()) + // .productMachineId(shoppingCartInfoURDVo.getProductMachineId()) + // .build() + //).collect(Collectors.toList()); + //boolean b = leaseShoppingCartInfoService.saveBatch(collect); + //if (b){ + // return Result.success("添加购物车成功"); + //} + //return Result.fail("添加购物车失败"); + String userId = SecurityUtils.getUsername(); + if (shoppingCartInfoURDVoList.isEmpty()) { + return Result.fail("请选择商品"); + } + LeaseShoppingCart leaseShoppingCart = leaseShoppingCartMapper + .selectOne(new LambdaQueryWrapper().eq(LeaseShoppingCart::getUserId, userId)); + if (leaseShoppingCart == null) { + leaseShoppingCart = LeaseShoppingCart.builder().userId(userId).build(); + int insert = leaseShoppingCartMapper.insert(leaseShoppingCart); + if (insert <= 0) { + return Result.fail("添加购物车失败"); + } + } + Long cartId = leaseShoppingCart.getId(); + List productMachineIds = shoppingCartInfoURDVoList.stream().map(ShoppingCartInfoURDVo::getProductMachineId).collect(Collectors.toList()); + List leaseShoppingCartInfos = leaseShoppingCartInfoMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShoppingCartInfo::getCartId, cartId).in(LeaseShoppingCartInfo::getProductMachineId, productMachineIds)); + + // 存储需要新增的记录 + List newRecords = shoppingCartInfoURDVoList.stream() + .filter(vo -> leaseShoppingCartInfos.stream().noneMatch(info -> info.getProductMachineId().equals(vo.getProductMachineId()))) + .map(shoppingCartInfoURDVo -> + LeaseShoppingCartInfo.builder() + .leaseTime(shoppingCartInfoURDVo.getLeaseTime()) + .cartId(cartId) + .productId(shoppingCartInfoURDVo.getProductId()) + .productMachineId(shoppingCartInfoURDVo.getProductMachineId()) + .build() + ).collect(Collectors.toList()); + + // 存储需要更新的记录 + Map voMap = shoppingCartInfoURDVoList.stream() + .collect(Collectors.toMap(ShoppingCartInfoURDVo::getProductMachineId, vo -> vo)); + List updateList = leaseShoppingCartInfos.stream() + .peek(info -> { + ShoppingCartInfoURDVo vo = voMap.get(info.getProductMachineId()); + if (vo != null) { + info.setLeaseTime(info.getLeaseTime() + vo.getLeaseTime()); + info.setId(info.getId()); + } + }) + .collect(Collectors.toList()); + + // 执行更新操作 + if (!updateList.isEmpty()) { + boolean updateResult = leaseShoppingCartInfoService.updateBatchById(updateList); + if (!updateResult) { + return Result.fail("更新购物车租赁时间失败"); + } + } + + // 执行新增操作 + if (!newRecords.isEmpty()) { + boolean saveResult = leaseShoppingCartInfoService.saveBatch(newRecords); + if (!saveResult) { + return Result.fail("添加新购物车记录失败"); + } + } + + return Result.success("添加购物车成功"); + } + + + @Override + public PageResult getGoodsList(PageVo pageVo) { + //1.获取用户购物车 + String userId = SecurityUtils.getUsername(); + LeaseShoppingCart leaseShoppingCart = leaseShoppingCartMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShoppingCart::getUserId, userId)); + if (leaseShoppingCart == null){ + return PageResult.fail(null,"购物车中不存在商品"); + } + //获取商品相关信息 + List cartInfoList = leaseShoppingCartInfoMapper.getCartInfoList(leaseShoppingCart.getId()); + PageInfo pageInfo = new PageInfo<>(cartInfoList); + if (cartInfoList.isEmpty()){ + return PageResult.fail(null,"购物车中不存在商品"); + } + PageHelper.startPage(pageVo.getPageNum(), pageVo.getPageSize()); + //查询购物车中店铺信息 + Map> shopGroupMap = cartInfoList.stream().collect(Collectors.groupingBy(ShoppingCartInfoDto::getShopId)); + List leaseShops = leaseShopMapper.selectList(new LambdaQueryWrapper().in(LeaseShop::getId, shopGroupMap.keySet())); + + //获取商品下机器id集合 + List machineIds = cartInfoList.stream().map(ShoppingCartInfoDto::getProductMachineId).collect(Collectors.toList()); + //获取机器id 为key ,机器详情集合为value 的map + List leaseShoppingCartInfos = leaseShoppingCartInfoMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShoppingCartInfo::getCartId, leaseShoppingCart.getId())); + Map machineMap = leaseShoppingCartInfos.stream().collect(Collectors.toMap(LeaseShoppingCartInfo::getProductMachineId, Function.identity())); + + //查询商品中机器详情 + 按照币种分组 + List leaseProductMachines = leaseProductMachineMapper.getMachinesByIds(machineIds); + Map> userAndMinerList = leaseProductMachines.stream().map( + ProductMachineDto -> + UserMinerDto.builder() + .user(ProductMachineDto.getUser()) + .miner(ProductMachineDto.getMiner()) + .coin(ProductMachineDto.getCoin()) + .build() + ).collect(Collectors.groupingBy(UserMinerDto::getCoin)); + + //获取实时币价 + List coins = leaseProductMachines.stream().map(ProductMachineDto::getCoin).distinct().collect(Collectors.toList()); + Map coinPriceMap = new HashMap<>(); + for (String coin : coins) { + BigDecimal price = redisService.getCacheBigDecimal(RedisKey.getPiceKey(coin)); + if (price == null){ + price = BigDecimal.ZERO; + } + coinPriceMap.put(coin, price); + } + + //按币种查询每个矿机的最近一次30分钟的实时算力(后续修改为24小时平均算力) + List userMinerPowerList = new ArrayList<>(); + userAndMinerList.forEach((coin, userMinerDtos) -> { + userMinerPowerList.addAll(leaseUserOwnedProductMapper.getUserMinerPower(userMinerDtos, coin)); + }); + Map realPowerList = userMinerPowerList.stream() + .collect(Collectors.toMap( + dto -> dto.getUser() + "-" + dto.getMiner() + "-" + dto.getCoin(), + dto -> dto + )); + //为每个矿机设置实时的算力 + 按店铺分组 + Map> shopIdAndMachineInfoMap = leaseProductMachines.stream().peek(productMachineDto -> { + UserMinerPowerDto userMinerPowerDto = realPowerList.get(productMachineDto.getUser() + "-" + productMachineDto.getMiner() + "-" + productMachineDto.getCoin()); + if (userMinerPowerDto != null) { + //单位为MH/s 需要转换成 矿机设定的单位 + BigDecimal value = userMinerPowerDto.getPower().multiply(PowerUnit.getPower(MH_UNIT)); + productMachineDto.setComputingPower(PowerUnitUtils.getPower(productMachineDto.getUnit(),value)); + productMachineDto.setTheoryUsdtIncome(productMachineDto.getTheoryIncome().multiply(coinPriceMap.get(productMachineDto.getCoin()))); + productMachineDto.setStartTime(userMinerPowerDto.getStartTime()); + productMachineDto.setEndTime(LocalDateTime.now()); + } + }).collect(Collectors.groupingBy(ProductMachineDto::getShopId)); + + + + //获取商铺钱包配置信息 + List shopIds = leaseShops.stream().map(LeaseShop::getId).collect(Collectors.toList()); + List shopWalletInfo = leaseShopMapper.getShopWalletInfoList(shopIds); + Map> payConfigMap = shopWalletInfo.stream().collect(Collectors.groupingBy(PayConfigDto::getShopId)); + + //组合返回对象 + List shopCartList = leaseShops.stream().map(leaseShop -> { + + List productMachineList = shopIdAndMachineInfoMap.get(leaseShop.getId()); + return ShopCartDto.builder() + .id(leaseShop.getId()) + .name(leaseShop.getName()) + .totalMachine(productMachineList != null ? productMachineList.size() : 0) + .payConfigList(payConfigMap.get(leaseShop.getId())) + .productMachineDtoList(productMachineList) + .build(); + }).collect(Collectors.toList()); + + //结算总价计算 + for (ShopCartDto shopCartDto : shopCartList) { + BigDecimal totalPrice = BigDecimal.ZERO; + //遍历每个商铺下的矿机 + List productMachineDtoList = shopCartDto.getProductMachineDtoList(); + if ( productMachineDtoList!= null) { + for (ProductMachineDto productMachineDto : productMachineDtoList) { + LeaseShoppingCartInfo cartInfo = machineMap.get(productMachineDto.getId()); + if (cartInfo != null ) { + Integer leaseTime = cartInfo.getLeaseTime(); + productMachineDto.setLeaseTime(leaseTime); + // 处理空指针情况 + BigDecimal price = productMachineDto.getPrice(); + if (price != null && leaseTime != null) { + BigDecimal itemPrice = price.multiply(new BigDecimal(leaseTime)); + totalPrice = totalPrice.add(itemPrice); + } + } + } + } + shopCartDto.setTotalPrice(totalPrice); + } + PageResult success = PageResult.success(shopCartList); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + + @Override + @Transactional + public Result deleteBatchGoods(List baseVoList) { + LeaseShoppingCart leaseShoppingCart = leaseShoppingCartMapper.selectOne(new LambdaQueryWrapper().eq(LeaseShoppingCart::getUserId, SecurityUtils.getUsername())); + + if (leaseShoppingCart == null){ + return Result.fail("删除购物车商品失败,购物车未获取到"); + } + + // 执行删除操作 + int i = leaseShoppingCartInfoMapper.deleteBatchData(leaseShoppingCart.getId(), baseVoList); + + if (i > 0){ + return Result.success("删除购物车商品成功"); + } + return Result.fail("删除购物车商品失败"); + } + + @Override + @Transactional + public Result deleteGoods(BaseVo baseVo) { + int delete = leaseShoppingCartInfoMapper.deleteById(baseVo.getId()); + if (delete > 0){ + return Result.success("删除购物车商品成功"); + } + return Result.fail("删除购物车商品失败"); + } + + + @Override + public Result deleteBatchGoodsForIsDelete() { + + LeaseShoppingCart leaseShoppingCart = leaseShoppingCartMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseShoppingCart::getUserId, SecurityUtils.getUsername())); + + List leaseShoppingCartInfos = leaseShoppingCartInfoMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShoppingCartInfo::getCartId, leaseShoppingCart.getId())); + + List machineIds = leaseShoppingCartInfos.stream().map(LeaseShoppingCartInfo::getProductMachineId).collect(Collectors.toList()); + List leaseProductMachines = leaseProductMachineMapper.selectList(new LambdaQueryWrapper() + .in(LeaseProductMachine::getId, machineIds)); + List delMachineIds = leaseProductMachines.stream().filter(productMachine -> productMachine.getDel() || productMachine.getState() == 1) + .map(LeaseProductMachine::getId).collect(Collectors.toList()); + + if (delMachineIds.isEmpty()){ + return Result.success("删除购物车已下架商品成功"); + } + + int delete = leaseShoppingCartInfoMapper.delete(new LambdaUpdateWrapper() + .in(LeaseShoppingCartInfo::getProductMachineId, delMachineIds)); + + if (delete > 0){ + return Result.success("删除购物车已下架商品成功"); + } + return Result.fail("删除失败,不存在已下架商品"); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShoppingCatInfoServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShoppingCatInfoServiceImpl.java new file mode 100644 index 0000000..ca76c69 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseShoppingCatInfoServiceImpl.java @@ -0,0 +1,21 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.m2pool.lease.entity.LeaseShoppingCartInfo; +import com.m2pool.lease.mapper.LeaseShoppingCartInfoMapper; +import com.m2pool.lease.service.LeaseShoppingCartInfoService; +import org.springframework.stereotype.Service; + +/** + *

+ * 购物车详情表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-24 + */ +@Service +public class LeaseShoppingCatInfoServiceImpl extends ServiceImpl implements LeaseShoppingCartInfoService { + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseUserOwnedProductServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseUserOwnedProductServiceImpl.java new file mode 100644 index 0000000..bdbcd16 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseUserOwnedProductServiceImpl.java @@ -0,0 +1,205 @@ +package com.m2pool.lease.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.pagehelper.PageHelper; + +import com.github.pagehelper.PageInfo; +import com.m2pool.common.redis.service.RedisService; +import com.m2pool.common.security.utils.SecurityUtils; +import com.m2pool.lease.constant.RedisKey; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.service.LeaseUserOwnedProductService; +import com.m2pool.lease.vo.BaseVo; +import com.m2pool.lease.vo.UserOwnedProductVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 用户拥有商品详情表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseUserOwnedProductServiceImpl extends ServiceImpl implements LeaseUserOwnedProductService { + + @Resource + private LeaseUserOwnedProductMapper leaseUserOwnedProductMapper; + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Resource + private RedisService redisService; + + @Override + public PageResult getOwnedList(UserOwnedProductVo userOwnedProductVo) { + PageHelper.startPage(userOwnedProductVo.getPageNum(), userOwnedProductVo.getPageSize()); + //查询已购买的商品集合 按租约状态 未过期在前 + 结束时间 最先结束的在前排序 + List leaseUserOwnedProducts = leaseUserOwnedProductMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseUserOwnedProduct::getUserId, SecurityUtils.getUsername()) + .eq(LeaseUserOwnedProduct::getDel, false) + .orderByAsc(LeaseUserOwnedProduct::getStatus) + .orderByAsc(LeaseUserOwnedProduct::getEndTime)); + PageInfo pageInfo = new PageInfo<>(leaseUserOwnedProducts); + if (leaseUserOwnedProducts.isEmpty()){ + PageResult fail = PageResult.fail(null, "用户未购买商品"); + PageHelper.clearPage(); + return fail; + } + Map> userAndMinerList = leaseUserOwnedProducts.stream().map( + leaseUserOwnedProduct -> + UserMinerDto.builder() + .user(leaseUserOwnedProduct.getUser()) + .miner(leaseUserOwnedProduct.getMiner()) + .coin(leaseUserOwnedProduct.getCoin()) + .build() + ).collect(Collectors.groupingBy(UserMinerDto::getCoin)); + List userMinerPowerList = new ArrayList<>(); + userAndMinerList.forEach((coin, userMinerDtos) -> { + userMinerPowerList.addAll( leaseUserOwnedProductMapper.getUserMinerPower(userMinerDtos, coin)); + }); + + //根据user+miner+coin 获取到实时的算力 + Map collect = userMinerPowerList.stream() + .collect(Collectors.toMap( + dto -> dto.getUser() + "-" + dto.getMiner() + "-" + dto.getCoin(), + dto -> dto + )); + + //获取币价 + Map coinPrice = new HashMap<>(); + //封装返回对象 + List userOwnedProducts = leaseUserOwnedProducts.stream().map(leaseUserOwnedProduct ->{ + String coin = leaseUserOwnedProduct.getCoin(); + BigDecimal bigDecimal = coinPrice.putIfAbsent(coin, redisService.getCacheBigDecimal(RedisKey.getPiceKey(coin))); + + UserOwnedProductDto build = UserOwnedProductDto.builder() + .id(leaseUserOwnedProduct.getId()) + .userId(leaseUserOwnedProduct.getUserId()) + .productMachineId(leaseUserOwnedProduct.getProductMachineId()) + .orderItemId(leaseUserOwnedProduct.getOrderItemId()) + .startTime(leaseUserOwnedProduct.getStartTime()) + .productMachineId(leaseUserOwnedProduct.getProductMachineId()) + .endTime(leaseUserOwnedProduct.getEndTime()) + .currentIncome(leaseUserOwnedProduct.getCurrentIncome()) + .estimatedEndIncome(leaseUserOwnedProduct.getEstimatedEndIncome()) + .currentUsdtIncome(bigDecimal == null ? leaseUserOwnedProduct.getCurrentUsdtIncome() : bigDecimal.multiply(leaseUserOwnedProduct.getCurrentIncome())) + .estimatedEndUsdtIncome(leaseUserOwnedProduct.getEstimatedEndUsdtIncome()) + .purchasedComputingPower(leaseUserOwnedProduct.getPurchasedComputingPower()) + .status(leaseUserOwnedProduct.getStatus()) + .type(leaseUserOwnedProduct.getType()) + .createTime(leaseUserOwnedProduct.getCreateTime()) + .build(); + UserMinerPowerDto userMinerPowerDto = collect.get(leaseUserOwnedProduct.getUser() + "-" + leaseUserOwnedProduct.getMiner() + "-"+ leaseUserOwnedProduct.getCoin()); + if (userMinerPowerDto != null){ + //已购机器30分算力 + build.setCurrentComputingPower(userMinerPowerDto.getPower()); + } + return build; + }).collect(Collectors.toList()); + PageResult success = PageResult.success(userOwnedProducts); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + + @Override + public Result getOwnedById(BaseVo baseVo) { + LeaseUserOwnedProduct leaseUserOwnedProduct = leaseUserOwnedProductMapper.selectById(baseVo.getId()); + List leaseProductMachines = new ArrayList<>(); + leaseProductMachines.add(LeaseProductMachine.builder() + .user(leaseUserOwnedProduct.getUser()) + .miner(leaseUserOwnedProduct.getMiner()) + .build()); + //获取实时算力 + List recentlyFiveMinutesData = leaseProductMachineMapper.getRecentlyFiveMinutesData(leaseProductMachines, leaseUserOwnedProduct.getCoin()); + + UserOwnedProductDto build = UserOwnedProductDto.builder() + .id(leaseUserOwnedProduct.getId()) + .userId(leaseUserOwnedProduct.getUserId()) + .productMachineId(leaseUserOwnedProduct.getProductMachineId()) + .orderItemId(leaseUserOwnedProduct.getOrderItemId()) + .startTime(leaseUserOwnedProduct.getStartTime()) + .productMachineId(leaseUserOwnedProduct.getProductMachineId()) + .endTime(leaseUserOwnedProduct.getEndTime()) + .currentIncome(leaseUserOwnedProduct.getCurrentIncome()) + .estimatedEndIncome(leaseUserOwnedProduct.getEstimatedEndIncome()) + .currentUsdtIncome(leaseUserOwnedProduct.getCurrentUsdtIncome()) + .estimatedEndUsdtIncome(leaseUserOwnedProduct.getEstimatedEndUsdtIncome()) + .purchasedComputingPower(leaseUserOwnedProduct.getPurchasedComputingPower()) + .status(leaseUserOwnedProduct.getStatus()) + .type(leaseUserOwnedProduct.getType()) + .createTime(leaseUserOwnedProduct.getCreateTime()) + .build(); + if (!recentlyFiveMinutesData.isEmpty()){ + build.setCurrentComputingPower(recentlyFiveMinutesData.get(0).getComputingPower().divide(BigDecimal.valueOf(24 * 60 * 60), 2, RoundingMode.HALF_UP)); + } + return Result.success(build); + } + + /** + * 支付验证成功后去修改订单等信息(迁移到这里让事务生效) + * @param leaseOrderItems + * @return 支付订单验证成功的个数 + */ + @Transactional + @Override + public boolean afterPaySuccessTodoSomeEvent(List leaseOrderItems){ + //回调才需要 + // 修改商品售出状态 + //List ids = leaseOrderItems.stream().map(LeaseOrderItem::getProductMachineId).collect(Collectors.toList()); + //int update = leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(1).build(), + // new LambdaQueryWrapper().eq(LeaseProductMachine::getDel, false).in(LeaseProductMachine::getId, ids)); + // 添加购买记录 + //List leaseOrderItems2 = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + // .in(LeaseOrderItem::getProductMachineId, ids)); + + //获取卖方收款币种币价 + BigDecimal price = redisService.getCacheBigDecimal(RedisKey.getPiceKey(leaseOrderItems.get(0).getCoin())); + List collect = leaseOrderItems.stream() + .map(item -> { + // 获取当前的 LocalDateTime + LocalDateTime now = LocalDateTime.now(); + // 获取当天 0 点的 LocalDateTime + LocalDateTime startOfDay = now.toLocalDate().atStartOfDay().plusDays(1); + return LeaseUserOwnedProduct.builder() + .miner(item.getMiner()) + .userId(SecurityUtils.getUsername()) + .user(item.getUser()) + .address(item.getAddress()) + .productMachineId(item.getProductMachineId()) + .orderItemId(item.getId()) + .orderId(item.getOrderId()) + //预估收益由订单创建时固定 实际收益通过定时任务实时计算 + .estimatedEndIncome(item.getTheoryIncome()) + .estimatedEndUsdtIncome(price == null ? BigDecimal.ZERO : item.getTheoryIncome().multiply(price)) + .coin(item.getCoin()) + .startTime(startOfDay) + .type(item.getType()) + .endTime(startOfDay.plusDays(item.getLeaseTime())) + .build(); + }).collect(Collectors.toList()); + boolean b1 = saveBatch(collect); + + return b1; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseUserServiceImpl.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseUserServiceImpl.java new file mode 100644 index 0000000..ab42e59 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/service/impl/LeaseUserServiceImpl.java @@ -0,0 +1,468 @@ +package com.m2pool.lease.service.impl; + +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.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.m2pool.common.core.utils.GoogleAuthenticator; +import com.m2pool.common.core.utils.StringUtils; +import com.m2pool.common.security.utils.SecurityUtils; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.exception.PaymentException; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.mq.message.RabbitmqPayRechargeMessage; +import com.m2pool.lease.mq.message.RabbitmqPayWithdrawMessage; +import com.m2pool.lease.service.LeaseUserService; +import com.m2pool.lease.utils.*; +import com.m2pool.lease.vo.*; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static com.m2pool.lease.constant.CoinCharge.getAllChargesAsDtoList; +import static com.m2pool.lease.constant.CoinCharge.getChargeByChainAndCoin; +import static com.m2pool.lease.constant.RabbitmqConstant.PAY_RECHARGE_QUEUE; +import static com.m2pool.lease.constant.RabbitmqConstant.PAY_WITHDRAW_QUEUE; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Service +public class LeaseUserServiceImpl extends ServiceImpl implements LeaseUserService { + + @Resource + private LeaseUserMapper leaseUserMapper; + + @Resource + private LeaseUserWalletDataMapper leaseUserWalletDataMapper; + + @Resource + private LeaseAutoAddressMapper leaseAutoAddressMapper; + + @Resource + private RabbitTemplate rabbitTemplate; + + @Resource + private LeasePayWithdrawMessageMapper leasePayWithdrawMessageMapper; + + @Resource + private LeasePayRechargeMessageMapper leasePayRechargeMessageMapper; + + + @Resource + private LeasePayRecordMessageMapper leasePayRecordMessageMapper; + + @Resource + private LeaseShopConfigMapper leaseShopConfigMapper; + + @Resource + private LeaseShopMapper leaseShopMapper; + + @Override + public Result login(UserURDVo userURDVo) { + LeaseUser leaseUser = leaseUserMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseUser::getUserId, userURDVo.getUserId())); + if (leaseUser != null){ + return Result.success(UserDto.builder() + .id(leaseUser.getId()) + .userId(leaseUser.getUserId()) + .password(leaseUser.getPassword()) + .build()); + } + LeaseUser build = LeaseUser.builder().password(userURDVo.getPassword()).userId(userURDVo.getUserId()).build(); + int insert = leaseUserMapper.insert(build); + + if (insert > 0){ + return Result.success(UserDto.builder() + .id(build.getId()) + .userId(build.getUserId()) + .password(build.getPassword()) + .build()); + }else { + return Result.fail("登录失败"); + } + } + + @Override + @Transactional + public Result bindWallet(ChainAndCoinVo chainAndCoinVo) { + //同一用户同一个链只会存在一个钱包 + List userWalletDataDtoList = leaseUserWalletDataMapper.getWalletInfoByChain(chainAndCoinVo.getChain(), SecurityUtils.getUsername()); + UserWalletDataDto result; + //如果某个链 未查找到钱包地址 去新绑定一个 + if (userWalletDataDtoList.isEmpty()){ + LeaseAutoAddress bindAddress = getBindAddress(chainAndCoinVo.getChain(), chainAndCoinVo.getCoin()); + if (bindAddress != null){ + String address = bindAddress.getAddress(); + String qrcode = QrCodeUtils.creatRrCode(bindAddress.getAddress(), 200, 200); + String username = SecurityUtils.getUsername(); + String queueId = UuidGeneratorUtil.generateUuidWithoutHyphen(); + result = UserWalletDataDto.builder() + .queueId(queueId) + .fromAddress(address) + .fromChain(chainAndCoinVo.getChain()) + .fromSymbol(chainAndCoinVo.getCoin()) + .balance(BigDecimal.ZERO) + .userId(username) + .qrcode(qrcode) + .id(bindAddress.getId()) + .build(); + leaseUserWalletDataMapper.insert(LeaseUserWalletData.builder() + .queueId(queueId) + .fromChain(chainAndCoinVo.getChain()) + .fromAddress(address) + .fromSymbol(chainAndCoinVo.getCoin()) + .qrcode(qrcode) + .userId( username) + .balance(BigDecimal.ZERO) + .build()); + bindAddress.setStatus(1); + leaseAutoAddressMapper.updateById(bindAddress); + //监听钱包 + sendMessage(result); + }else{ + return Result.fail("没有可用的地址,请联系管理员生成可用的钱包地址"); + } + }else{ + for (UserWalletDataDto userWalletDataDto : userWalletDataDtoList) { + if (userWalletDataDto.getFromSymbol().equals(chainAndCoinVo.getCoin())){ + //开发环境 + //sendMessage(UserWalletDataDto.builder() + // .queueId(userWalletDataDto.getQueueId()) + // .fromAddress(userWalletDataDto.getFromAddress()) + // .fromChain(chainAndCoinVo.getChain()) + // .fromSymbol(chainAndCoinVo.getCoin()) + // .balance(BigDecimal.ZERO) + // .userId(userWalletDataDto.getUserId()) + // .qrcode(userWalletDataDto.getQrcode()) + // .build()); + return Result.success(userWalletDataDto); + } + } + UserWalletDataDto userWalletDataDto = userWalletDataDtoList.get(0); + result = UserWalletDataDto.builder() + .queueId(userWalletDataDto.getQueueId()) + .fromAddress(userWalletDataDto.getFromAddress()) + .fromChain(chainAndCoinVo.getChain()) + .fromSymbol(chainAndCoinVo.getCoin()) + .balance(BigDecimal.ZERO) + .userId(userWalletDataDto.getUserId()) + .qrcode(userWalletDataDto.getQrcode()) + .build(); + + LeaseUserWalletData build = LeaseUserWalletData.builder() + .queueId(userWalletDataDto.getQueueId()) + .fromChain(userWalletDataDto.getFromChain()) + .fromAddress(userWalletDataDto.getFromAddress()) + .fromSymbol(chainAndCoinVo.getCoin()) + .qrcode(userWalletDataDto.getQrcode()) + .userId(userWalletDataDto.getUserId()) + .balance(BigDecimal.ZERO) + .build(); + //链钱包存在 但是新增币种 + leaseUserWalletDataMapper.insert(build); + } + + return Result.success(result); + } + + + @Override + @Transactional + public Result> getWalletInfo() { + List userWalletDataDto = leaseUserWalletDataMapper.selectByUserId(SecurityUtils.getUsername()); + //获取手续费 + for (UserWalletDataDto walletDataDto : userWalletDataDto) { + BigDecimal chargeByChainAndCoin = getChargeByChainAndCoin(walletDataDto.getFromChain(), walletDataDto.getFromSymbol()); + walletDataDto.setCharge(chargeByChainAndCoin); + } + + if (!userWalletDataDto.isEmpty()){ + List collect = userWalletDataDto.stream().peek(item -> item.setBalance(item.getBalance().subtract(item.getBlockedBalance()))).collect(Collectors.toList()); + return Result.success(collect); + } + return Result.fail("未绑定钱包"); + } + + /** + * 检查地址是否半年没有操作(支付,充值,提现) 这个方法可以改成监测 钱包(提现和充值都会修改钱包) 的最近修改时间 + 支付操作 + * @param fromAddress + * @return + */ + public boolean checkAddress(String fromAddress){ + //支付操作 + boolean b = leasePayRecordMessageMapper.checkPayOperator(fromAddress); + //提现操作 + boolean b1 = leasePayWithdrawMessageMapper.checkWithdrawOperator(fromAddress); + //充值操作 + boolean b2 = leasePayRechargeMessageMapper.checkRechargeOperator(fromAddress); + if (b || b1 || b2){ + return true; + } + return false; + } + + /** + * 获取一个未使用的地址 + * @return + */ + public LeaseAutoAddress getBindAddress(String chain, String coin){ + LeaseAutoAddress leaseAutoAddress = leaseAutoAddressMapper.selectOne(new LambdaQueryWrapper() + .eq(LeaseAutoAddress::getStatus, 0) + .eq(LeaseAutoAddress::getFromChain, chain) + .last("limit 1")); + return leaseAutoAddress; + } + + /** + * 发送mq 消息,从而启动钱包监听 + */ + public void sendMessage(UserWalletDataDto userWalletDataDto){ + try { + System.out.println("发送mq消息"); + long l = System.currentTimeMillis()/1000; + RabbitmqPayRechargeMessage build = RabbitmqPayRechargeMessage.builder() + .queue_id(userWalletDataDto.getQueueId()) + .address(userWalletDataDto.getFromAddress()) + .chain(userWalletDataDto.getFromChain()) + .symbol(userWalletDataDto.getFromSymbol()) + .timestamp(l) + .sign(HashUtils.sha256(l)) + .build(); + rabbitTemplate.convertAndSend(PAY_RECHARGE_QUEUE,build); + }catch (Exception e){ + throw new PaymentException("获取钱包信息失败,请刷新重试"); + } + } + + + @Override + @DSTransactional + public Result withdrawBalance(BalanceVo balanceVo) { + String username = SecurityUtils.getUsername(); + UserWalletDataDto userWalletDataDto = leaseUserWalletDataMapper. + getWalletInfoByAddress(balanceVo.getFromAddress(),balanceVo.getToSymbol(),username); + if (balanceVo.getAmount().compareTo(BigDecimal.valueOf(2)) < 0){ + return Result.fail("提现失败:提现金额不能小于 2 USDT"); + } + + if (StringUtils.isNull(userWalletDataDto) || StringUtils.isEmpty(userWalletDataDto.getFromAddress())){ + return Result.fail("未查询到需要提现的钱包地址"); + } + //校验地址 + if (StringUtils.isEmpty(balanceVo.getToAddress()) || StringUtils.isEmpty(balanceVo.getToChain()) || StringUtils.isEmpty(balanceVo.getToSymbol()) ){ + return Result.fail("提现地址,链,币种 不能为空"); + } + + if (!WalletRuleCheckUtils.checkAddress(balanceVo.getToChain(),balanceVo.getToAddress())){ + return Result.fail("提现收款地址格式不正确"); + } + + //获取未冻结余额 + BigDecimal noBlockedBalance = userWalletDataDto.getBalance().subtract(userWalletDataDto.getBlockedBalance()); + + //校验余额是否足够 + if (noBlockedBalance.compareTo(balanceVo.getAmount()) < 0){ + return Result.fail("提现失败:当前未冻结余额:"+noBlockedBalance+"USDT,需提现金额:"+balanceVo.getAmount()+"USDT"); + } + + GoogleInfo googleInfo = leaseUserMapper.getGoogleInfoByEmail(SecurityUtils.getUsername()); + //开发环境 + //if(googleInfo == null || StringUtils.isBlank(googleInfo.getSecret())){ + // //未绑定定谷歌验证器 + // return Result.fail("您的账号未开启双重验证,请先开启验证!"); + //} + //if(!GoogleAuthenticator.checkCode(googleInfo.getSecret(), balanceVo.getCode(), System.currentTimeMillis())){ + // return Result.fail("谷歌验证码错误"); + //} + + //同一个from只能存在一笔提现中的订单 + Integer recentlyOneData = leasePayWithdrawMessageMapper.getRecentlyOneData(balanceVo.getFromAddress(), balanceVo.getToChain()); + if (recentlyOneData != null && recentlyOneData == 2){ + return Result.fail("提现申请失败,已存在一笔金额正在提现中..."); + } + + BigDecimal serviceCharge = getChargeByChainAndCoin(balanceVo.getToChain(), balanceVo.getToSymbol()); + String queueId = UuidGeneratorUtil.generateUuidWithoutHyphen(); + Long timestamp = System.currentTimeMillis()/1000; + //验证通过存储提现记录 + int insert = leasePayWithdrawMessageMapper.insert(LeasePayWithdrawMessage.builder() + .queueId(queueId) + .toChain(balanceVo.getToChain()) + .toSymbol(balanceVo.getToSymbol()) + .fromChain(userWalletDataDto.getFromChain()) + .fromSymbol(userWalletDataDto.getFromSymbol()) + .fromAddress(userWalletDataDto.getFromAddress()) + .serviceCharge(serviceCharge) + .toAddress(balanceVo.getToAddress()) + .amount(balanceVo.getAmount()) + .build()); + + LeaseUserWalletData build = LeaseUserWalletData.builder() + .id(userWalletDataDto.getId()) + .blockedBalance(userWalletDataDto.getBlockedBalance().add(balanceVo.getAmount())) + .build(); + //toAddress 为空,或则与这次请求的钱包地址不同,修改表中toAddress 的值为本次请求参数的钱包地址 + if (userWalletDataDto.getToAddress().isEmpty() || !userWalletDataDto.getToAddress().equals(balanceVo.getToAddress())){ + build.setToAddress(balanceVo.getToAddress()); + build.setToChain(balanceVo.getToChain()); + build.setToSymbol(balanceVo.getToSymbol()); + } + //修改钱包冻结余额 乐观锁 + int i = leaseUserWalletDataMapper.update(build, new LambdaUpdateWrapper() + .eq(LeaseUserWalletData::getBlockedBalance, userWalletDataDto.getBlockedBalance())); + if (insert > 0 && i > 0){ + //发送mq消息到队列 + RabbitmqPayWithdrawMessage message = RabbitmqPayWithdrawMessage.builder() + .queue_id(queueId) + .from_address(userWalletDataDto.getFromAddress()) + .to_address(balanceVo.getToAddress()) + .amount(balanceVo.getAmount().subtract(serviceCharge)) + .chain(balanceVo.getToChain()) + .symbol(balanceVo.getToSymbol()) + .fee(serviceCharge) + .timestamp(timestamp) + .sign(HashUtils.sha256(timestamp)) + .build(); + try { + //发送 提现 消息 + rabbitTemplate.convertAndSend(PAY_WITHDRAW_QUEUE,message); + System.out.println("发送提现消息成功"+queueId); + return Result.success("提现申请成功"); + } catch (Exception e) { + throw new PaymentException(("提现失败,失败原因"+e.getMessage())); + } + } + throw new PaymentException("提现失败,冻结金额已变化,请重新提现!"); + } + + @Override + public PageResult balanceWithdrawList(BalancePageVo balancePageVo) { + + String userEmail = SecurityUtils.getUsername(); + System.out.println("用户"+userEmail+"提现列表"); + List walletList = leaseUserWalletDataMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getUserId,userEmail)); + PageHelper.startPage(balancePageVo.getPageNum(), balancePageVo.getPageSize()); + List payWithdrawMessageDtos = leasePayWithdrawMessageMapper + .balanceWithdrawList( + walletList, + balancePageVo.getStatus()); + PageInfo pageInfo = new PageInfo<>(payWithdrawMessageDtos); + System.out.println(userEmail + "用户提现"+ payWithdrawMessageDtos); + PageResult success = PageResult.success(payWithdrawMessageDtos); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + @Override + public PageResult balanceRechargeList(BalancePageVo balancePageVo) { + + List walletList = leaseUserWalletDataMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getUserId, SecurityUtils.getUsername())); + PageHelper.startPage(balancePageVo.getPageNum(), balancePageVo.getPageSize()); + List payWithdrawMessageDtos = leasePayRechargeMessageMapper.balanceRechargeList(walletList,balancePageVo.getStatus()); + PageInfo pageInfo = new PageInfo<>(payWithdrawMessageDtos); + PageResult success = PageResult.success(payWithdrawMessageDtos); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + @Override + public PageResult balancePayList(BalancePageVo balancePageVo) { + //获取店铺信息 + LeaseShop leaseShop = leaseShopMapper.selectOne(new LambdaQueryWrapper().eq(LeaseShop::getUserEmail, SecurityUtils.getUsername())); + if (leaseShop == null){ + return PageResult.fail(null,"查看交易信息失败"); + } + //获取卖家的自定义钱包地址 + List leaseShopConfigs = leaseShopConfigMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseShopConfig::getShopId, leaseShop.getId())); + if(leaseShopConfigs.isEmpty()){ + return PageResult.fail(null,"未绑定钱包,不存在交易流水"); + } + PageHelper.startPage(balancePageVo.getPageNum(), balancePageVo.getPageSize()); + List payRecordMessageDtos = leasePayRecordMessageMapper.balancePayList(leaseShopConfigs,balancePageVo.getStatus()); + PageInfo pageInfo = new PageInfo<>(payRecordMessageDtos); + PageResult success = PageResult.success(payRecordMessageDtos); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + @Override + public PageResult transactionRecord(RecordTypePageVo recordTypePageVo) { + Integer status = recordTypePageVo.getStatus(); + //先查到用户绑定的所有钱包 + List walletList = leaseUserWalletDataMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getUserId, SecurityUtils.getUsername())); + if (walletList.isEmpty()){ + return PageResult.fail(null,"未绑定钱包,不存在交易流水"); + } + PageHelper.startPage(recordTypePageVo.getPageNum(), recordTypePageVo.getPageSize()); + List transactionRecordDtoList = new ArrayList<>(); + //查询支付记录 + if (status == 0){ + transactionRecordDtoList = leasePayRecordMessageMapper.transactionRecord(walletList); + } + //查询提现记录 + if (status == 1){ + transactionRecordDtoList = leasePayWithdrawMessageMapper.transactionRecord(walletList); + } + //查询充值记录 + if (status == 2){ + transactionRecordDtoList = leasePayRechargeMessageMapper.transactionRecord(walletList); + } + + PageInfo pageInfo = new PageInfo<>(transactionRecordDtoList); + PageResult success = PageResult.success(transactionRecordDtoList); + success.setTotal(pageInfo.getTotal()); + success.setTotalPage(pageInfo.getPages()); + PageHelper.clearPage(); + return success; + } + + @Override + public Result> getRecentlyTransaction() { + List walletList = leaseUserWalletDataMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseUserWalletData::getUserId, SecurityUtils.getUsername())); + if (!walletList.isEmpty()){ + List recentlyTransaction = leasePayRecordMessageMapper.getRecentlyTransaction(walletList); + recentlyTransaction.addAll(leasePayWithdrawMessageMapper.getRecentlyTransaction(walletList)) ; + recentlyTransaction.addAll(leasePayRechargeMessageMapper.getRecentlyTransaction(walletList)); + // 按 updateTime 倒序排序,并取前五个元素 + recentlyTransaction = recentlyTransaction.stream() + .sorted((dto1, dto2) -> dto2.getUpdateTime().compareTo(dto1.getUpdateTime())) + .limit(5) + .collect(Collectors.toList()); + return Result.success(recentlyTransaction); + } + return Result.fail("交易记录为空"); + } + + + @Override + public Result> getCharge() { + List allChargesAsDtoList = getAllChargesAsDtoList(); + return Result.success(allChargesAsDtoList); + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/MachineTask.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/MachineTask.java new file mode 100644 index 0000000..609f853 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/MachineTask.java @@ -0,0 +1,116 @@ +package com.m2pool.lease.task; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.m2pool.lease.dto.ProductMachineDto; +import com.m2pool.lease.entity.LeaseNexaMachineAvgPower; +import com.m2pool.lease.entity.LeaseNexaMachinePower; +import com.m2pool.lease.entity.LeaseProductMachine; +import com.m2pool.lease.mapper.LeaseNexaMachineAvgPowerMapper; +import com.m2pool.lease.mapper.LeaseNexaMachinePowerMapper; +import com.m2pool.lease.mapper.LeaseProductMachineMapper; +import com.m2pool.lease.mapper.LeaseUserOwnedProductMapper; +import com.m2pool.lease.service.LeaseNexaMachinePowerService; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneId; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Description 后台管理系统 定时任务 (没有用到后续可能删除) + * @Date 2025/7/15 15:45 + * @Author yyb + */ +@Configuration +@EnableScheduling +@Deprecated +public class MachineTask { + + // + //@Resource + //private LeaseNexaMachinePowerMapper leaseNexaMachinePowerMapper; + // + //@Resource + //private LeaseUserOwnedProductMapper leaseUserOwnedProductMapper; + // + //@Resource + //private LeaseProductMachineMapper leaseProductMachineMapper; + // + // + //@Resource + //private LeaseNexaMachinePowerService leaseNexaMachinePowerService; + // + //@Resource + //private LeaseNexaMachineAvgPowerMapper leaseNexaMachineAvgPowerMapper; + // + ///** + // * 每五分钟更新一次已经出售的机器的算力(所有币种数据) + // */ + //@Scheduled(cron = "0 0/5 * * * ?") + //public void insertMachinePowerTask(){ + // // 获取五分钟前的时间 + // Calendar calendar = Calendar.getInstance(); + // calendar.set(Calendar.SECOND, 0); + // calendar.set(Calendar.MILLISECOND, 0); + // calendar.add(Calendar.MINUTE, -5); + // Date pointDate = calendar.getTime(); + // //获取当天零点时间 + // DateTime dateTime = DateUtil.beginOfDay(DateTime.now()); + // //1.查询已购生效机器ids集合 + // List productMachineIds = leaseUserOwnedProductMapper.getProductMachineIds(dateTime); + // if (productMachineIds.isEmpty()){ + // System.out.println("没有存在租赁期机器"); + // return; + // } + // // 2. 先查询已购表中的在有效期内的机器user 和 miner + // List leaseProductMachines = leaseProductMachineMapper.selectList(new LambdaQueryWrapper().in(LeaseProductMachine::getId, productMachineIds)); + // // 3.根据这个user 和 miner 从hashrate库中获取对应的实时算力 TODO 这里可能不需要记录实时算力 并且这个定时任务也不需要了。这个实时算力没多大用 后续用收益代替 + // List nexaMinersv2 = leaseNexaMachinePowerMapper.getMachinePowerInHashRateById(leaseProductMachines,pointDate, "nexa_minersv2"); + // //4.向数据库写入数据 + // boolean b = leaseNexaMachinePowerService.saveBatch(nexaMinersv2); + // System.out.println("矿工算力入库状态(true 成功 false 失败):" + b); + //} + // + ///** + // * 每半小时更新一次m2pool中nexa的所有机器的实时平均算力(3天平均算力) + // */ + //@Scheduled(cron = "0 0/30 * * * ?") + //public void insertNexaMachineAvgPowerTask(){ + // //每半小时更新一次 + // List nexaMinersv2 = leaseNexaMachinePowerMapper.getMachineThreePower(null, "nexa"); + // + // if (nexaMinersv2.isEmpty()) { + // return; + // } + // List collect = nexaMinersv2.stream().map(productMachineDto -> { + // // 将 LocalDateTime 转换为 Instant + // Instant startInstant = productMachineDto.getStartTime().atZone(ZoneId.systemDefault()).toInstant(); + // Instant endInstant = productMachineDto.getEndTime().atZone(ZoneId.systemDefault()).toInstant(); + // // 使用 Duration 计算毫秒差 + // Duration duration = Duration.between(startInstant, endInstant); + // long millis = duration.toMillis(); + // return LeaseNexaMachineAvgPower.builder() + // .user(productMachineDto.getUser()) + // .miner(productMachineDto.getMiner()) + // .startTime(productMachineDto.getStartTime()) + // .endTime(productMachineDto.getEndTime()) + // .realAvgPower(productMachineDto.getComputingPower() + // .multiply(BigDecimal.valueOf(Math.pow(2, 32))) + // .divide(BigDecimal.valueOf(millis), 2, RoundingMode.HALF_UP)) + // .build(); + // }).collect(Collectors.toList()); + // + // boolean b = leaseNexaMachineAvgPowerMapper.insertBatchDatas(collect); + //} +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/OrderAndPayTask.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/OrderAndPayTask.java new file mode 100644 index 0000000..224cae3 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/OrderAndPayTask.java @@ -0,0 +1,530 @@ +package com.m2pool.lease.task; + +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.m2pool.lease.constant.PowerUnit; +import com.m2pool.lease.dto.*; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.mq.message.*; +import com.m2pool.lease.service.LeaseOrderItemService; +import com.m2pool.lease.service.LeasePayRecordMessageService; +import com.m2pool.lease.service.LeaseProductService; +import com.m2pool.lease.service.LeaseUserOwnedProductService; +import com.m2pool.lease.utils.HashUtils; +import com.m2pool.lease.utils.UuidGeneratorUtil; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.m2pool.lease.constant.RabbitmqConstant.*; + +/** + * @Description 订单超时 定时任务 + * @Date 2025/7/15 15:45 + * @Author yyb + */ +@Configuration +@EnableScheduling +public class OrderAndPayTask { + + + @Resource + private RabbitTemplate rabbitTemplate; + + @Resource + private LeaseOrderInfoMapper leaseOrderInfoMapper; + @Resource + private LeaseOrderItemMapper leaseOrderItemMapper; + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + @Resource + private LeaseUserWalletDataMapper leaseUserWalletDataMapper; + @Resource + private LeasePayRecordMessageService leasePayRecordMessageService; + @Resource + private LeasePayRecordMessageMapper leasePayRecordMessageMapper; + @Resource + private LeasePayWithdrawMessageMapper leasePayWithdrawMessageMapper; + @Resource + private LeasePayRechargeMessageMapper leasePayRechargeMessageMapper; + @Resource + private LeaseUserOwnedProductService leaseUserOwnedProductService; + @Resource + private LeaseAutoAddressMapper leaseAutoAddressMapper; + @Resource + private LeaseProductService leaseProductService; + @Resource + private LeaseShopConfigMapper leaseShopConfigMapper; + @Resource + private LeaseOrderItemService leaseOrderItemService; + + /** + * 检查钱包半年内是否有 支付,充值,提现操作 + */ + //@Scheduled(cron = "0 5 1 * * ? ") + @Scheduled(cron = "0 0/1 * * * ? ") + @Transactional + public void checkOperator(){ + //1.查询lease_auto_address 表 状态为1 已使用 的钱包 + List validAddress = leaseAutoAddressMapper.getValidAddress(); + if (validAddress.isEmpty()){ + return; + } + //2.获取创建时间大于半年,且余额为0的钱包 + List walletForBalanceIsZero = leaseUserWalletDataMapper.getWalletForBalanceIsZero(validAddress); + if (walletForBalanceIsZero.isEmpty()){ + return; + } + //3.根据钱包查询lease_pay_record_message,lease_pay_recharge_message,lease_pay_withdraw_message 三表半年内是否有记录 + Map payRecordMessageMap = leasePayRecordMessageMapper.checkPayOperatorBatch(walletForBalanceIsZero); + Map withdrawMessageMap = leasePayWithdrawMessageMapper.checkWithdrawOperatorBatch(walletForBalanceIsZero); + Map rechargeMessageMap = leasePayRechargeMessageMapper.checkRechargeOperatorBatch(walletForBalanceIsZero); + + //3.如果没有记录,则修改钱包的状态为 2已过期 + for (LeaseUserWalletData userWalletDataDto : walletForBalanceIsZero) { + String address = userWalletDataDto.getFromAddress(); + CheckAddressDto payRecordMessage = payRecordMessageMap.get(address); + CheckAddressDto withdrawMessage = withdrawMessageMap.get(address); + CheckAddressDto rechargeMessage = rechargeMessageMap.get(address); + + if (payRecordMessage == null && withdrawMessage == null && rechargeMessage == null){ + //发送钱包过期删除监听mq消息 + long l = System.currentTimeMillis()/1000L; + RabbitmqDeleteWalletMessage build = RabbitmqDeleteWalletMessage.builder() + .msg_type(0) + .queue_id(userWalletDataDto.getQueueId().toString()) + .chain(userWalletDataDto.getFromChain()) + .symbol(userWalletDataDto.getFromSymbol()) + .address(userWalletDataDto.getFromAddress()) + .timestamp(l) + .sign(HashUtils.sha256(l)).build(); + rabbitTemplate.convertAndSend(DELETE_WALLET_QUEUE, build); + System.out.println("发送钱包过期删除监听mq消息成功"); + } + } + + } + + + /** + * 支付 定时任务 + */ + //@Scheduled(cron = "0 5 0 * * ? ") + @Scheduled(cron = "0 0/5 * * * ? ") + @Transactional + public void paymentTask(){ + // 获取当天 0 点的 时间 + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startOfDay = now.toLocalDate().atStartOfDay(); + //1.查找在进行中的订单 + List needPayOrderList = leaseOrderInfoMapper.getNeedPayOrderList(); + if (needPayOrderList.isEmpty()){ + System.out.println("没有进行中的订单"); + return; + } + Map orderNumberMap = needPayOrderList.stream().collect(Collectors.toMap(LeaseOrderInfo::getId, LeaseOrderInfo::getOrderNumber)); + //2.根据订单号找到对应的订单详情(不包含租约到期) ,并根据这些订单详情找到每个矿机的信息 + List infoIds = needPayOrderList.stream().map(LeaseOrderInfo::getId).collect(Collectors.toList()); + List leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper() + .eq(LeaseOrderItem::getStatus,1) + .in(LeaseOrderItem::getOrderId, infoIds)); + //因卖方收款钱包修改后,改变订单收款地址 + leaseOrderItems = updateOrderItemSellerWalletAddress(leaseOrderItems); + List machineIdList = leaseOrderItems.stream().map(LeaseOrderItem::getProductMachineId).collect(Collectors.toList()); + List leaseProductMachines = leaseProductMachineMapper.selectBatchIds(machineIdList); + + Map> coinAndMachineMap = leaseProductMachines.stream().collect(Collectors.groupingBy(LeaseProductMachine::getCoin)); + Map idAndMachineMap = leaseProductMachines.stream() + .collect(Collectors.toMap(LeaseProductMachine::getId, Function.identity())); + + List productMachineList = new ArrayList<>(); + //2.1 查询到矿机集合后,按挖矿币种分组-----> 并查询每一组矿机的24小时的总算力 + coinAndMachineMap.forEach((coin, machines) -> { + productMachineList.addAll(leaseProductMachineMapper.getRecentlyFiveMinutesData(leaseProductMachines, coin)); + }); + Map machineDtoMap = productMachineList.stream() + .collect(Collectors.toMap( + dto -> dto.getUser() + "-" + dto.getMiner(), + dto -> dto + )); + //2.2 订单详情集合 按照 买方地址 + 链名称分组 + Map> userMapItem = leaseOrderItems.stream() + .collect(Collectors.groupingBy( + item-> item.getAddress() + "-" + item.getChain() + )); + + + //3.筛选出租期到期的商品 + List expireProductList = new ArrayList<>(); + List rabbitmqPayAutoMessages = new ArrayList<>(); + Map orderInfoIdAndIsComplete = new HashMap<>(); + userMapItem.forEach((addressAndChain, items) -> { + LeaseOrderItem leaseOrderItem = items.get(0); + + List expire = new ArrayList<>(); + + //因为生成订单时会冻结整个订单的金额,所以这里不用再去判断 + String queueId = UuidGeneratorUtil.generateUuidWithoutHyphen(); + long timestamp = System.currentTimeMillis()/1000; + + //买方信息 + RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder() + .queue_id(queueId) + .chain(leaseOrderItem.getChain()) + .symbol(leaseOrderItem.getSymbol()) + .total_amount(BigDecimal.ZERO) + .from_address(leaseOrderItem.getFromAddress()) + .timestamp(timestamp) + .sign(HashUtils.sha256(timestamp)) + .build(); + + //封装卖方收款信息 + List sellerPayInfoMessages = new ArrayList<>(); + //买方收款信息 相同订单最后整合成一个卖方信息 + Map> orderIdMap = items.stream().collect(Collectors.groupingBy(LeaseOrderItem::getOrderId)); + orderIdMap.forEach((orderId, orderItemList) -> { + LeaseOrderItem orderInfo = orderItemList.get(0); + RabbitmqPayAutoInfoMessage sellInfo = RabbitmqPayAutoInfoMessage.builder() + .to_address(orderInfo.getAddress()) + .amount(BigDecimal.ZERO) + .blockAmount(BigDecimal.ZERO) + .needAmount(BigDecimal.ZERO) + .order_id(orderInfo.getOrderId().toString()) + .shopId(orderInfo.getShopId()) + .userId(orderInfo.getUserId()) + .build(); + for (LeaseOrderItem item : orderItemList) { + orderInfoIdAndIsComplete.putIfAbsent(item.getOrderId(), true); + LocalDateTime expireTime = item.getCreateTime().plusDays(1).toLocalDate().atStartOfDay().plusDays(item.getLeaseTime()); + //开发环境 + List list = leasePayRecordMessageService.list(new LambdaQueryWrapper() + .eq(LeasePayRecordMessage::getOrderId, item.getOrderId())); + // 租期已过 + if (startOfDay.isAfter(expireTime) /**开发环境*/|| list.size() == item.getLeaseTime()) { + item.setStatus(0); + expire.add(item); + }else{ + orderInfoIdAndIsComplete.put(item.getOrderId(), false); + //根据算力波动实时计算需支付金额 + String key = item.getUser() + "-" + item.getMiner(); + LeaseProductMachine machine = idAndMachineMap.get(item.getProductMachineId()); + ProductMachineDto productMachineDto = machineDtoMap.get(key); + sellInfo.setNeedAmount(sellInfo.getNeedAmount().add(item.getPrice())); + sellInfo.setBlockAmount(sellInfo.getBlockAmount().add(item.getPrice())); + if (productMachineDto != null){ + + //理论算力 + BigDecimal theoryPower = machine.getTheoryPower().multiply(PowerUnit.getPower(machine.getUnit())) + .divide(BigDecimal.valueOf(1000 * 1000),2,RoundingMode.HALF_UP); + //实际算力 + BigDecimal realPower = productMachineDto.getComputingPower() + .divide(BigDecimal.valueOf(24 * 60 * 60), 2, RoundingMode.HALF_UP); + //设置实际支付金额 + BigDecimal divide = theoryPower.subtract(realPower).divide(theoryPower, 10, RoundingMode.HALF_UP); + + //设置实际需要发送消息去支付的各订单金额和总金额 + if (divide.compareTo(BigDecimal.valueOf(0.05)) > 0){ + sellInfo.setAmount(sellInfo.getAmount().add(item.getPrice().multiply(BigDecimal.ONE.subtract(divide)))); + build.setTotal_amount(build.getTotal_amount().add(item.getPrice().multiply(BigDecimal.ONE.subtract(divide)))); + }else{ + build.setTotal_amount(build.getTotal_amount().add(item.getPrice())); + sellInfo.setAmount(sellInfo.getAmount().add(item.getPrice())); + } + } + + } + } + sellerPayInfoMessages.add(sellInfo); + + }); + build.setTransactions(sellerPayInfoMessages); + //if 开发环境 + if(build.getTotal_amount().compareTo(BigDecimal.ZERO) > 0){ + rabbitmqPayAutoMessages.add(build); + } + expireProductList.addAll(expire); + }); + //4.租约到期相关信息修改 + if (!expireProductList.isEmpty()){ + List itemIds = new ArrayList<>(); + List machineIds = new ArrayList<>(); + for (LeaseOrderItem leaseOrderItem : expireProductList) { + itemIds.add(leaseOrderItem.getId()); + machineIds.add(leaseOrderItem.getProductMachineId()); + } + //4.1 修改订单详情表中状态为 0 租约已过期 + leaseOrderItemMapper.update(LeaseOrderItem.builder().status(0).build(), new LambdaUpdateWrapper() + .in(LeaseOrderItem::getId, itemIds)); + //4.2 修改商品库存矿机表 矿机状态为 0 未售出 + leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(), new LambdaUpdateWrapper() + .in(LeaseProductMachine::getId, machineIds)); + //4.3 修改用户已购矿机表状态为 1 套餐已过期 + leaseUserOwnedProductService.update(LeaseUserOwnedProduct.builder().status(1).build(),new LambdaUpdateWrapper() + .in(LeaseUserOwnedProduct::getProductMachineId, machineIds)); + + //4.4 矿机对应商品 销售量修改 + Map productIdAndCountMap = expireProductList.stream().collect(Collectors.groupingBy(LeaseOrderItem::getProductId, Collectors.counting())); + Set longs = productIdAndCountMap.keySet(); + List leaseProducts = leaseProductService.list(new LambdaQueryWrapper().in(LeaseProduct::getId, longs)); + leaseProducts.forEach(leaseProduct -> { + leaseProduct.setSaleNumber(leaseProduct.getSaleNumber() - productIdAndCountMap.get(leaseProduct.getId()).intValue()); + }); + leaseProductService.updateBatchById(leaseProducts); + + //4.5 找到详情表所有状态为0 租约已过期 ,并且订单info表订单状态为7 进行中的订单 并改为状态8 订单已完成 + List orderIds = orderInfoIdAndIsComplete.entrySet().stream() + .filter(entry -> Boolean.TRUE.equals(entry.getValue())) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + if(!orderIds.isEmpty()){ + leaseOrderInfoMapper.update(LeaseOrderInfo.builder().status(8).build(), + new LambdaQueryWrapper().in(LeaseOrderInfo::getId, orderIds)); + } + + } + //5.根据这些订单发送今天的支付消息到mq + if (!rabbitmqPayAutoMessages.isEmpty()){ + List collect = new ArrayList<>(); + for (RabbitmqPayAutoMessage rabbitmqPayAutoMessage : rabbitmqPayAutoMessages) { + List list = new ArrayList<>(); + for (RabbitmqPayAutoInfoMessage transaction : rabbitmqPayAutoMessage.getTransactions()) { + list.add(LeasePayRecordMessage.builder() + .queueId(rabbitmqPayAutoMessage.getQueue_id()) + .fromAddress(rabbitmqPayAutoMessage.getFrom_address()) + .orderId(transaction.getOrder_id()) + .orderNumber(orderNumberMap.get(Long.parseLong(transaction.getOrder_id()))) + .toAddress(transaction.getTo_address()) + .amount(transaction.getNeedAmount()) + .needAmount(transaction.getAmount()) + .fromChain(rabbitmqPayAutoMessage.getChain()) + .fromSymbol(rabbitmqPayAutoMessage.getSymbol()) + .blockAmount(transaction.getBlockAmount()) + .shopId(transaction.getShopId()) + .userId(transaction.getUserId()) + .toChain(rabbitmqPayAutoMessage.getChain()) + .toSymbol(rabbitmqPayAutoMessage.getSymbol()) + .build()); + } + try{ + rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, rabbitmqPayAutoMessage); + System.out.println("支付消息发送成功:"+rabbitmqPayAutoMessage); + }catch (Exception e){ + //一般出现在rabbitmq服务出现故障时出现,状态改为三,状态为三后续消息重试 + list = list.stream().peek(item->item.setStatus(3)).collect(Collectors.toList()); + System.out.println("消息发送失败:"+e.getMessage()); + }finally { + collect.addAll(list); + } + } + leasePayRecordMessageService.saveBatch(collect); + } + } + + /** + * 修改卖家钱包被修改后 的 order_item 的 中对应卖家的钱包地址 + * @param orderItemList 今天需要支付的订单 + */ + public List updateOrderItemSellerWalletAddress( List orderItemList){ + List collect = orderItemList.stream() + .map(LeaseOrderItem -> ShopChainAndCoinDto.builder().shopId(LeaseOrderItem.getShopId()) + .coin(LeaseOrderItem.getSymbol()) + .chain(LeaseOrderItem.getChain()).build()) + .distinct() + .collect(Collectors.toList()); + //查询到对应商铺对应的 chain 然后比较上面的链对应的地址是否改变 + List shopConfigList = leaseShopConfigMapper.selectShopConfigByShopIdAndSymbolAndChain(collect); + List updateOrderItemList = new ArrayList<>(); + // 遍历 orderItemList + for (LeaseOrderItem orderItem : orderItemList) { + for (ShopConfigDelDto shopConfig : shopConfigList) { + // 检查 chain 和 shopId 是否相同 + if (orderItem.getShopId().equals(shopConfig.getShopId()) && + orderItem.getChain().equals(shopConfig.getChain())) { + // 检查 address 是否不同 + if (!orderItem.getAddress().equals(shopConfig.getPayAddress())) { + // 更新 orderItem 的 address + orderItem.setAddress(shopConfig.getPayAddress()); + updateOrderItemList.add(orderItem); + } + break; + } + } + } + leaseOrderItemService.updateBatchById(updateOrderItemList); + return orderItemList; + + } + + + /** + * 一些校验失败的支付消息需要重新发送 + */ + @Scheduled(cron = "0 0/5 * * * ? ") + @Transactional + public void checkPushFailPayMessage(){ + //查找出状态为三 消息发送失败的订单 再次发送支付消息。直到成功为止 + List list = leasePayRecordMessageService.list(new LambdaQueryWrapper() + .eq(LeasePayRecordMessage::getStatus, 3) + .ge(LeasePayRecordMessage::getCreateTime, LocalDateTime.now().minusHours(3))); + System.out.println("开始重新发送支付消息"+ JSON.toJSONString(list)); + List updateList = new ArrayList<>(); + Map> collect = list.stream().collect(Collectors.groupingBy(LeasePayRecordMessage::getQueueId)); + collect.forEach((queueId, itemList)->{ + LeasePayRecordMessage item = itemList.get(0); + long l = System.currentTimeMillis()/1000; + RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder() + .queue_id(item.getQueueId()) + .chain(item.getToChain()) + .symbol(item.getFromSymbol()) + .from_address(item.getFromAddress()) + .sign(HashUtils.sha256(l)) + .timestamp(l) + .build(); + List transactions = itemList.stream() + .map(orderInfo -> RabbitmqPayAutoInfoMessage.builder() + .order_id(orderInfo.getOrderId()) + .amount(orderInfo.getAmount()) + .blockAmount(orderInfo.getBlockAmount()) + .shopId(orderInfo.getShopId()) + .userId(orderInfo.getUserId()) + .build()) + .collect(Collectors.toList()); + build.setTransactions(transactions); + try { + rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build); + List updates = itemList.stream().peek(record -> record.setStatus(2)).collect(Collectors.toList()); + updateList.addAll(updates); + }catch (Exception e){ + List updates = itemList.stream().peek(record -> record.setStatus(3)).collect(Collectors.toList()); + updateList.addAll(updates); + System.out.println("消息发送失败(5分)"+e.getMessage()); + } + + }); + if (!updateList.isEmpty()){ + leasePayRecordMessageService.updateBatchById(updateList); + } + } + + + //@Scheduled(cron = "0 0/1 * * * ? ") + //@Transactional + //public void test(){ + // System.out.println("发送消息到队列------------------------------------------"); + // long l = System.currentTimeMillis()/1000; + // //支付 + // rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, RabbitmqPayAutoMessage.builder() + // .queue_id("1") + // .from_address("1") + // .to_address("1") + // .amount(BigDecimal.valueOf(1)) + // .chain("1") + // .symbol("1") + // .order_id("1") + // .timestamp(l) + // .sign(HashUtils.sha256(l)) + // .build() + // ); + // //充值 + // rabbitTemplate.convertAndSend(PAY_RECHARGE_QUEUE, RabbitmqPayRechargeMessage.builder() + // .address("2") + // .chain("2") + // .symbol("2") + // .timestamp(l) + // .sign(HashUtils.sha256(l)) + // .build() + // ); + // //提现 + // rabbitTemplate.convertAndSend(PAY_WITHDRAW_QUEUE, RabbitmqPayWithdrawMessage.builder() + // .queue_id("1") + // .from_address("1") + // .to_address("1") + // .amount(BigDecimal.valueOf(1)) + // .chain("1") + // .symbol("1") + // .timestamp(l) + // .sign(HashUtils.sha256(l)) + // .build() + // ); + // + // + // + //} + + /** + * 每分钟检查一次超时的订单,是否修改了状态为 6 订单已超时 + */ + //@Scheduled(cron = "0 0/1 * * * ? ") + //@Transactional + //public void checkIsExpireOrder(){ + // LocalDateTime now = LocalDateTime.now(); + // LocalDateTime createTime = now.minusMinutes(15); + // List leaseOrderInfos = leaseOrderInfoMapper.selectList(new LambdaQueryWrapper() + // .eq(LeaseOrderInfo::getStatus, PAYMENT_IN_PROGRESS.getCode()) + // .lt(LeaseOrderInfo::getCreateTime, createTime)); + // + // //普通订单状态跟着支付订单走,先修改支付订单状态(查找15m前的支付中订单) + // List leasePaymentRecords = leasePaymentRecordMapper.selectList(new LambdaQueryWrapper() + // .eq(LeasePaymentRecord::getStatus, PAYMENT_IN_PROGRESS.getCode()) + // .lt(LeasePaymentRecord::getCreateTime, createTime)); + // if (leasePaymentRecords.isEmpty()){ + // return; + // } + // //1.根据 订单实际时间已超时 但是订单状态为 6支付中 的情况----->修改这些订单的状态为 5订单已超时 + // int updatePayStatus = leasePaymentRecordMapper.updateBatchStatusForOderIdAndShopId(leasePaymentRecords); + // + // //2.修改机器中售出状态 从2售出中改为 0未售出 + // List orderStatusIsPayInData = leaseOrderItemMapper.getMachineByOrderStatusIsPayInData(leasePaymentRecords); + // if (orderStatusIsPayInData.isEmpty()){ + // return; + // } + // int updateMachineStatus = leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(), + // new LambdaQueryWrapper() + // .eq(LeaseProductMachine::getSaleState, 2).in(LeaseProductMachine::getId, orderStatusIsPayInData)); + // + // //3.修改普通订单状态为 5订单已超时 + // List orderIds = leaseOrderInfos.stream().map(LeaseOrderInfo::getId).collect(Collectors.toList()); + // if (orderIds.isEmpty()){ + // return; + // } + // int updateOrderStatus = leaseOrderInfoMapper.update(LeaseOrderInfo.builder().status(5).build(), + // new LambdaQueryWrapper().eq(LeaseOrderInfo::getStatus, 6).in(LeaseOrderInfo::getId, orderIds)); + // + // System.out.println("修改了" + updatePayStatus + "个支付订单状态为5订单已超时。" + // + updateMachineStatus + "个机器状态为未售出。"+ updateOrderStatus + "个普通订单状态为5订单已超时"); + // + //} + + + /** + * //获取 15 钟内支付订单 再次去校验是否支付全部成功 全部成功则修改订单状态为 1全部支付成功 + */ + //@Scheduled(cron = "0/30 * * * * ? ") + //@Transactional + //public void paymentRecord(){ + // List leasePaymentRecordList = leasePaymentRecordMapper.selectList(new LambdaQueryWrapper() + // .eq(LeasePaymentRecord::getDel, false) + // .ge(LeasePaymentRecord::getCreateTime, LocalDateTime.now().minusMinutes(15))); + // + // if (!leasePaymentRecordList.isEmpty()){ + // leasePaymentRecordService.paymentCallbackTask(leasePaymentRecordList); + // } + //} + + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/OwnProductTask.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/OwnProductTask.java new file mode 100644 index 0000000..a4cd8bd --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/task/OwnProductTask.java @@ -0,0 +1,278 @@ +package com.m2pool.lease.task; + +import cn.hutool.json.JSONUtil; +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.lease.dto.HourIncomeDto; +import com.m2pool.lease.dto.OrderStatusDto; +import com.m2pool.lease.entity.*; +import com.m2pool.lease.mapper.*; +import com.m2pool.lease.mq.message.RabbitmqPoolProxyMessage; +import com.m2pool.lease.service.LeaseOrderInfoService; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.rmi.dgc.Lease; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +import static com.m2pool.lease.constant.RabbitmqConstant.POOL_PROXY_QUEUE_NAME; + +/** + * @Description 后台管理系统 定时任务 + * @Date 2025/7/15 15:45 + * @Author yyb + */ +@Configuration +@EnableScheduling +public class OwnProductTask { + + @Resource + private LeaseUserOwnedProductMapper leaseUserOwnedProductMapper; + + + @Resource + private LeaseProductMachineMapper leaseProductMachineMapper; + + @Resource + private LeaseOrderItemMapper leaseOrderItemMapper; + + @Resource + private LeaseOrderInfoService leaseOrderInfoService; + + @Resource + private LeasePayRecordMessageMapper leasePayRecordMessageMapper; + + @Resource + private RabbitTemplate rabbitTemplate; + + private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors(); + private static final int BATCH_SIZE = 1000; + private final ExecutorService executorService = java.util.concurrent.Executors.newFixedThreadPool(THREAD_POOL_SIZE); + /** + * 修改已购表租约过期状态为1 已过期 + 机器表状态为0 未售出 + 修改租约到期订单状态为已完成 + */ + @Scheduled(cron = "0 1,5,7 0 * * ? ") + //@Scheduled(cron = "0 0/3 * * * ? ") + @Transactional + public void updateOwnMachineStateTask(){ + // 获取当天 0 点的 LocalDateTime + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startOfDay = now.toLocalDate().atStartOfDay(); + //1. 查询当天失效机器 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .eq(LeaseUserOwnedProduct::getEndTime, startOfDay).eq(LeaseUserOwnedProduct::getStatus, 0); + List leaseUserOwnedProducts = leaseUserOwnedProductMapper.selectList(wrapper); + + if (!leaseUserOwnedProducts.isEmpty()){ + //2.修改商品机器表中 销售状态为 0 未售出 + List ids = new ArrayList<>(); + List isExpireIds = new ArrayList<>(); + List itemIds = new ArrayList<>(); + for (LeaseUserOwnedProduct leaseUserOwnedProduct : leaseUserOwnedProducts) { + ids.add(leaseUserOwnedProduct.getId()); + isExpireIds.add(leaseUserOwnedProduct.getProductMachineId()); + itemIds.add(leaseUserOwnedProduct.getOrderItemId()); + } + leaseUserOwnedProductMapper.update(LeaseUserOwnedProduct.builder().status(1).build(),new LambdaUpdateWrapper() + .in(LeaseUserOwnedProduct::getId, ids)); + leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(), + new LambdaQueryWrapper().in(LeaseProductMachine::getId, isExpireIds)); + leaseOrderItemMapper.update(LeaseOrderItem.builder().status(0).build(),new LambdaQueryWrapper().in(LeaseOrderItem::getId, itemIds)); + //3.订单所有机器已过期,直接修改订单状态为已完成 + List orderIds = leaseOrderItemMapper.getOrderIds(itemIds); + List orderInfoStatus = leaseOrderItemMapper.getOrderInfoStatus(orderIds); + + List infoList = new ArrayList<>(); + orderInfoStatus.forEach(item->{ + if (item.getOrderInfoStatus() == 8){ + infoList.add(LeaseOrderInfo.builder().id(item.getOrderId()).status(8).build()); + } + }); + if (!infoList.isEmpty()){ + leaseOrderInfoService.saveOrUpdateBatch(infoList); + } + + System.out.println("租约过期机器状态修改成功"); + //3.发送rabbitmq消息给矿池代理删除代理的矿机 + //sendRabbitmqMessage(leaseUserOwnedProducts); + } + } + + public void sendRabbitmqMessage( List leaseUserOwnedProducts) { + leaseUserOwnedProducts.forEach(item -> { + executorService.execute(()->{ + RabbitmqPoolProxyMessage rabbitmqPoolProxyMessage = RabbitmqPoolProxyMessage.builder() + .MethodID(1) + .Msg("") + .ID(item.getUser() + "-" + item.getMiner()) + .Address(item.getAddress()) + .build(); + try { + rabbitTemplate.convertAndSend(POOL_PROXY_QUEUE_NAME, rabbitmqPoolProxyMessage); + //同步阻塞等待消息发送成功 + //boolean b = rabbitTemplate.waitForConfirms(10000); + } catch (Exception e) { + + System.err.println("发送失败: " + e.getMessage()); + } + }); + }); + + } + + + + //@Scheduled(cron = "0 35 0/1 * * ? ") + @Scheduled(cron = "0 0/5 * * * ? ") + @DSTransactional + public void updateNexaIncomeTask(){ + List updateList = computeIncome("nexa"); + //批量修改 + batchUpdateLeaseUserOwnedProducts(updateList); + + } + + //@Scheduled(cron = "10 35 0/1 * * ? ") + @Scheduled(cron = "0 0/5 * * * ? ") + @DSTransactional + public void updateGrsIncomeTask(){ + List updateList = computeIncome("grs"); + //批量修改 + batchUpdateLeaseUserOwnedProducts(updateList); + } + + //@Scheduled(cron = "20 35 0/1 * * ? ") + @Scheduled(cron = "0 0/5 * * * ? ") + @DSTransactional + public void updateRxdIncomeTask(){ + List updateList = computeIncome("rxd"); + //批量修改 + batchUpdateLeaseUserOwnedProducts(updateList); + } + + //@Scheduled(cron = "30 35 0/1 * * ? ") + @Scheduled(cron = "0 0/5 * * * ? ") + @DSTransactional + public void updateMonaIncomeTask(){ + List updateList = computeIncome("mona"); + //批量修改 + batchUpdateLeaseUserOwnedProducts(updateList); + } + + + /** + * 计算已购生效机器过去一小时收益 + * @param coin + */ + public List computeIncome(String coin){ + //获取当前时间整点时间 + LocalDateTime now = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); + //获取当天开始时间 + LocalDateTime startOfDay = now.with(LocalTime.MIN); + LocalDateTime end = now.minusHours(1); + LocalDateTime start = now.minusHours(2); + //1. 查询在有效期内的已购机器 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .eq(LeaseUserOwnedProduct::getCoin, coin) + .le(LeaseUserOwnedProduct::getStartTime, startOfDay) + .gt(LeaseUserOwnedProduct::getEndTime, startOfDay); + List leaseUserOwnedProducts = leaseUserOwnedProductMapper.selectList(wrapper); + + + //2.获取近一个小时矿机的收益 +并计算实时收益 + List updateList = new ArrayList<>(); + if (!leaseUserOwnedProducts.isEmpty()){ + Map collect = new HashMap<>(); + Set orderInfoIds = new HashSet<>(); + for (LeaseUserOwnedProduct item : leaseUserOwnedProducts) { + collect.put(item.getUser() + "_" + item.getMiner() + "-" + item.getCoin(), item); + orderInfoIds.add(item.getOrderId()); + } + + //2.1 查询当天已支付订单 + Map recordStatus = leasePayRecordMessageMapper.selectOrderInfoMap(orderInfoIds); + + List incomeDtos = leaseUserOwnedProductMapper.getHourIncomeList(leaseUserOwnedProducts,coin, start, end); + + for (HourIncomeDto hourIncomeDto : incomeDtos) { + LeaseUserOwnedProduct leaseUserOwnedProduct = collect.get(hourIncomeDto.getUser() + "_" + hourIncomeDto.getMiner()+ "-" + coin) ; + LeasePayRecordMessage leasePayRecordMessage = recordStatus.get(leaseUserOwnedProduct.getOrderId()); + if (leasePayRecordMessage != null && leasePayRecordMessage.getStatus() == 1){ + BigDecimal coinIncome = hourIncomeDto.getIncome().add(leaseUserOwnedProduct.getCurrentIncome()); + BigDecimal usdtIncome = hourIncomeDto.getUsdtIncome().add(leaseUserOwnedProduct.getCurrentUsdtIncome()); + //当日待结算收益不为0,把待结算收益加到当前收益中 + if (leaseUserOwnedProduct.getSettleIncome().compareTo(BigDecimal.ZERO) > 0){ + coinIncome = coinIncome.add(leaseUserOwnedProduct.getSettleIncome()); + usdtIncome = usdtIncome.add(leaseUserOwnedProduct.getSettleUsdtIncome()); + leaseUserOwnedProduct.setSettleIncome(BigDecimal.ZERO); + leaseUserOwnedProduct.setSettleUsdtIncome(BigDecimal.ZERO); + } + leaseUserOwnedProduct.setCurrentIncome(coinIncome); + leaseUserOwnedProduct.setCurrentUsdtIncome(usdtIncome); + + }else{ + leaseUserOwnedProduct.setSettleIncome(hourIncomeDto.getIncome().add(leaseUserOwnedProduct.getSettleIncome())); + leaseUserOwnedProduct.setSettleUsdtIncome(hourIncomeDto.getUsdtIncome().add(leaseUserOwnedProduct.getSettleUsdtIncome())); + } + updateList.add(leaseUserOwnedProduct); + } + } + return updateList; + } + + /** + * 批量修改已购机器的收益 + * @param updateList + */ + public void batchUpdateLeaseUserOwnedProducts(List updateList) { + // 用于记录执行过程中的异常 + AtomicReference exceptionRef = new AtomicReference<>(); + List> futures = new ArrayList<>(); + + for (int i = 0; i < updateList.size(); i += BATCH_SIZE) { + int toIndex = Math.min(i + BATCH_SIZE, updateList.size()); + List subList = updateList.subList(i, toIndex); + + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + leaseUserOwnedProductMapper.updateBatchIncome(subList); + } catch (Exception e) { + exceptionRef.set(e); + throw new RuntimeException(e); + } + }, executorService); + + futures.add(future); + } + + // 等待所有任务完成 + CompletableFuture allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + try { + allFutures.get(); + } catch (InterruptedException | ExecutionException e) { + // 如果有异常,将异常信息设置到 exceptionRef 中 + exceptionRef.set(e); + } + + // 如果有异常,抛出异常触发事务回滚 + if (exceptionRef.get() != null) { + throw new RuntimeException("批量更新数据时发生错误", exceptionRef.get()); + } + } + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/HashUtils.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/HashUtils.java new file mode 100644 index 0000000..39a5a5d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/HashUtils.java @@ -0,0 +1,66 @@ +package com.m2pool.lease.utils; + +import com.m2pool.lease.entity.LeaseProduct; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.HashMap; + +public class HashUtils { + + private static final String key = "9f3c7a12"; + + /** + * 将十六进制字符串转换为字节数组 (两个字符代表一个字节) + * @param hex 十六进制字符串 + * @return 转换后的字节数组 + */ + public static byte[] hexStringToByteArray(String hex) { + int len = hex.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + + Character.digit(hex.charAt(i+1), 16)); + } + return data; + } + + public static String sha256(Long input) { + try { + // 获取 SHA-256 算法的 MessageDigest 实例 + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + String key = getkey(input); + // 将十六进制字符串转换为字节数组 + byte[] inputBytes = hexStringToByteArray(key); + //时间戳 + 秘钥 + + // 将输入字节数组进行 SHA-256 哈希计算 + byte[] hashBytes = digest.digest(inputBytes); + String s = JnaUtils.bytesToHex(hashBytes); + return s; + } catch (Exception e) { + throw new RuntimeException("SHA-256算法不可用", e); + } + } + + /** + * 获取key + * @param timestamp 时间戳 + * @return key + */ + public static String getkey(Long timestamp){ + String inputStr = timestamp.toString(); + // 将字符串转换为 BigInteger 对象,指定基数为 10 + BigInteger decimalValue = new BigInteger(inputStr, 10); + // 将 BigInteger 对象转换为十六进制字符串 + return decimalValue.toString(16) + key; + } + + public static void main(String[] args) { + //Long inputStr = 1758610297L; + //System.out.println("加密结果" + sha256(inputStr)); + + } + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/HttpPayUtils.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/HttpPayUtils.java new file mode 100644 index 0000000..b2f3900 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/HttpPayUtils.java @@ -0,0 +1,92 @@ +package com.m2pool.lease.utils; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * @Description 支付工具类 + * @Date 2025/8/8 11:05 + * @Author yyb + */ +public class HttpPayUtils { + + private static final String URI = "http://127.0.0.1:12345"; + + public static final String PAY_ETH = "/checkPayment/eth"; + /** + * 发送 GET 请求 + * @param params 请求参数,键值对形式 + * @return 响应结果字符串 + */ + public static String doGet(String method,Map params) { + String URL = URI + method; + if (params != null && !params.isEmpty()) { + return HttpUtil.get(URL, params); + } + return HttpUtil.get(URL); + } + /** + * 发送 POST 请求,使用 JSON 格式提交数据 + * @param json 请求的 JSON 数据 + * @return 响应结果字符串 + */ + public static PaymentDto doPost(String method,String json) { + String URL = URI + method; + HttpResponse response = HttpRequest.post(URL) + .header("Content-Type", "application/json") + .body(json) + .execute(); + System.out.println("支付回调结果"+response); + if (response.body() != null && !response.body().isEmpty()) { + return JSONUtil.toBean(response.body(), PaymentDto.class); + } + return null; + } + + + @Data + public class PaymentDto { + private int code; + private boolean result; + private List data; + } + + + @Data + public class PaymentData { + private String blockNumber; + //大于等于支付订单的时间 + private String timeStamp; + //交易id + private String hash; + private String nonce; + private String blockHash; + //发送者钱包地址 + private String from; + private String contractAddress; + // 接收者钱包地址 + private String to; + // 转账金额一致 + private String value; + private String tokenName; + private String tokenSymbol; + private String tokenDecimal; + private String transactionIndex; + private String gas; + private String gasPrice; + private String gasUsed; + private String cumulativeGasUsed; + private String input; + private String methodId; + private String functionName; + private String confirmations; + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/JnaUtils.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/JnaUtils.java new file mode 100644 index 0000000..1fe8501 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/JnaUtils.java @@ -0,0 +1,54 @@ +package com.m2pool.lease.utils; + +import java.math.BigInteger; + +/** + * @Description 支付工具类 + * @Date 2025/8/8 11:05 + * @Author yyb + */ +public class JnaUtils { + + private static final String key = "m2pool"; + + /** + * 获取签名秘钥 + * @param timeStamp + * @return + */ + public static String getSign(Long timeStamp){ + String inputStr = "1758610297"; + // 将字符串转换为 BigInteger 对象,指定基数为 10 + BigInteger decimalValue = new BigInteger(inputStr, 10); + // 将 BigInteger 对象转换为十六进制字符串 + String hexValue = decimalValue.toString(16); + // 输出结果长度为 32 字节 + byte[] output = new byte[32]; + try { + NativeLibrary.INSTANCE.alph_hash(output, hexValue); + // 处理输出结果 + } catch (Exception e) { + System.err.println("调用本地方法失败: " + e.getMessage()); + e.printStackTrace(); + } + + + String s = bytesToHex(output); + System.out.println("加密结果"+s); + return s; + } + + public static String bytesToHex(byte[] bytes) { + StringBuilder hexString = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/NativeLibrary.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/NativeLibrary.java new file mode 100644 index 0000000..dd3ed1a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/NativeLibrary.java @@ -0,0 +1,12 @@ +package com.m2pool.lease.utils; + +import com.sun.jna.Library; +import com.sun.jna.Native; + +public interface NativeLibrary extends Library { + // 加载本地库,注意在 Linux 下库名不需要带 lib 前缀和 .so 后缀 + NativeLibrary INSTANCE = Native.load("/home/ubuntu/cnative/libblake3.so", NativeLibrary.class); + + // 定义本地方法,方法签名要和 C 头文件中的函数签名对应 + void alph_hash(byte[] output, String input); +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/PowerUnitUtils.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/PowerUnitUtils.java new file mode 100644 index 0000000..a94d7db --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/PowerUnitUtils.java @@ -0,0 +1,63 @@ +package com.m2pool.lease.utils; + +import com.m2pool.common.core.utils.StringUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * @Description 算力转换 + * @Date 2024/6/13 10:54 + * @Author dy + */ +public class PowerUnitUtils { + + /** + * 根据unit 对value 进行转换 + * @param unit + * @param value + * @return + */ + public static BigDecimal getPower(String unit,BigDecimal value) { + + + if (StringUtils.isEmpty(unit)) { + unit = "gh/s"; + } + unit = unit.toLowerCase(); + // 根据输入单位计算对应的转换因子 + BigDecimal conversionFactor; + switch (unit) { + case "h/s": + conversionFactor = BigDecimal.ONE; + break; + case "kh/s": + conversionFactor = BigDecimal.valueOf(1000L); + break; + case "mh/s": + conversionFactor = BigDecimal.valueOf(1000L).pow(2); + break; + case "gh/s": + conversionFactor = BigDecimal.valueOf(1000L).pow(3); + break; + case "th/s": + conversionFactor = BigDecimal.valueOf(1000L).pow(4); + break; + case "ph/s": + conversionFactor = BigDecimal.valueOf(1000L).pow(5); + break; + case "eh/s": + conversionFactor = BigDecimal.valueOf(1000L).pow(6); + break; + default: + throw new IllegalArgumentException("不支持的单位: " + unit); + } + + // 进行单位转换并保留小数 + return value.divide(conversionFactor,6, RoundingMode.HALF_UP); + } + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/QrCodeUtils.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/QrCodeUtils.java new file mode 100644 index 0000000..989452f --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/QrCodeUtils.java @@ -0,0 +1,96 @@ +package com.m2pool.lease.utils; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.m2pool.lease.dto.QrCodeDto; +import org.apache.commons.codec.binary.Base64; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Hashtable; + +/** + * @Description URL转Base64二维码 + * @Date 2024/8/21 11:18 + * @Author 杜懿 + */ +public class QrCodeUtils { + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static String creatRrCode(String contents, int width, int height) { + String base64 = ""; + + Hashtable hints = new Hashtable(); + hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); + hints.put(EncodeHintType.MARGIN, 1); + + try { + BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints); + bitMatrix = deleteWhite(bitMatrix); + + // 1、读取文件转换为字节数组 + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BufferedImage image = toBufferedImage(bitMatrix); + + //转换成png格式的IO流 + ImageIO.write(image, "png", out); + byte[] bytes = out.toByteArray(); + + // 2、将字节数组转为二进制 + base64 = Base64.encodeBase64String(bytes).trim(); + + } catch (WriterException e) { + e.printStackTrace(); + + } catch (IOException e) { + e.printStackTrace(); + } + + return base64; + } + + /** + * image流数据处理 + */ + private static BufferedImage toBufferedImage(BitMatrix matrix) { + int width = matrix.getWidth(); + int height = matrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); + } + } + return image; + } + + /** + * 去白边 + */ + private static BitMatrix deleteWhite(BitMatrix matrix) { + int[] rec = matrix.getEnclosingRectangle(); + int resWidth = rec[2] + 1; + int resHeight = rec[3] + 1; + + BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); + resMatrix.clear(); + for (int i = 0; i < resWidth; i++) { + for (int j = 0; j < resHeight; j++) { + if (matrix.get(i + rec[0], j + rec[1])) + resMatrix.set(i, j); + } + } + return resMatrix; + } + + public static void main(String[] args) { + System.out.println(creatRrCode("0x1c3d5d2a0eeb78476bcefadb44fbf24d29eeb964", 200,200)); + } + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/UuidGeneratorUtil.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/UuidGeneratorUtil.java new file mode 100644 index 0000000..34fc5a0 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/UuidGeneratorUtil.java @@ -0,0 +1,37 @@ +package com.m2pool.lease.utils; + +import pt.kcry.blake3.Blake3; + +import java.util.UUID; + +/** + * UUID 生成工具类,提供生成标准 UUID 和去除连字符的 UUID 的方法。 + */ +public class UuidGeneratorUtil { + + /** + * 生成标准格式的 UUID,包含连字符,例如:550e8400-e29b-41d4-a716-446655440000 + * + * @return 标准格式的 UUID 字符串 + */ + public static String generateStandardUuid() { + return UUID.randomUUID().toString(); + } + + /** + * 生成去除连字符的 UUID,例如:550e8400e29b41d4a716446655440000 + * + * @return 去除连字符的 UUID 字符串 + */ + public static String generateUuidWithoutHyphen() { + return generateStandardUuid().replace("-", ""); + } + + // 测试代码 + public static void main(String[] args) { + //System.out.println("标准 UUID: " + generateStandardUuid()); + //System.out.println("无连字符 UUID: " + generateUuidWithoutHyphen()); + + } + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/WalletRuleCheckUtils.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/WalletRuleCheckUtils.java new file mode 100644 index 0000000..fe3037b --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/utils/WalletRuleCheckUtils.java @@ -0,0 +1,95 @@ +package com.m2pool.lease.utils; + +import cn.hutool.core.net.URLEncoder; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +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){ + if (address == null) { + return false; + } + chain = chain.toUpperCase(); + switch (chain) { + case "TRON": + return checkTRON(address); + case "ETH": + return checkETH(address); + default: + return false; + } + } + + /** + * 调用 Tronscan API 获取账户信息 + * @param address 要查询的账户地址 + * @return API 响应结果 + */ + public static boolean checkTRON(String address) { + String baseUrl = "https://apilist.tronscanapi.com/api/accountv2"; + // 对地址进行 URL 编码 + String encodedAddress = URLEncoder.createDefault().encode(address, StandardCharsets.UTF_8); + // 构建请求 URL + String url = baseUrl + "?address=" + encodedAddress; + // 发送带有请求头的 GET 请求 + HttpResponse response = HttpRequest.get(url) + .header("TRON-PRO-API-KEY", API_KEY) + .execute(); + + String s = parseResult(response.body()); + if (!StringUtils.isEmpty(s) && "some parameters are invalid or out of range".equals(s)){ + return false; + } + return true; + } + + /** + * 解析 API 响应结果,获取 result 字段 + * @param response API 响应结果 + * @return result 字段的值 + */ + private static String parseResult(String response) { + JSONObject jsonObject = JSONUtil.parseObj(response); + return jsonObject.getStr("message"); + } + + // ---------------TRON校验------------------- + + + + // ---------------ETH校验 目前只做了基础校验还需要EIP-55 校验------------------- + private static final Pattern ETH_BASIC_PATTERN = Pattern.compile("^0x[a-fA-F0-9]{40}$"); + + /** + * 基础格式校验以太坊地址 + * @param address 待校验的以太坊地址 + * @return 如果地址格式正确返回 true,否则返回 false + */ + public static boolean checkETH(String address) { + if (address == null) { + return false; + } + return ETH_BASIC_PATTERN.matcher(address).matches(); + } + // ---------------ETH校验------------------- + public static void main(String[] args) { + + } +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BalancePageVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BalancePageVo.java new file mode 100644 index 0000000..8ed6504 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BalancePageVo.java @@ -0,0 +1,29 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 余额提现/充值分页请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "余额提现/充值分页请求对象",value = "BalancePageVo") +public class BalancePageVo extends PageVo{ + + @ApiModelProperty(value = "记录状态 充值业务 : 0 充值失败 1 充值成功 2 充值中 3 证书校验失败 ---提现业务: 0 提现失败 1 提现成功 2 提现中 3 证书校验失败 支付服务:0 支付失败 1 支付成功 2 支付中 3 证书校验失败 ") + private Integer status; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BalanceVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BalanceVo.java new file mode 100644 index 0000000..2b7aee7 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BalanceVo.java @@ -0,0 +1,62 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.poi.openxml4j.opc.PackageRelationship; + +import java.math.BigDecimal; + +/** + *

+ * 余额提现请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "余额提现请求对象",value = "BalanceVo") +public class BalanceVo { + + + /** + * 提现金额 + */ + @ApiModelProperty(value = "提现 金额",required = true) + private BigDecimal amount; + + /** + * 链 + */ + @ApiModelProperty(value = "用户自定义的钱包地址链",required = true) + private String toChain; + + /** + * 币种 + */ + @ApiModelProperty(value = "用户自定义的钱包地址的币种",required = true) + private String toSymbol; + + @ApiModelProperty(value = "手续费",required = true) + private BigDecimal serviceCharge; + + @ApiModelProperty(value = "绑定的地址",required = true) + private String fromAddress; + /** + * 提现地址(用户自定义) + */ + @ApiModelProperty(value = "提现地址(用户自定义)",required = true) + private String toAddress; + + @ApiModelProperty(value = "谷歌双重验证验证码",required = true) + private Long code; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BaseVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BaseVo.java new file mode 100644 index 0000000..22dade8 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/BaseVo.java @@ -0,0 +1,22 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 基础请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "基础请求对象",value = "BaseVo" ) +public class BaseVo { + @ApiModelProperty(value = "id") + private Long id; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ChainAndCoinVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ChainAndCoinVo.java new file mode 100644 index 0000000..a0d6a08 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ChainAndCoinVo.java @@ -0,0 +1,30 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 余额提现/充值分页请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "充值步骤选择链和钱包后自动绑定钱包请求对象",value = "ChainAndCoinVo") +public class ChainAndCoinVo { + + @ApiModelProperty(value = "链名称",example = "TRON") + private String chain; + + @ApiModelProperty(value = "币种名称",example = "BTC") + private String coin; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/CheckPayStatusVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/CheckPayStatusVo.java new file mode 100644 index 0000000..b90d9c9 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/CheckPayStatusVo.java @@ -0,0 +1,55 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 支付校验请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付校验请求对象",value = "CheckPayStatusVo") +public class CheckPayStatusVo { + + @ApiModelProperty(value = "支付订单ID") + private Long id; + + //@ApiModelProperty(value = "订单ID") + //private Long orderId; + // + //@ApiModelProperty(value = "商铺ID") + //private Long shopId; + // + //@ApiModelProperty(value = "支付订单状态") + //private Integer status; + + + /** + * 卖方地址 + */ + @ApiModelProperty(value = "买方钱包地址") + private String form; + + /** + * 交易id + */ + @ApiModelProperty(value = "交易id,多个交易id以英文','隔开") + private String hash; + + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/CoinVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/CoinVo.java new file mode 100644 index 0000000..99af1ec --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/CoinVo.java @@ -0,0 +1,22 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 币种请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "币种请求对象",value = "CoinVo" ) +public class CoinVo { + + @ApiModelProperty(value = "币种") + private String coin; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderAndCodeVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderAndCodeVo.java new file mode 100644 index 0000000..485624e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderAndCodeVo.java @@ -0,0 +1,37 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + * @Description 支付订单请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单结算及谷歌验证码请求对象",value = "OrderAndCodeVo" ) +public class OrderAndCodeVo { + + @ApiModelProperty(value = "支付币种",required = true) + private String coin; + + @ApiModelProperty(value = "链名称",required = true) + private String chain; + + @ApiModelProperty(value = "币价",required = true) + private BigDecimal price; + + @ApiModelProperty(value = "谷歌验证码",required = true) + private Long code; + + @ApiModelProperty(value = "订单信息列表",required = true) + private List orderInfoVoList; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoStateVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoStateVo.java new file mode 100644 index 0000000..80fd167 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoStateVo.java @@ -0,0 +1,31 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 订单状态请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单状态请求对象",value = "OrderInfoStateVo" ) +public class OrderInfoStateVo extends PageVo{ + + /** + * 7 订单进行中 8 订单已完成 + */ + @ApiModelProperty(value = " 7 订单进行中 8 订单已完成") + private Integer status; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoURDVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoURDVo.java new file mode 100644 index 0000000..9f57461 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoURDVo.java @@ -0,0 +1,52 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 订单请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单请求对象",value = "OrderInfoURDVo" ) +public class OrderInfoURDVo extends BaseVo{ + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单号") + private String orderNumber; + + /** + * 用户 ID + */ + @ApiModelProperty(value = "用户 ID") + private Long userId; + + /** + * 订单总价 + */ + @ApiModelProperty(value = "订单总价") + private BigDecimal totalPrice; + + /** + * 收货地址(模拟) + */ + @ApiModelProperty(value = "收货地址(模拟)") + private String address; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoVo.java new file mode 100644 index 0000000..b7d325e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderInfoVo.java @@ -0,0 +1,40 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 订单生成请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单生成请求对象",value = "OrderInfoVo") +public class OrderInfoVo extends BaseVo{ + + @ApiModelProperty(value = "店铺ID",example = "8") + private Long shopId; + + @ApiModelProperty(value = "商品 ID",example = "2") + private Long productId; + + @ApiModelProperty(value = "矿机 ID",example = "1") + private Long machineId; + + @ApiModelProperty(value = "租赁时长",example = "1") + private Integer leaseTime; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderItemVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderItemVo.java new file mode 100644 index 0000000..25eb2b9 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderItemVo.java @@ -0,0 +1,47 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 订单明细请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "订单明细请求对象",value = "OrderItemVo") +public class OrderItemVo extends BaseVo{ + /** + * 机器id + */ + @ApiModelProperty(value = "机器id",example = "1") + private Long productMachineId; + + @ApiModelProperty(value = "矿工账号") + private String user; + + @ApiModelProperty(value = "矿机编号") + private String miner; + + /** + * 商品单价 + */ + @ApiModelProperty(value = "商品价格") + private BigDecimal price; + + @ApiModelProperty(value = "租赁天数",example = "1") + private Integer leaseTime; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderVo.java new file mode 100644 index 0000000..9018269 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/OrderVo.java @@ -0,0 +1,21 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 支付订单请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付订单请求对象",value = "OrderVo" ) +public class OrderVo { + @ApiModelProperty(value = "普通订单id") + private Long orderId; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PageVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PageVo.java new file mode 100644 index 0000000..379e7a7 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PageVo.java @@ -0,0 +1,21 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description 分页请求对象 + * @Date 2025/5/23 09:52 + * @Author yyb + */ +@Data +@ApiModel(value = "分页请求对象") +public class PageVo { + @ApiModelProperty(value = "当前页码 (默认为1)",example = "1") + private Integer pageNum = 1; + + @ApiModelProperty(value = "每页条数(默认为20)",example = "20") + private Integer pageSize = 20; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PayVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PayVo.java new file mode 100644 index 0000000..8e1279e --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PayVo.java @@ -0,0 +1,48 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 支付请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "支付请求对象",value = "PayVo") +public class PayVo { + + /** + * 支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd + */ + private String coin; + + /** + * 支付金额 + */ + private BigDecimal amount; + + /** + * 支付地址 + */ + private String address; + + /** + * 支付订单生成时间戳 + */ + private Long ts; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PriceCalculateVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PriceCalculateVo.java new file mode 100644 index 0000000..f1c7dbe --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/PriceCalculateVo.java @@ -0,0 +1,26 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * @Description 算力价格计算器请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "算力价格计算器请求对象",value = "PriceCalculateVo" ) +public class PriceCalculateVo { + + @ApiModelProperty(value = "机器实时算力") + private BigDecimal power; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductAndMachineVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductAndMachineVo.java new file mode 100644 index 0000000..f2a5a99 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductAndMachineVo.java @@ -0,0 +1,25 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 购物车商品机器删除请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "购物车商品机器删除请求对象",value = "ProductAndMachineVo" ) +public class ProductAndMachineVo { + @ApiModelProperty(value = "商品id") + private Long productId; + + @ApiModelProperty(value = "机器id") + private Long machineId; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductForUpdateMachineVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductForUpdateMachineVo.java new file mode 100644 index 0000000..7401e05 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductForUpdateMachineVo.java @@ -0,0 +1,21 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Description 卖方查询商品矿机列表请求对象 + * @Date 2025/7/25 11:15 + * @Author yyb + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "卖方查询商品矿机列表请求对象",value = "ProductForUpdateMachineVo" ) +public class ProductForUpdateMachineVo extends PageVo{ + @ApiModelProperty(value = "商品id") + private Long id; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductMachineParamsVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductMachineParamsVo.java new file mode 100644 index 0000000..556ef09 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductMachineParamsVo.java @@ -0,0 +1,57 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 机器参数请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "机器参数请求对象",value = "ProductMachineParamsVo" ) +public class ProductMachineParamsVo{ + + @ApiModelProperty(value = "商品 ID",example = "2") + private Long productId; + + @ApiModelProperty(value = "矿机型号",example = "龍珠") + private String type; + + @ApiModelProperty(value = "商品机器单机理论算力(卖方手动填写)",example = "0.01") + private BigDecimal theoryPower; + + @ApiModelProperty(value = "商品机器单机算力单位",example = "TH/S") + private String unit; + + @ApiModelProperty(value = "功耗",example = "0.01") + private BigDecimal powerDissipation; + + @ApiModelProperty(value = "机器成本价格单位$ [ 功耗 * 电费 * 24 * (1 + 收益率) ]",example = "0.01") + private BigDecimal cost; + + //@ApiModelProperty(value = "电费",example = "0.01") + //private BigDecimal electricityBill; + + //@ApiModelProperty(value = "收益率",example = "0.01") + //private BigDecimal incomeRate; + + @ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7") + private Integer maxLeaseDays; + + @ApiModelProperty(value = "商品对应的机器列表") + List productMachineURDVos; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductMachineURDVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductMachineURDVo.java new file mode 100644 index 0000000..a072613 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductMachineURDVo.java @@ -0,0 +1,66 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 商品对应实际商品请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品对应实际商品请求对象",value = "ProductMachineURDVo" ) +public class ProductMachineURDVo extends BaseVo{ + + @ApiModelProperty(value = "矿机型号",example = "龍珠") + private String type; + + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号",example = "a20") + private String user; + + /** + * 挖矿机器编号 + */ + @ApiModelProperty(value = "挖矿机器编号",example = "100x1") + private String miner; + + /** + * 单价 + */ + @ApiModelProperty(value = "实际价格(同一个商品下的矿机单价默认为商品表的cost字段值= 功耗 * 电费 $/度 * 24h * (1+收益率) 用户可以自定义该价格)",example = "2760.00") + private BigDecimal price; + + /** + * 上下架状态,0 上架,1 下架 + */ + @ApiModelProperty(value = "上下架状态,0 上架,1 下架",example = "1") + private Integer state; + + @ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7") + private Integer maxLeaseDays; + + @ApiModelProperty(value = "商品机器单机理论算力(卖方手动填写)",example = "0.01") + private BigDecimal theoryPower; + + @ApiModelProperty(value = "商品机器单机算力单位",example = "TH/S") + private String unit; + + @ApiModelProperty(value = "功耗",example = "0.01") + private BigDecimal powerDissipation; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductPageVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductPageVo.java new file mode 100644 index 0000000..82c7046 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductPageVo.java @@ -0,0 +1,39 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 商品列表分页请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品列表分页请求对象",value = "ProductPageVo" ) +public class ProductPageVo extends PageVo{ + + /** + * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + @ApiModelProperty(value = "矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona",example = "nexa") + private String coin; + + /** + * 算法 + */ + @ApiModelProperty(value = "算法") + private String algorithm; + + @ApiModelProperty(value = "用户邮箱(个人中心商品列表)") + private String userEmail; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductURDVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductURDVo.java new file mode 100644 index 0000000..e9ef8db --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductURDVo.java @@ -0,0 +1,59 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 商品返回对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "商品返回对象",value = "ProductURDVo" ) +public class ProductURDVo extends BaseVo{ + + @ApiModelProperty(value = "上下架状态 0 上架,1 下架",example = "1") + private Integer state; + + @ApiModelProperty(value = "店铺id",example = "8") + private Long shopId; + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称",example = "Nexa-M2-Miner") + private String name; + + /** + * 商品图片路径 + */ + @ApiModelProperty(value = "商品图片路径",example = "这是图片路径") + private String image; + + /** + * 商品描述 + */ + @ApiModelProperty(value = "商品描述",example = "这是商品描述") + private String description; + + /** + * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona + */ + @ApiModelProperty(value = "矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona",example = "nexa") + private String coin; + + + @ApiModelProperty(value = "商品类型 0 矿机,1 算力",example = "0") + private Integer type; + + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductUpdateMachineVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductUpdateMachineVo.java new file mode 100644 index 0000000..5d211d1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ProductUpdateMachineVo.java @@ -0,0 +1,76 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 矿机修改接口请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "矿机修改接口请求对象",value = "ProductUpdateMachineVo" ) +public class ProductUpdateMachineVo { + + @ApiModelProperty(value = "矿机id") + private Long id; + + @ApiModelProperty(value = "矿机型号",example = "龍珠") + private String type; + + @ApiModelProperty(value = "商品机器单机理论算力(卖方手动填写)",example = "0.01") + private BigDecimal theoryPower; + + @ApiModelProperty(value = "商品机器单机算力单位",example = "TH/S") + private String unit; + + @ApiModelProperty(value = "功耗",example = "0.01") + private BigDecimal powerDissipation; + + //@ApiModelProperty(value = "电费",example = "0.01") + //private BigDecimal electricityBill; + + @ApiModelProperty(value = "收益率",example = "0.01") + private BigDecimal incomeRate; + + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号",example = "a20") + private String user; + + /** + * 挖矿机器编号 + */ + @ApiModelProperty(value = "挖矿机器编号",example = "100x1") + private String miner; + + /** + * 单价 + */ + @ApiModelProperty(value = "实际价格(同一个商品下的矿机单价默认为商品表的cost字段值= 功耗 * 电费 $/度 * 24h * (1+收益率) 用户可以自定义该价格)",example = "2760.00") + private BigDecimal price; + + /** + * 上下架状态,0 上架,1 下架 + */ + @ApiModelProperty(value = "上下架状态,0 上架,1 下架",example = "1") + private Integer state; + + @ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7") + private Integer maxLeaseDays; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/RechargeVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/RechargeVo.java new file mode 100644 index 0000000..d9a6891 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/RechargeVo.java @@ -0,0 +1,51 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + *

+ * 余额提现请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "余额充值请求对象",value = "RechargeVo") +public class RechargeVo { + + + /** + * 提现金额 + */ + @ApiModelProperty(value = "提现/充值 金额",required = true) + private BigDecimal amount; + + /** + * 链 + */ + @ApiModelProperty(value = "链",required = true) + private String chain; + + /** + * 币种 + */ + @ApiModelProperty(value = "币种",required = true) + private String symbol; + + /** + * 提现地址(用户自定义) + */ + @ApiModelProperty(value = "提现地址(用户自定义)",required = true) + private String address; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/RecordTypePageVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/RecordTypePageVo.java new file mode 100644 index 0000000..904dae6 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/RecordTypePageVo.java @@ -0,0 +1,27 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 交易流水请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "交易流水请求对象",value = "RecordTypePageVo") +public class RecordTypePageVo extends PageVo{ + + @ApiModelProperty(value = "0 支付 1 提现 2 充值") + private Integer status; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShopConfigVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShopConfigVo.java new file mode 100644 index 0000000..19082af --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShopConfigVo.java @@ -0,0 +1,53 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + *

+ * 店铺商品配置请求对象 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺商品配置请求对象",value = "ShopConfigVo") +public class ShopConfigVo extends BaseVo { + + + + /** + * 链名称 + */ + @ApiModelProperty(value = "链名称",example = "tron") + private String chain; + + /** + * nexa rxd dgbo dgbq dgbs alph enx grs mona usdt + */ + @ApiModelProperty(value = "支付币种(多个以逗号隔开)",example = "nexa") + private String payCoin; + + /** + * 币种类型 0 虚拟币 1 稳定币 + */ + @ApiModelProperty(value = "币种类型 0 虚拟币 1 稳定币",example = "0") + private Integer payType; + + /** + * 卖方对应收款钱包 + */ + @ApiModelProperty(value = "卖方对应收款钱包",example = "nexa:nqtsq5g50jkkmklvjyaflg46c4nwuy46z9gzswqe3l0csc7g") + private String payAddress; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShopVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShopVo.java new file mode 100644 index 0000000..aa18f95 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShopVo.java @@ -0,0 +1,57 @@ +package com.m2pool.lease.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import lombok.*; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 店铺表 + *

+ * + * @author yyb + * @since 2025-08-05 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "店铺请求对象",value = "ShopVo") +public class ShopVo extends BaseVo{ + + /** + * 店铺名称 + */ + @ApiModelProperty(value = "店铺名称",example = "nexa算力租赁专卖店") + private String name; + + /** + * 店铺图片路径 + */ + @ApiModelProperty(value = "店铺图片路径") + private String image; + + /** + * 店铺描述 + */ + @ApiModelProperty(value = "店铺描述",example = "欢迎来到nexa算力租赁专卖店") + private String description; + + /** + * 商铺状态 0 待审核 1 审核通过(店铺开启) 2 店铺关闭 + */ + @ApiModelProperty(value = "商铺状态 0 待审核 1 审核通过(店铺开启) 2 店铺关闭",example = "1") + private Integer state; + /** + * 逻辑删除字段 + */ + //@ApiModelProperty(value = "逻辑删除字段",example = "false") + //private Boolean del; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShoppingCartInfoURDVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShoppingCartInfoURDVo.java new file mode 100644 index 0000000..c7cfd67 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/ShoppingCartInfoURDVo.java @@ -0,0 +1,45 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 购物车详情请求对象 + *

+ * + * @author yyb + * @since 2025-07-24 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "购物车详情请求对象",value = "ShoppingCartInfoDto") +public class ShoppingCartInfoURDVo extends BaseVo{ + + + /** + * 商品 ID + */ + @ApiModelProperty(value = "商品 ID", example = "2") + private Long productId; + + /** + * 商品机器ID + */ + @ApiModelProperty(value = "商品机器ID", example = "1") + private Long productMachineId; + + /** + * 租赁天数 + */ + @ApiModelProperty(value = "租赁天数", example = "1") + private Integer leaseTime; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserMinerVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserMinerVo.java new file mode 100644 index 0000000..d4854f1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserMinerVo.java @@ -0,0 +1,40 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 用户挖矿账户矿工请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户挖矿账户矿工请求对象",value = "UserMinerVo" ) +public class UserMinerVo { + /** + * 挖矿机器 对应的矿工账号 + */ + @ApiModelProperty(value = "挖矿机器 对应的矿工账号",example = "a20") + private String user; + + /** + * 挖矿机器编号 + */ + //@ApiModelProperty(value = "挖矿机器编号") + //private String miner; + + + @ApiModelProperty(value = "机器挖矿币种(默认nexa)",example = "nexa",required = true) + private String coin = "nexa"; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserOwnedProductVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserOwnedProductVo.java new file mode 100644 index 0000000..aa1ea49 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserOwnedProductVo.java @@ -0,0 +1,30 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 用户拥有商品基础请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户拥有商品基础请求对象",value = "UserOwnedBaseVo" ) +public class UserOwnedProductVo extends PageVo{ + /** + * ID + */ + @ApiModelProperty(value = "ID") + private Long id; + +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserURDVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserURDVo.java new file mode 100644 index 0000000..7bb95cb --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserURDVo.java @@ -0,0 +1,35 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 用户请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户请求对象",value = "UserDto") +public class UserURDVo { + /** + * 用户名 + */ + @ApiModelProperty(value = "用户id(邮箱)",example = "Eudora.law@outlook.com") + private String userId; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码",example = "123456") + private String password; +} diff --git a/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserVo.java b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserVo.java new file mode 100644 index 0000000..5f37bc3 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/java/com/m2pool/lease/vo/UserVo.java @@ -0,0 +1,24 @@ +package com.m2pool.lease.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 用户基础请求对象 + *

+ * + * @author yyb + * @since 2025-07-23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户基础请求对象",value = "UserDto") +public class UserVo { + @ApiModelProperty(value = "id") + private Long id; +} diff --git a/m2pool-modules/m2pool-lease/src/main/resources/bootstrap-dev.yml b/m2pool-modules/m2pool-lease/src/main/resources/bootstrap-dev.yml new file mode 100644 index 0000000..01c95d6 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,39 @@ +#开发环境 +server: + port: 8898 + compression: + enabled: true + mime-types: application/json +spring: + mvc: + pathmatch: + matching-strategy: ant_path_matcher + application: + # 应用名称 + name: m2pool-lease + # profiles: + # # 环境配置 + # active: test + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 10.168.2.220:8848 + namespace: m2_dev + group: m2_dev_group + # server-addr: 127.0.0.1:8808 + config: + # 配置中心地址 + server-addr: 10.168.2.220:8848 + # server-addr: 127.0.0.1:8808 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + namespace: m2_dev + group: m2_dev_group + servlet: + multipart: + max-file-size: 2MB + max-request-size: 8MB diff --git a/m2pool-modules/m2pool-lease/src/main/resources/bootstrap-test.yml b/m2pool-modules/m2pool-lease/src/main/resources/bootstrap-test.yml new file mode 100644 index 0000000..0719136 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/bootstrap-test.yml @@ -0,0 +1,39 @@ +#测试环境 +server: + port: 8888 + compression: + enabled: true + mime-types: application/json +spring: + mvc: + pathmatch: + matching-strategy: ant_path_matcher + application: + # 应用名称 + name: m2pool-lease + # profiles: + # # 环境配置 + # active: test + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 127.0.0.1:8808 + namespace: m2_test + group: m2_test_group + # server-addr: 127.0.0.1:8808 + config: + # 配置中心地址 + server-addr: 127.0.0.1:8808 + # server-addr: 127.0.0.1:8808 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + namespace: m2_test + group: m2_test_group + servlet: + multipart: + max-file-size: 2MB + max-request-size: 8MB diff --git a/m2pool-modules/m2pool-lease/src/main/resources/bootstrap.yml b/m2pool-modules/m2pool-lease/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..3d7808a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/bootstrap.yml @@ -0,0 +1,3 @@ +spring: + profiles: + active: dev diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseAutoAddressMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseAutoAddressMapper.xml new file mode 100644 index 0000000..0f90ceb --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseAutoAddressMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + id, address, status,from_symbol,from_chain + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseNexaMachineAvgPowerMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseNexaMachineAvgPowerMapper.xml new file mode 100644 index 0000000..11964e0 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseNexaMachineAvgPowerMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + id, user, miner, start_time, end_time, real_avg_power + + + insert into lease_nexa_machine_avg_power (user, miner, start_time, end_time, real_avg_power) values + + (#{item.user}, #{item.miner}, #{item.startTime}, #{item.endTime}, #{item.realAvgPower}) + + ON DUPLICATE KEY UPDATE + `start_time` = VALUES(`start_time`), + `end_time` = VALUES(`end_time`), + `real_avg_power` = VALUES(`real_avg_power`) + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseNexaMachinePowerMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseNexaMachinePowerMapper.xml new file mode 100644 index 0000000..8b60413 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseNexaMachinePowerMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + id, `user`, miner, `date`, accepts, `state`, last_submit + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseOrderInfoMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseOrderInfoMapper.xml new file mode 100644 index 0000000..ba053b1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseOrderInfoMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + id, order_number, user_id, total_price, status, address, create_time, update_time, del + + + + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseOrderItemMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseOrderItemMapper.xml new file mode 100644 index 0000000..2e921f5 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseOrderItemMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + id, order_id, product_id,product_machine_id,`name`, unit, image, quantity, price, create_time, update_time, del + + + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayRechargeMessageMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayRechargeMessageMapper.xml new file mode 100644 index 0000000..03654da --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayRechargeMessageMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + id, address, amount, symbol,`chain`, create_time, update_time, status, del + + + + + + + + + + insert into lease_pay_recharge_message (queue_id,address, amount, chain, symbol, status,tx_hash) + values (#{leasePayRechargeMessage.queueId},#{leasePayRechargeMessage.address}, + #{leasePayRechargeMessage.amount}, #{leasePayRechargeMessage.chain}, + #{leasePayRechargeMessage.symbol},#{leasePayRechargeMessage.status},#{leasePayRechargeMessage.txHash}) + ON DUPLICATE KEY UPDATE + `queue_id` = VALUES(`queue_id`), + `address` = VALUES(`address`), + `amount` = VALUES(`amount`), + `chain` = VALUES(`chain`), + `symbol` = VALUES(`symbol`), + `status` = VALUES(`status`), + `tx_hash` = VALUES(`tx_hash`) + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayRecordMessageMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayRecordMessageMapper.xml new file mode 100644 index 0000000..01db70d --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayRecordMessageMapper.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + id, queue_id, from_address, to_address, amount, `to_chain`, to_symbol,from_chain,from_symbol, order_id,create_time, status, del + + + + + + + + + + + update lease_pay_record_message + set + status = #{leasePayRecordMessage.status}, + update_time = #{leasePayRecordMessage.updateTime}, + tx_hash = #{leasePayRecordMessage.txHash}, + block_height = #{leasePayRecordMessage.blockHeight}, + real_amount = #{leasePayRecordMessage.realAmount} + where id = #{leasePayRecordMessage.id} and (tx_hash = "" or tx_hash = #{txHash}) + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayWithdrawMessageMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayWithdrawMessageMapper.xml new file mode 100644 index 0000000..de70b33 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePayWithdrawMessageMapper.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + id, queue_id, from_address, to_address, amount, from_chain, from_symbol,to_chain,to_symbol, create_time, update_time, status, del + + + + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePaymentRecordMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePaymentRecordMapper.xml new file mode 100644 index 0000000..120be10 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeasePaymentRecordMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + id, order_id, payment_method, amount, status, create_time, update_time, del + + + update lease_payment_record set status = 5 + where + status = 6 AND + ( + (`order_id` = #{item.orderId} and `shop_id` = #{item.shopId}) + ) + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductIncomeMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductIncomeMapper.xml new file mode 100644 index 0000000..cd0b89a --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductIncomeMapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + id, user_owned_product_id, average_income, estimated_end_income, current_actual_income, create_time, update_time + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductMachineMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductMachineMapper.xml new file mode 100644 index 0000000..a2b093f --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductMachineMapper.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + id, product_id, user, miner, price, computing_power, state, del, create_time, update_time + + + + UPDATE lease_product_machine + SET + sale_state = 1 + WHERE + id IN + + #{id} + + and sale_state = 0 + + + + + + + + + + + + INSERT INTO lease_product_machine ( + shop_id, product_id, user, type, coin, miner, theory_power, + computing_power, theory_income, unit, + power_dissipation, income_rate, cost, price, sale_state, + state, del,max_lease_days + ) + VALUES + + ( + #{item.shopId}, #{item.productId}, #{item.user}, #{item.type}, #{item.coin}, #{item.miner}, + #{item.theoryPower}, #{item.computingPower}, #{item.theoryIncome}, #{item.unit}, #{item.powerDissipation}, #{item.incomeRate}, #{item.cost}, + #{item.price}, #{item.saleState}, #{item.state}, #{item.del}, #{item.maxLeaseDays} + ) + + ON DUPLICATE KEY UPDATE + shop_id = VALUES(shop_id), + product_id = VALUES(product_id), + `type` = VALUES(`type`), + theory_power = VALUES(theory_power), + computing_power = VALUES(computing_power), + theory_income = VALUES(theory_income), + unit = VALUES(unit), + power_dissipation = VALUES(power_dissipation), + income_rate = VALUES(income_rate), + cost = VALUES(cost), + price = VALUES(price), + sale_state = VALUES(sale_state), + `state` = VALUES(`state`), + del = VALUES(del), + max_lease_days = VALUES(max_lease_days) + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductMapper.xml new file mode 100644 index 0000000..60cafc1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseProductMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + id, `name`, image,`state`,unit, `type`, description, create_time, update_time, del + + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopAddressConfigMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopAddressConfigMapper.xml new file mode 100644 index 0000000..d71e433 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopAddressConfigMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + id, user_id, address, shop_id + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopConfigMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopConfigMapper.xml new file mode 100644 index 0000000..fea04a5 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopConfigMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + id, shop_id, product_id, pay_coin, pay_type, pay_address, create_time, update_time, del + + + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopMapper.xml new file mode 100644 index 0000000..0bedd45 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShopMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + id, user_email, name, image, description, create_time, update_time, del + + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShoppingCartInfoMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShoppingCartInfoMapper.xml new file mode 100644 index 0000000..d3e61ac --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShoppingCartInfoMapper.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + id, cart_id, product_id, product_machine_id, create_time, update_time + + + + + + DELETE FROM lease_shopping_cart_info + WHERE cart_id = #{cartId} + + AND ( + + (product_id = #{item.productId} AND product_machine_id = #{item.machineId}) + + ) + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShoppingCartMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShoppingCartMapper.xml new file mode 100644 index 0000000..9dfbcb1 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseShoppingCartMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + id, user_id, create_time, update_time + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserMapper.xml new file mode 100644 index 0000000..05847ad --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + id, user_id, password, create_time, update_time + + + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserOwnedProductMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserOwnedProductMapper.xml new file mode 100644 index 0000000..6de9039 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserOwnedProductMapper.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + id, address, product_machine_id, order_item_id, start_time, end_time, purchased_computing_power, status, type, create_time, update_time, del + + + + + + + UPDATE lease_user_owned_product + SET + current_income = + + WHEN #{item.id} THEN #{item.currentIncome} + , + current_usdt_income = + + WHEN #{item.id} THEN #{item.currentUsdtIncome} + + WHERE id IN + + #{item.id} + + + diff --git a/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserWalletDataMapper.xml b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserWalletDataMapper.xml new file mode 100644 index 0000000..9c52063 --- /dev/null +++ b/m2pool-modules/m2pool-lease/src/main/resources/mapper/lease/LeaseUserWalletDataMapper.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + id, user_id, from_address, balance, to_address, from_symbol, from_chain, to_symbol, to_chain, qrcode, create_time, update_time, del + + + + + + + + + +