Compare commits

..

22 Commits

Author SHA1 Message Date
yyb
261cbe38d2 update m2pool 注销账号删除api,只读页,挖矿账号等信息实现 2026-01-05 15:47:11 +08:00
yyb
dccbb10512 update m2pool 注销账号后新注册修改 2026-01-04 17:31:13 +08:00
yyb
89bf55b4ce update m2pool 新增注销账号功能 2026-01-04 13:55:27 +08:00
yyb
5bd7f61c55 update m2pool 新增注销账号功能 2026-01-04 11:55:23 +08:00
yyb
c791d4fc17 update m2pool 新增注销账号功能 2025-12-31 10:01:46 +08:00
yyb
d5af03e5a4 update m2pool 新增注销账号功能 2025-12-30 09:55:32 +08:00
yyb
1e7c2099bf update m2pool 新增注销账号功能 2025-12-30 09:53:41 +08:00
yyb
b210b114d5 update 租赁系统1.1.0 新增谷歌验证相关代码 2025-12-26 10:07:49 +08:00
yyb
379e102ab4 update 租赁系统1.1.0 新增登录系统,准备迁移该模块为独立模块 2025-12-25 11:01:54 +08:00
yyb
709681d7e5 update 租赁系统1.1.0 新增登录系统,准备迁移该模块为独立模块 2025-12-25 10:03:41 +08:00
yyb
bc2f76662c update 租赁系统1.1.0 新增充值,支付,提现 日志账本系统 2025-12-23 10:27:50 +08:00
yyb
4e23775014 update 租赁系统1.1.0 钱包地址参数加密,gpu矿机新增到订单流程测试修改等 2025-12-22 09:43:40 +08:00
yyb
f1896bc1ae update 租赁系统1.1.0 钱包地址参数加密,gpu矿机新增到订单流程测试修改等 2025-12-22 09:42:57 +08:00
yyb
6250442c77 update 租赁系统1.1.0 bug 测试修改 2025-12-16 11:33:38 +08:00
yyb
6983e8657b update 租赁系统1.1.0新版本业务完成 2025-12-12 15:13:53 +08:00
yyb
cdc0cc8212 update 租赁系统订单相关接口,tcp客户端相关业务 2025-12-05 17:46:29 +08:00
yyb
7cd19a2338 update 租赁系统业务完成,其他矿池挖矿机器租赁业务开始 2025-11-20 11:01:34 +08:00
yyb
a7a2b73d00 update 租赁系统业务完成,其他矿池挖矿机器租赁业务开始 2025-11-19 16:39:25 +08:00
yyb
9c0cc31a64 update 租赁系统业务完成(待测试) 2025-11-18 11:13:19 +08:00
yyb
20fcfa778e update 租赁系统11-14 一订单对应多个卖家需求完成 2025-11-14 11:41:39 +08:00
yyb
0fff57492e update 邮箱样式微调 2025-11-07 16:35:02 +08:00
yyb
0dfc209485 update 邮箱 2025-11-04 14:59:06 +08:00
307 changed files with 16649 additions and 1843 deletions

438
lease_v1.0.0.sql Normal file
View File

@@ -0,0 +1,438 @@
-- 第一版租赁系统 只支持自营矿池挖矿
-- -- 创建用户表,存储用户基本信息
-- CREATE TABLE IF NOT EXISTS `lease_user` (
-- `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
-- `user_id` VARCHAR(50) NOT NULL UNIQUE COMMENT '用户id(邮箱)',
-- `password` VARCHAR(64) NOT NULL COMMENT '密码',
-- `address` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '钱包地址',
-- `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-- `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
--
--
-- 创建店铺表
CREATE TABLE IF NOT EXISTS `lease_shop` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '店铺ID',
`user_email` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '店铺拥有者邮箱',
`name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '店铺名称',
`image` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '店铺图片路径',
`state` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '商铺状态 0 待审核 1 审核通过(店铺开启) 2 店铺关闭',
`description` TEXT COMMENT '店铺描述',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段',
UNIQUE INDEX idx_email (user_email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店铺表';
-- 创建店铺--店铺支持收款地址配置表
CREATE TABLE IF NOT EXISTS `lease_shop_config` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '配置ID',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`product_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品 ID (商品id为0代表适用于店铺中所有商品) ------- 该字段删除',
`pay_coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd',
`chain` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖家地址链名称',
`pay_coin_image` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '支付币种图标',
`pay_type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '币种类型 0 虚拟币 1 稳定币',
`pay_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖方对应收款钱包',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`qrcode` LONGTEXT COMMENT '卖方对应收款钱包二维码',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店铺支持收款地址配置表';
-- 用于店铺收款钱包配置 时下拉选择链和币
CREATE TABLE IF NOT EXISTS `lease_chain_coin_config` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '配置ID',
`coin_full` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种全称',
`coin_image` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '支付币种图标',
`coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd',
`chain` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '链名称'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店铺支持收款地址配置表(店铺钱包)';
-- 创建商品表,存储挖矿机器和算力套餐信息
CREATE TABLE IF NOT EXISTS `lease_product` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '商品 ID',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '商品名称',
`image` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品图片路径',
`algorithm` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '算法',
`sale_number` INT NOT NULL DEFAULT 0 COMMENT '销售机器数(租赁出一次算一个销售数)',
`total_machine_number` INT NOT NULL DEFAULT 0 COMMENT '当前总矿机数(包含已售出矿机数)',
`max_price` DECIMAL(30, 18) NOT NULL DEFAULT 0.000000 COMMENT '商品下机器最大价格',
`min_price` DECIMAL(30, 18) NOT NULL DEFAULT 0.000000 COMMENT '商品下机器最小价格',
`coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT ' 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona',
`coin_full_name` VARCHAR(32) NOT NULL DEFAULT '' COMMENT ' 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona',
`type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '商品类型0 矿机 1 算力 ',
`state` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '上下架状态0 上架1 下架',
`description` TEXT COMMENT '商品描述',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
CREATE TABLE IF NOT EXISTS `lease_product_machine` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`product_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品 ID',
`user` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '挖矿机器 对应的矿工账号',
`type` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '矿机型号',
`coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT ' 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona',
`miner` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '挖矿机器编号',
`theory_power` DECIMAL(32, 6) NOT NULL DEFAULT 0.000000 COMMENT '商品机器单机算力(卖方手动填写)理论算力 (如果实时变化可不要这个字段)',
`computing_power` DECIMAL(32, 6) NOT NULL DEFAULT 0.000000 COMMENT '实际算力(计算得到,商家不能够自己添加和修改) (如果实时变化可不要这个字段)',
`theory_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.00 COMMENT '单机理论收益单位usdt每日:根据添加机器时,实时计算的收益值)',
-- `actual_income` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '单机预估实际收益(每日)',
`unit` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '算力单位 GH/s TH/s PH/s',
-- `electricity_bill` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '电费 单位 $/度 (该字段目前未使用,可删除)',
`max_lease_days` INT NOT NULL DEFAULT 7 COMMENT '矿机租售天数',
`power_dissipation` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '功耗 单位kw/h',
`income_rate` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 DEFAULT 0.00 COMMENT '收益率',
`cost` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '默认单价单位$ [ 功耗 * 电费 * 24 * (1 + 收益率) ]',
`price` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '实际单价',
`sale_state` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '售出状态 0未售出 1已售出 2售出中(已下单情况该状态已不存在)',
`state` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '上下架状态0 上架1 下架',
`del` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除字段',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
KEY `idx_user_coin_miner` (`user`, `coin`, `miner`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表对应的物品机器表';
CREATE TABLE IF NOT EXISTS `lease_product_machine_price` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
`product_machine_id` BIGINT NOT NULL DEFAULT 0 COMMENT '矿机id',
`price` DECIMAL(30, 18) NOT NULL DEFAULT 0.00 COMMENT '实际单价',
`coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '价值单位',
`chain` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '',
`del` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表对应的物品机器表';
-- 创建已购机器表(租赁表)
CREATE TABLE IF NOT EXISTS `lease_user_owned_product` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`user_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户id(邮箱)',
`product_machine_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品对应的机器id',
`user` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '挖矿机器 对应的矿工账号',
`order_id` BIGINT NOT NULL DEFAULT 0 COMMENT '订单 ID',
`miner` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '挖矿机器编号',
`coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona',
`estimated_end_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '预估商品结束时的总收益',
`estimated_end_usdt_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '预估商品结束时的总收益 单价usdt',
`current_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '当前收益(根据购买机器到现在的平均算力计算得到)单位 币种',
`current_usdt_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '当前收益(根据购买机器到现在的平均算力计算得到----非实时单位usdt',
`settle_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '待结算收益(用于存储某天还未支付情况下的收益)',
`settle_usdt_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '待结算收益 (用于存储某天还未支付情况下的收益----非实时)单位usdt',
`order_item_id` BIGINT NOT NULL DEFAULT 0 COMMENT '订单明细 ID关联订单中的购买记录',
`address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖方对应收款钱包',
`start_time` DATETIME NOT NULL COMMENT '商品开始使用时间(购买当天24点生效)',
`end_time` DATETIME NOT NULL COMMENT '商品使用结束时间',
`purchased_computing_power` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '购买算力时实时算力,当 type 为 1 时有效',
`status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '商品状态0 表示运行中1 表示已过期 ',
`type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '商品类型0 表示挖矿机器1 表示算力套餐',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '购买时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户拥有商品详情表';
-- 创建购物车表,存储用户添加到购物车的商品信息
CREATE TABLE IF NOT EXISTS `lease_shopping_cart` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '购物车 ID',
`user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '用户 ID(邮箱)',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='购物车表';
-- 创建购物车详情表
CREATE TABLE IF NOT EXISTS `lease_shopping_cart_info` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`cart_id` BIGINT NOT NULL DEFAULT 0 COMMENT '购物车ID',
`product_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品 ID',
`product_machine_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品机器ID',
`lease_time` int NOT NULL DEFAULT 1 COMMENT '租赁天数',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='购物车详情表';
-- 创建订单表,存储订单基本信息
CREATE TABLE IF NOT EXISTS `lease_order_info` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '订单 ID',
`order_number` VARCHAR(50) NOT NULL DEFAULT '' UNIQUE COMMENT '订单号',
`user_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户id(邮箱)',
`total_price` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '订单总价',
`status` TINYINT(1) NOT NULL DEFAULT 7 COMMENT '订单状态0 表示待支付1 表示全部已支付2 表示已取消 3售后状态 4已退款 5 支付已超时 6 支付中 ( 目前只有这三种状态 7 订单进行中 8 订单已完成 9 余额不足,订单已取消) 10 部分已支付',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
-- 创建订单明细表,存储订单中的商品明细
CREATE TABLE IF NOT EXISTS `lease_order_item` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '订单明细 ID',
`order_id` BIGINT NOT NULL DEFAULT 0 COMMENT '订单 ID',
`user_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户id(邮箱)',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`product_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品 ID',
`product_machine_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商品对应的机器id',
`user` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '挖矿机器 对应的矿工账号',
`miner` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '挖矿机器编号',
`name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '商品名称',
`theory_income` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '单机理论收益',
`lease_time` INT NOT NULL DEFAULT 0 COMMENT '租赁天数',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '0 租约已过期 1 租约生效中 2 等待租约生效 ',
`pay_coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd',
`coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona',
`address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖方对应收款钱包',
`chain` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖家地址链名称',
`symbol` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖家地址支付币种',
`from_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '买方对应收款钱包(删除,支付时用户必定存在和卖家收款地址相同币种和链的地址,代码中已做处理)',
`from_chain` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '买方地址链名称(删除)',
`from_symbol` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '买方地址支付币种(删除)',
`image` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品图片路径',
`quantity` INT NOT NULL DEFAULT 1 COMMENT '商品数量(弃用)',
`price` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '商品价格',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';
-- 创建支付记录表,模拟支付信息
CREATE TABLE IF NOT EXISTS `lease_payment_record` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '支付记录 ID',
`order_id` BIGINT NOT NULL DEFAULT 0 UNIQUE COMMENT '订单 ID',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`product_id` BIGINT COMMENT '商品 ID后续删除',
`pay_coin` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd',
`amount` DECIMAL(40, 6) NOT NULL DEFAULT 0.000000 COMMENT '需支付总金额',
`pay_amount` DECIMAL(40, 6) NOT NULL DEFAULT 0.000000 COMMENT '已支付金额',
`status` TINYINT(1) NOT NULL DEFAULT 7 COMMENT '支付状态0支付失败 1支付成功--全部货款已支付 2待支付 5支付已超时 6 支付中( 目前只有这三种状态 7 订单进行中 8 订单已完成 9 余额不足,订单已取消) 10支付成功--已支付部分货款 ',
`from` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '买家钱包',
`hash` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '交易id 交易成功后生成',
`pay_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖方对应收款钱包',
`qrcode` LONGTEXT COMMENT '支付地址二维码',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
KEY `orderid_shopid` (`order_id`,`shop_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付记录表';
-- -- 创建商品收益表,存储每个商品对应的收益信息
-- CREATE TABLE IF NOT EXISTS `lease_product_income` (
-- `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '收益记录 ID',
-- `user_owned_product_id` BIGINT NOT NULL DEFAULT 0 COMMENT '用户拥有商品详情 ID关联 lease_user_owned_product 表',
-- `estimated_end_income` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '预估商品结束时的总收益',
-- `current_actual_income` DECIMAL(18, 2) NOT NULL DEFAULT 0.00 COMMENT '当前实际总收益',
-- `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
-- `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间'
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品收益表';
--
--
-- -- 删除
-- CREATE TABLE IF NOT EXISTS `lease_shop_address_config` (
-- `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
-- `user_id` varchar(64) NOT NULL COMMENT '买方账号id邮箱',
-- `address` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '卖方收款钱包 每个买方对应一个地址(自动生成匹配)',
-- `shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
-- UNIQUE KEY `idx_user_address_shop` (`user_id`,`address`,shop_id)
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='矿池nexa机器实时平均算力';
-- 官方自动生成地址存储表
CREATE TABLE IF NOT EXISTS `lease_auto_address` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`address` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '钱包地址',
`from_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`from_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 未使用 1 已使用 2 钱包已过期',
`bind_user` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '绑定者邮箱',
UNIQUE INDEX `idx_address_from_symbol_from_chain` (`address`, `from_symbol`, `from_chain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='官方自动生成地址表';
-- 个人钱包资料表
CREATE TABLE IF NOT EXISTS `lease_user_wallet_data` (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`user_id` VARCHAR(50) NOT NULL UNIQUE COMMENT '用户id(邮箱)',
`queue_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '钱包唯一id(用于充值功能)',
`from_address` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '充值钱包地址(我们提供)',
`balance` DECIMAL(40, 6) NOT NULL DEFAULT 0.000000 COMMENT '余额',
`blocked_balance` DECIMAL(40, 6) NOT NULL DEFAULT 0.000000 COMMENT '冻结余额(用户购买机器完成租约所需金额)',
`to_address` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '收款钱包地址(用户自己填写)',
`from_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`from_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`to_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`to_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`qrcode` LONGTEXT COMMENT '支付地址二维码',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段' ,
UNIQUE INDEX `idx_user_from_info` (`user_id`, `from_address`,`from_symbol`, `from_chain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户钱包信息表(个人钱包)';
-- 支付记录表
CREATE TABLE IF NOT EXISTS lease_pay_record_message (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`queue_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '消息ID',
`from_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '买家充值地址',
`to_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖家充值地址',
`order_number` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '订单号(方便查询,基本未使用)',
`order_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '订单号',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`user_id` VARCHAR(50) NOT NULL COMMENT '买方邮箱',
`block_amount`DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '买方钱包冻结金额',
`amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '理论支付金额',
`real_amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.000000 COMMENT '实际支付金额',
`need_amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.000000 COMMENT '实际应支付金额(支付是一天一次,根据一天内预估算力和实际算力差值计算得来)',
`block_height` BIGINT NOT NULL DEFAULT 0 COMMENT '报块高度',
`from_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`from_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`to_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`to_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`tx_hash` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '交易id',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` tinyint(1) NOT NULL DEFAULT 2 COMMENT '0 支付失败 1 支付成功 2 支付中 3 校验失败 4 发送支付消息失败',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付记录表';
CREATE TABLE IF NOT EXISTS lease_pay_record_message_info (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`queue_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '消息ID',
`from_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '买家充值地址',
`to_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '卖家充值地址',
`order_number` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '订单号(方便查询,基本未使用)',
`order_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '订单号',
`shop_id` BIGINT NOT NULL DEFAULT 0 COMMENT '商铺ID',
`user_id` VARCHAR(50) NOT NULL COMMENT '买方邮箱',
`block_amount`DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '买方钱包冻结金额',
`amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '理论支付金额',
`real_amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.000000 COMMENT '实际支付金额',
`need_amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.000000 COMMENT '实际应支付金额(支付是一天一次,根据一天内预估算力和实际算力差值计算得来)',
`block_height` BIGINT NOT NULL DEFAULT 0 COMMENT '报块高度',
`from_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`from_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`to_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`to_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`tx_hash` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '交易id',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` tinyint(1) NOT NULL DEFAULT 2 COMMENT '0 支付失败 1 支付成功 2 支付中 3 校验失败 4 发送支付消息失败',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付记录详情表(订单对应每日应支付金额)';
-- 充值记录返回表
CREATE TABLE IF NOT EXISTS lease_pay_recharge_message (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`queue_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '消息ID',
`address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '充值地址',
`amount` DECIMAL(40, 6) NOT NULL DEFAULT 0.00000000 COMMENT '支付金额',
`chain` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '链名称',
`symbol` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '币种',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '充值时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '0 充值失败 1 充值成功 2 充值中',
`tx_hash` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '交易id',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段' ,
UNIQUE INDEX `tx_hash_key` (`tx_hash`);
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='充值记录表';
-- 提现记录表
CREATE TABLE IF NOT EXISTS lease_pay_withdraw_message (
`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`queue_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '消息ID',
`from_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '用户充值地址',
`to_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '提现地址(用户自定义)',
`amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '提现金额',
`from_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`from_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`to_symbol` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '币种名称',
`service_charge` DECIMAL(40, 6) NOT NULL DEFAULT 0.000000 COMMENT '提现费用',
`to_chain` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链名称',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '充值时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` tinyint(1) NOT NULL DEFAULT 2 COMMENT '0 提现失败 1 提现成功 2 提现中',
`tx_hash` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '交易id',
`del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='提现记录表';
CREATE TABLE IF NOT EXISTS `nexa_real_power` (
`id` int NOT NULL AUTO_INCREMENT,
`user` varchar(64) NOT NULL COMMENT "挖矿账户",
`miner` varchar(64) NOT NULL COMMENT "矿工编号",
`date` datetime NOT NULL,
`power` decimal(32,6) NOT NULL COMMENT "实时算力单位 MH/S",
PRIMARY KEY (`id`),
UNIQUE KEY `user_miner` (`user`,`miner`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='矿机实时算力';
CREATE TABLE IF NOT EXISTS `grs_real_power` (
`id` int NOT NULL AUTO_INCREMENT,
`user` varchar(64) NOT NULL COMMENT "挖矿账户",
`miner` varchar(64) NOT NULL COMMENT "矿工编号",
`date` datetime NOT NULL,
`power` decimal(32,6) NOT NULL COMMENT "实时算力单位 MH/S",
PRIMARY KEY (`id`),
UNIQUE KEY `user_miner` (`user`,`miner`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='矿机实时算力';
CREATE TABLE IF NOT EXISTS `mona_real_power` (
`id` int NOT NULL AUTO_INCREMENT,
`user` varchar(64) NOT NULL COMMENT "挖矿账户",
`miner` varchar(64) NOT NULL COMMENT "矿工编号",
`date` datetime NOT NULL,
`power` decimal(32,6) NOT NULL COMMENT "实时算力单位 MH/S",
PRIMARY KEY (`id`),
UNIQUE KEY `user_miner` (`user`,`miner`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='矿机实时算力';
CREATE TABLE IF NOT EXISTS `rxd_real_power` (
`id` int NOT NULL AUTO_INCREMENT,
`user` varchar(64) NOT NULL COMMENT "挖矿账户",
`miner` varchar(64) NOT NULL COMMENT "矿工编号",
`date` datetime NOT NULL,
`power` decimal(32,6) NOT NULL COMMENT "实时算力单位 MH/S",
PRIMARY KEY (`id`),
UNIQUE KEY `user_miner` (`user`,`miner`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='矿机实时算力';
ALTER TABLE lease_product MODIFY COLUMN `max_price` DECIMAL(30, 18) NOT NULL DEFAULT 0.000000 COMMENT '商品下机器最大价格';
ALTER TABLE lease_product MODIFY COLUMN `min_price` DECIMAL(30, 18) NOT NULL DEFAULT 0.000000 COMMENT '商品下机器最小价格';
ALTER TABLE lease_product_machine MODIFY COLUMN `theory_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '单机理论收益单位usdt每日:根据添加机器时,实时计算的收益值)';
ALTER TABLE lease_user_owned_product MODIFY COLUMN `estimated_end_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '预估商品结束时的总收益';
ALTER TABLE lease_user_owned_product MODIFY COLUMN `estimated_end_usdt_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '预估商品结束时的总收益 单价usdt';
ALTER TABLE lease_user_owned_product MODIFY COLUMN `current_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '当前收益(根据购买机器到现在的平均算力计算得到)单位 币种';
ALTER TABLE lease_user_owned_product MODIFY COLUMN `current_usdt_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '当前收益(根据购买机器到现在的平均算力计算得到----非实时单位usdt';
ALTER TABLE lease_user_owned_product MODIFY COLUMN `settle_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '待结算收益(用于存储某天还未支付情况下的收益)';
ALTER TABLE lease_user_owned_product MODIFY COLUMN `settle_usdt_income` DECIMAL(32, 18) NOT NULL DEFAULT 0.000000 COMMENT '待结算收益 (用于存储某天还未支付情况下的收益----非实时)单位usdt';
ALTER TABLE lease_pay_record_message MODIFY COLUMN `block_amount`DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '买方钱包冻结金额';
ALTER TABLE lease_pay_record_message MODIFY COLUMN `amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '理论支付金额';
ALTER TABLE lease_pay_record_message MODIFY COLUMN `real_amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.000000 COMMENT '实际支付金额';
ALTER TABLE lease_pay_record_message MODIFY COLUMN `need_amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.000000 COMMENT '实际应支付金额(支付是一天一次,根据一天内预估算力和实际算力差值计算得来)';
ALTER TABLE lease_pay_withdraw_message MODIFY COLUMN `amount` DECIMAL(40, 18) NOT NULL DEFAULT 0.00000000 COMMENT '提现金额';
ALTER TABLE lease_pay_recharge_message ADD COLUMN `block_height` BIGINT NOT NULL DEFAULT 0 COMMENT '报块高度';
ALTER TABLE lease_pay_recharge_message ADD COLUMN `from_address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '充值来源地址(用户自己的钱包)';
ALTER TABLE lease_pay_withdraw_message ADD COLUMN `block_height` BIGINT NOT NULL DEFAULT 0 COMMENT '报块高度';
ALTER TABLE lease_order_item ADD COLUMN `already_pay_amount` DECIMAL(32, 18) NOT NULL DEFAULT 0.00 COMMENT '已支付总金额(每天加一)';
ALTER TABLE lease_order_item ADD COLUMN `already_pay_real_amount` DECIMAL(32, 18) NOT NULL DEFAULT 0.00 COMMENT '已支付实际总金额';
ALTER TABLE lease_order_item ADD COLUMN `settle_pay_real_amount` DECIMAL(32, 18) NOT NULL DEFAULT 0.00 COMMENT '当日待确认支付金额';
ALTER TABLE lease_order_info ADD COLUMN `fee` DECIMAL(32, 8) NOT NULL DEFAULT 0.00 COMMENT '订单手续费';

View File

@@ -0,0 +1,25 @@
package com.m2pool.system.api;
import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.constant.ServiceNameConstants;
import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.factory.RemotePoolFallbackFactory;
import com.m2pool.system.api.factory.RemoteUserFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* @Description 矿池服务
* @Date 2026/1/5 10:15
* @Author yyb
*/
@FeignClient(contextId = "remotePoolService",value = ServiceNameConstants.POOL_SERVICE,fallbackFactory = RemotePoolFallbackFactory.class)
public interface RemotePoolService {
@PostMapping("/user/deleteUserDataAndPutTemporaryTable")
R<Boolean> deleteUserDataAndPutTemporaryTable();
}

View File

@@ -3,6 +3,7 @@ package com.m2pool.system.api;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.constant.SecurityConstants; import com.m2pool.common.core.constant.SecurityConstants;
import com.m2pool.common.core.constant.ServiceNameConstants; import com.m2pool.common.core.constant.ServiceNameConstants;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.SysUser; import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.entity.SysUserLeveDate; import com.m2pool.system.api.entity.SysUserLeveDate;
import com.m2pool.system.api.factory.RemoteUserFallbackFactory; import com.m2pool.system.api.factory.RemoteUserFallbackFactory;
@@ -82,7 +83,7 @@ public interface RemoteUserService {
* @return 结果 * @return 结果
*/ */
@PostMapping("/user/profile/checkGoogleCode") @PostMapping("/user/profile/checkGoogleCode")
public R<Boolean> checkGoogleCode(@RequestBody Long code, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<Boolean> checkGoogleCode(@RequestBody CloseAccountVo closeAccountVo, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/** /**
* 获取客服列表 * 获取客服列表
@@ -92,4 +93,12 @@ public interface RemoteUserService {
@GetMapping("/user/getCSList") @GetMapping("/user/getCSList")
public R<List<SysUser>> getCSList(); public R<List<SysUser>> getCSList();
/**
* 关闭
*
* @return 结果
*/
@PostMapping("/user/closeAccount")
R<Boolean> closeAccount(@RequestBody SysUser sysUser);
} }

View File

@@ -0,0 +1,32 @@
package com.m2pool.system.api.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CloseAccountVo {
@Email
private String userEmail;
/**
* 谷歌验证器验证码
*/
@ApiModelProperty(value = "谷歌验证码",required = true)
public long gCode;
/**
* 邮箱验证码
*/
@NotBlank
@ApiModelProperty(value = "邮箱验证码",required = true)
public String eCode;
}

View File

@@ -0,0 +1,31 @@
package com.m2pool.system.api.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
/**
* @Description 用户矿机在离线的数量
* @Date 2024/6/12 16:13
* @Author dy
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmailTemplateEntity implements Serializable {
/** 邮箱 */
private String email;
/** 主题 */
private String subject;
/** 模版名称 */
private String templateName;
/** 填充到模版的数据 */
private Map<String,Object> data;
}

View File

@@ -0,0 +1,36 @@
package com.m2pool.system.api.factory;
import com.m2pool.common.core.Result.R;
import com.m2pool.system.api.RemotePoolService;
import com.m2pool.system.api.RemoteUserService;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.entity.SysUserLeveDate;
import com.m2pool.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description 矿池服务
* @Date 2026/1/5 10:17
* @Author yyb
*/
@Component
public class RemotePoolFallbackFactory implements FallbackFactory<RemotePoolService> {
private static final Logger log = LoggerFactory.getLogger(RemotePoolFallbackFactory.class);
@Override
public RemotePoolService create(Throwable cause) {
log.error("矿池服务调用失败:{}",cause.getMessage());
return new RemotePoolService(){
@Override
public R<Boolean> deleteUserDataAndPutTemporaryTable() {
return R.fail("注销账户失败," + cause.getMessage());
}
};
}
}

View File

@@ -2,6 +2,7 @@ package com.m2pool.system.api.factory;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.system.api.RemoteUserService; import com.m2pool.system.api.RemoteUserService;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.SysUser; import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.entity.SysUserLeveDate; import com.m2pool.system.api.entity.SysUserLeveDate;
import com.m2pool.system.api.model.LoginUser; import com.m2pool.system.api.model.LoginUser;
@@ -60,7 +61,7 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
} }
@Override @Override
public R<Boolean> checkGoogleCode(Long code, String source) { public R<Boolean> checkGoogleCode(CloseAccountVo closeAccountVo, String source) {
return R.fail("谷歌验证器校验失败:" + cause.getMessage()); return R.fail("谷歌验证器校验失败:" + cause.getMessage());
} }
@@ -69,6 +70,11 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
return R.fail("客服列表获取失败:" + cause.getMessage()); return R.fail("客服列表获取失败:" + cause.getMessage());
} }
@Override
public R<Boolean> closeAccount(SysUser sysUser) {
return R.fail("注销用户失败:" + cause.getMessage());
}
}; };
} }
} }

View File

@@ -12,7 +12,6 @@
<artifactId>m2pool-auth</artifactId> <artifactId>m2pool-auth</artifactId>
<description>认证模块:登录认证、权限鉴定等</description> <description>认证模块:登录认证、权限鉴定等</description>
<dependencies> <dependencies>
<!-- SpringCloud Alibaba Nacos --> <!-- SpringCloud Alibaba Nacos -->
@@ -71,6 +70,19 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -1,10 +1,14 @@
package com.m2pool.auth; package com.m2pool.auth;
import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients; import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@EnableCustomConfig
@EnableCustomSwagger2
@EnableM2PoolFeignClients @EnableM2PoolFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class M2PoolAuthApplication{ public class M2PoolAuthApplication{

View File

@@ -10,6 +10,7 @@ import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.common.security.auth.AuthUtil; import com.m2pool.common.security.auth.AuthUtil;
import com.m2pool.common.security.service.TokenService; import com.m2pool.common.security.service.TokenService;
import com.m2pool.common.security.utils.SecurityUtils; import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.EmailTemplateEntity; import com.m2pool.system.api.entity.EmailTemplateEntity;
import com.m2pool.system.api.model.LoginUser; import com.m2pool.system.api.model.LoginUser;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@@ -86,6 +87,10 @@ public class TokenController {
return maliService.resetPwdCode(entity); return maliService.resetPwdCode(entity);
} }
@PostMapping("updatePwdCode") @PostMapping("updatePwdCode")
public R<?> updatePwdCode() public R<?> updatePwdCode()
{ {
@@ -93,6 +98,29 @@ public class TokenController {
} }
/**
* 注销账户
* @param closeAccountVo
* @return
*/
@PostMapping("/closeAccount")
@ApiOperation(value = "用户注销")
public R<?> closeAccount(@RequestBody @Valid CloseAccountVo closeAccountVo){
return sysLoginService.closeAccount(closeAccountVo);
}
/**
* 发送注销账户邮件
* @param emailCodeVo
* @return
*/
@PostMapping("/sendCloseAccount")
@ApiOperation(value = "发送注销用户邮箱验证码")
public R<?> sendCloseAccount(@RequestBody @Valid GetLoginEmailCodeEntity emailCodeVo){
return maliService.sendCloseAccount(emailCodeVo);
}
@GetMapping("hello") @GetMapping("hello")
public R<?> hello() public R<?> hello()
{ {

View File

@@ -4,6 +4,9 @@ import com.m2pool.auth.entity.GetEmailCodeEntity;
import com.m2pool.auth.entity.GetLoginEmailCodeEntity; import com.m2pool.auth.entity.GetLoginEmailCodeEntity;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.system.api.entity.EmailTemplateEntity; import com.m2pool.system.api.entity.EmailTemplateEntity;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
/** /**
* @Description TODO * @Description TODO
@@ -73,4 +76,19 @@ public interface MailService {
public R<?> updatePwdCode(); public R<?> updatePwdCode();
/**
* 账号注销验证码
* @param emailCodeVo
* @return
*/
R<?> sendCloseAccount(GetLoginEmailCodeEntity emailCodeVo);
/**
* 账号注销邮箱验证码 消息格式设置
* @param to
* @param code
*/
void sendCloseAccountMailMessage(String to, String code);
} }

View File

@@ -1,7 +1,6 @@
package com.m2pool.auth.service; package com.m2pool.auth.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
import com.m2pool.auth.entity.*; import com.m2pool.auth.entity.*;
import com.m2pool.common.core.RedisTransKey; import com.m2pool.common.core.RedisTransKey;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
@@ -12,6 +11,7 @@ import com.m2pool.common.core.enums.UserStatus;
import com.m2pool.common.core.exception.ServiceException; import com.m2pool.common.core.exception.ServiceException;
import com.m2pool.common.core.text.Convert; import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.DateUtils; import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.GoogleAuthenticator;
import com.m2pool.common.core.utils.ServletUtils; import com.m2pool.common.core.utils.ServletUtils;
import com.m2pool.common.core.utils.StringUtils; import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.utils.ip.IpUtils; import com.m2pool.common.core.utils.ip.IpUtils;
@@ -22,16 +22,15 @@ import com.m2pool.common.security.service.TokenService;
import com.m2pool.common.security.utils.SecurityUtils; import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.system.api.RemoteLogService; import com.m2pool.system.api.RemoteLogService;
import com.m2pool.system.api.RemoteUserService; import com.m2pool.system.api.RemoteUserService;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.SysLogininfor; import com.m2pool.system.api.entity.SysLogininfor;
import com.m2pool.system.api.entity.SysUser; import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.model.LoginUser; import com.m2pool.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Update;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.transaction.annotation.Transactional;
import javax.validation.Valid;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -562,5 +561,55 @@ public class SysLoginService {
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER); remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
} }
public R<?> closeAccount(CloseAccountVo closeAccountVo){
String email = closeAccountVo.getUserEmail();
String emailCode = closeAccountVo.getECode();
// 用户名或密码为空 错误
if (StringUtils.isBlank(email))
{
recordLogininfor(email, Constants.LOGIN_FAIL, "邮箱必须填写");
throw new ServiceException("邮箱必须填写");
}
if(!StringUtils.isBlank(email)){
if(!email.matches(EMAIL_REGEX)){
throw new ServiceException("邮箱格式错误");
}
}else {
throw new ServiceException("邮箱为必填项");
}
String closeAccountKey = RedisTransKey.getCloseAccountKey(email);
System.out.println("redis 的 key"+closeAccountKey);
//校验谷歌验证码和邮箱验证码
if(redisService.hasKey(closeAccountKey)){
Object o = redisService.getCacheObject(closeAccountKey);//user:emailCode:email
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
//验证验证码
if(emailCode.equals(emailCodeEntity.getEmailCode())){
//不做处理 进入后续登录流程
}else {
throw new ServiceException("验证码错误");
}
}else {
throw new ServiceException("验证码未获取或已过期,请重新获取验证码");
}
R<Boolean> booleanR1 = remoteUserService.checkGoogleCode(closeAccountVo, SecurityConstants.INNER);
System.out.println("谷歌验证码"+booleanR1);
//if(booleanR1 == null || !booleanR1.getData()){
// throw new ServiceException("谷歌验证码错误");
//}
R<LoginUser> userInfo = remoteUserService.getUserInfo(SecurityUtils.getUsername(), SecurityConstants.INNER);
if (R.FAIL == userInfo.getCode()) {
throw new ServiceException("服务器请求失败请稍后再试");
}
SysUser sysUser = userInfo.getData().getSysUser();
sysUser.setDelFlag("2");
R<Boolean> booleanR = remoteUserService.closeAccount(sysUser);
if (R.FAIL == booleanR.getCode()) {
throw new ServiceException("服务器请求失败请稍后再试");
}
return booleanR;
}
} }

View File

@@ -556,4 +556,62 @@ public class MaliServiceImpl implements MailService {
} }
@Override
public R<?> sendCloseAccount(GetLoginEmailCodeEntity emailCodeVo) {
String email = SecurityUtils.getUsername();
if(StringUtils.isBlank(email)){
return R.fail("token解析失败");
}
//通过邮箱获取用户
R<LoginUser> userByEmail = remoteUserService.getUserInfo(email, SecurityConstants.INNER);
if(StringUtils.isNull(userByEmail.getData())){
return R.fail("token解析异常");
}
//判断用户是不是恶意刷邮箱,在规定时间内进行的
String closeAccountKey = RedisTransKey.getCloseAccountKey(email);
System.out.println("redis 的 key"+closeAccountKey);
if (redisService.hasKey(closeAccountKey)) {
Object o = redisService.getCacheObject(closeAccountKey);//user:updatePwdCode:email
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
if (emailCodeEntity.getTimes() >= 5) {
return R.fail("请求次数过多请10分钟后再试");
} else {
//这里就不去判断两次绑定的邮箱是不是一样的了,不排除第一次输入错了邮箱的情况
String emailCode = CodeUtils.creatCode(6);
emailCodeEntity.setEmailCode(emailCode);
emailCodeEntity.setTimes(emailCodeEntity.getTimes() + 1);
long overTime = redisService.getExpire(closeAccountKey);
redisService.setCacheObject(closeAccountKey, emailCodeEntity, overTime, TimeUnit.SECONDS
);
sendCloseAccountMailMessage(email, emailCodeEntity.getEmailCode());
}
} else {
String emailCode = CodeUtils.creatCode(6);
// 最多允许用户在10分钟内发送2次的邮箱验证
// 0s倒计时后用户可以再发送验证码但是间隔在10分钟内只能再发送1次
EmailCodeEntity emailCodeEntity = new EmailCodeEntity(
email, emailCode,1
);
//设置失效时间10分钟
redisService.setCacheObject(closeAccountKey, emailCodeEntity,
10L, TimeUnit.MINUTES
);
sendCloseAccountMailMessage(email, emailCodeEntity.getEmailCode());
}
return R.success("请求成功,注销账户邮箱验证码发送成功");
}
@Override
public void sendCloseAccountMailMessage(String to, String code) {
Map<String, Object> content = new HashMap<>();
content.put("code",code);
content.put("text","You are logging out of the user account. If this is not done by you, please ignore it. The verification code is valid for 10 minutes.");
EmailTemplateEntity entity = new EmailTemplateEntity(to,"Change password, email verification code","emailCode-en",content);
sendHtmlMailMessage(entity);
}
} }

View File

@@ -3,6 +3,9 @@ server:
# Spring # Spring
spring: spring:
mvc:
pathmatch:
matching-strategy: ant-path-matcher
#邮箱基本配置 #邮箱基本配置
mail: mail:
# 配置在limit_time内用户可以发送limit次验证码 # 配置在limit_time内用户可以发送limit次验证码

View File

@@ -27,7 +27,7 @@
style="position:relative; display:inline-flex; align-items:center; justify-content:center; margin-top:2vh; width:80%; max-width:300px; height:50px; border-radius:12px; background:#ffffff; border:3px solid #651EFE;"> style="position:relative; display:inline-flex; align-items:center; justify-content:center; margin-top:2vh; width:80%; max-width:300px; height:50px; border-radius:12px; background:#ffffff; border:3px solid #651EFE;">
<!-- 合并 th:style 属性 --> <!-- 合并 th:style 属性 -->
<span class="code-text js-code-text" data-default-code="4MKM6AX" th:text="${code}" <span class="code-text js-code-text" data-default-code="4MKM6AX" th:text="${code}"
style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; font-weight:800; font-size:24px; letter-spacing:0.18em; color:#111827;"></span> style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; font-weight:800; font-size:24px; letter-spacing:0.18em; color:#111827;margin:auto;"></span>
</div> </div>
</section> </section>

View File

@@ -15,6 +15,7 @@ public class RedisTransKey {
public static final String RedisAddCreditEmailCodeName="addCreditEmailCode"; public static final String RedisAddCreditEmailCodeName="addCreditEmailCode";
public static final String RedisResetPwdCodeName="restPwdCode"; public static final String RedisResetPwdCodeName="restPwdCode";
public static final String RedisUpdatePwdCodeName="updatePwdCode"; public static final String RedisUpdatePwdCodeName="updatePwdCode";
public static final String RedisCloseAccountName="closeAccount";
public static String setEmailKey(String key){ public static String setEmailKey(String key){
return RedisNameSpace+":"+RedisEmailCodeName+":"+key; return RedisNameSpace+":"+RedisEmailCodeName+":"+key;
@@ -39,6 +40,10 @@ public class RedisTransKey {
return RedisNameSpace+":"+RedisAddCreditEmailCodeName+":"+key; return RedisNameSpace+":"+RedisAddCreditEmailCodeName+":"+key;
} }
public static String setCloseAccountKey(String key){
return RedisNameSpace+":"+RedisCloseAccountName+":"+key;
}
public static String getEmailKey(String key){return setEmailKey(key);} public static String getEmailKey(String key){return setEmailKey(key);}
public static String getRootKey(String key){return setRootKey(key);} public static String getRootKey(String key){return setRootKey(key);}
public static String getTokenKey(String key){return setTokenKey(key);} public static String getTokenKey(String key){return setTokenKey(key);}
@@ -47,4 +52,8 @@ public class RedisTransKey {
public static String getUpdatePwdKey(String key){return setUpdatePwdKey(key);} public static String getUpdatePwdKey(String key){return setUpdatePwdKey(key);}
public static String getAddCreditEmailKey(String key){return setAddCreditEmailKey(key);} public static String getAddCreditEmailKey(String key){return setAddCreditEmailKey(key);}
public static String getCloseAccountKey(String key){return setCloseAccountKey(key);}
} }

View File

@@ -0,0 +1,15 @@
package com.m2pool.common.datasource.annotation;
import com.baomidou.dynamic.datasource.annotation.DS;
import java.lang.annotation.*;
/**
* 矿池数据库(只读)
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@DS("mining")
public @interface MiningDB {
}

View File

@@ -5,11 +5,19 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
@@ -19,13 +27,21 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
* @Date 2024/6/13 09:58 * @Date 2024/6/13 09:58
* @Author dy * @Author dy
*/ */
@RefreshScope
@Configuration @Configuration
@EnableCaching @EnableCaching
public class RedisConfig extends CachingConfigurerSupport { public class RedisConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.database:0}")
private int database = 0;
@Bean @Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" }) @SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) public RedisTemplate<Object, Object> redisTemplate(@Qualifier("redisConnectionFactory0") RedisConnectionFactory connectionFactory)
{ {
RedisTemplate<Object, Object> template = new RedisTemplate<>(); RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory); template.setConnectionFactory(connectionFactory);
@@ -50,6 +66,45 @@ public class RedisConfig extends CachingConfigurerSupport {
return template; return template;
} }
@Bean(name = "redisTemplate7")
public RedisTemplate<Object, Object> redisTemplate7(@Qualifier("redisConnectionFactory7") RedisConnectionFactory redisConnectionFactory0) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory0);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
/**
* 7号 数据库 - >
* @return
*/
@Bean
public RedisConnectionFactory redisConnectionFactory7() {
LettuceConnectionFactory factory = new LettuceConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(7);
return factory;
}
/**
* 默认 数据库
* @return
*/
@Bean
@Primary //添加@Primary默认使用的库
public RedisConnectionFactory redisConnectionFactory0() {
LettuceConnectionFactory factory = new LettuceConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(database);
return factory;
}
@Bean @Bean
public DefaultRedisScript<Long> limitScript() public DefaultRedisScript<Long> limitScript()
{ {
@@ -62,6 +117,8 @@ public class RedisConfig extends CachingConfigurerSupport {
return redisScript; return redisScript;
} }
/** /**
* 限流脚本 * 限流脚本
*/ */

View File

@@ -1,6 +1,7 @@
package com.m2pool.common.redis.service; package com.m2pool.common.redis.service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@@ -21,8 +22,14 @@ import java.util.concurrent.TimeUnit;
public class RedisService { public class RedisService {
@Autowired @Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate; private RedisTemplate redisTemplate;
@Autowired
@Qualifier("redisTemplate7")
private RedisTemplate redisTemplate7;
/** /**
* 缓存基本的对象Integer、String、实体类等 * 缓存基本的对象Integer、String、实体类等
* *
@@ -34,6 +41,7 @@ public class RedisService {
redisTemplate.opsForValue().set(key, value); redisTemplate.opsForValue().set(key, value);
} }
/** /**
* 缓存基本的对象Integer、String、实体类等 * 缓存基本的对象Integer、String、实体类等
* *
@@ -47,6 +55,12 @@ public class RedisService {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit); redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
} }
public <T> void setCacheObject7(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
{
redisTemplate7.opsForValue().set(key, value, timeout, timeUnit);
}
/** /**
* 设置有效时间 * 设置有效时间
* *
@@ -118,6 +132,12 @@ public class RedisService {
return operation.get(key); return operation.get(key);
} }
public <T> T getCacheObject7(final String key)
{
ValueOperations<String, T> operation = redisTemplate7.opsForValue();
return operation.get(key);
}
/** /**
* 所有数字类型转换为BigDecimal * 所有数字类型转换为BigDecimal
* @param key 缓存键值 * @param key 缓存键值
@@ -153,6 +173,7 @@ public class RedisService {
return redisTemplate.delete(key); return redisTemplate.delete(key);
} }
/** /**
* 删除集合对象 * 删除集合对象
* *

View File

@@ -0,0 +1,64 @@
package com.m2pool.common.security.interceptor;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
public class AuthRequestWrapper extends HttpServletRequestWrapper {
private String body;
public AuthRequestWrapper(HttpServletRequest request) {
super(request);
try(BufferedReader reader = request.getReader()){
body= reader.lines().collect(Collectors.joining());
}catch (Exception e){
System.out.println("!!-- read request from requestbody error"+e.getMessage());
}
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletIns = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return byteArrayIns.read();
}
};
return servletIns;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

View File

@@ -0,0 +1,66 @@
package com.m2pool.common.security.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@Component
public class CoinInterceptor implements HandlerInterceptor {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("调用Coin拦截器1:" + request);
// 仅处理 POST、PUT 等有请求体的请求方法
if ("POST".equalsIgnoreCase(request.getMethod()) || "PUT".equalsIgnoreCase(request.getMethod())) {
try {
// 读取请求体内容
if (request instanceof AuthRequestWrapper){
//BufferedReader reader = request.getReader();
//System.out.println("调用Coin拦截器2:" + reader);
//
//if (!requestBody.isEmpty()) {
// // 反序列化请求体为 RequestObject 对象
// RequestObject requestObject = objectMapper.readValue(requestBody, RequestObject.class);
// System.out.println("调用Coin拦截器3:" + requestObject.toString());
// String coin = requestObject.getCoin();
// System.out.println("调用Coin拦截器4:" + coin);
// if ("enx".equals(coin)) {
// response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
// response.getWriter().write("enx币种已下架");
// return false;
// }
//}
}
} catch (Exception e) {
// 处理反序列化异常
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().write("请求体解析失败");
return false;
}
}
return true;
}
/**
* 读取请求体内容
*/
private String readRequestBody(HttpServletRequest request) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = request.getReader()) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
}
return stringBuilder.toString();
}
}

View File

@@ -39,9 +39,9 @@ public class HeaderInterceptor implements AsyncHandlerInterceptor {
SecurityContextHolder.setUserKey(ServletUtils.getHeader(request,SecurityConstants.USER_KEY)); SecurityContextHolder.setUserKey(ServletUtils.getHeader(request,SecurityConstants.USER_KEY));
//开发环境 //开发环境
String authorization = request.getHeader("Authorization"); //String authorization = request.getHeader("Authorization");
String userName = JwtUtils.getUserName(authorization); //String userName = JwtUtils.getUserName(authorization);
SecurityContextHolder.setUserName(userName); //SecurityContextHolder.setUserName(userName);
String token = SecurityUtils.getToken(); String token = SecurityUtils.getToken();
if(StringUtils.isNotEmpty(token)){ if(StringUtils.isNotEmpty(token)){

View File

@@ -0,0 +1,27 @@
package com.m2pool.common.security.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
@Component
@WebFilter("/*")
public class RequestBodyFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request = new AuthRequestWrapper(request);
filterChain.doFilter(request,response);
}
}

View File

@@ -0,0 +1,16 @@
package com.m2pool.common.security.interceptor;
import com.fasterxml.jackson.annotation.JsonProperty;
public class RequestObject {
private String coin;
// 添加 getter 和 setter 方法
public String getCoin() {
return coin;
}
public void setCoin(String coin) {
this.coin = coin;
}
}

View File

@@ -0,0 +1,47 @@
server:
port: 8878
# Spring
spring:
application:
# 应用名称
name: m2pool-gateway
main:
allow-circular-references: true
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: m2_dev
group: m2_dev_group
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: m2_dev
group: m2_dev_group
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: 127.0.0.1:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: 127.0.0.1:8848
dataId: sentinel-m2pool-gateway
groupId: m2_dev_group
data-type: json
rule-type: flow
servlet:
multipart:
max-file-size: 2MB
max-request-size: 8MB

View File

@@ -78,7 +78,7 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
//获取链接建立时的请求头信息 //获取链接建立时的请求头信息
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if (accessor.getCommand() == StompCommand.CONNECT ) { if (accessor.getCommand() == StompCommand.CONNECT ) {
System.out.println("yyb-开始链接"+new Date()); System.out.println("开始链接"+new Date());
StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if(mha == null){ if(mha == null){
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL)); throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL));
@@ -92,7 +92,7 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
ipLimit(accessor,type,email); ipLimit(accessor,type,email);
//链接请求头中用户信息存入stomp中 //链接请求头中用户信息存入stomp中
mha.setUser(new StompPrincipal(email,type,true)); mha.setUser(new StompPrincipal(email,type,true));
System.out.println("yyb-链接成功"+new Date()); System.out.println("链接成功"+new Date());
} }
if (accessor.getCommand() == StompCommand.SUBSCRIBE) { if (accessor.getCommand() == StompCommand.SUBSCRIBE) {
LOGGER.info("------------websocket subscribe message"); LOGGER.info("------------websocket subscribe message");

View File

@@ -3,7 +3,7 @@ package com.m2pool.file.service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
/** /**
* 文件上传接口 * 接口
* *
* @author dy * @author dy
*/ */

View File

@@ -164,6 +164,15 @@
<version>3.1.2</version> <version>3.1.2</version>
</dependency> </dependency>
<!-- Thymeleaf 用于发送邮箱 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@@ -3,19 +3,36 @@ package com.m2pool.lease;
import com.m2pool.common.security.annotation.EnableCustomConfig; import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients; import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2; import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import com.m2pool.lease.netty.server.NettyTcpServer;
import io.netty.channel.ChannelFuture;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.Resource;
@EnableCustomConfig @EnableCustomConfig
@EnableCustomSwagger2 @EnableCustomSwagger2
@EnableM2PoolFeignClients @EnableM2PoolFeignClients
@SpringBootApplication @SpringBootApplication
@MapperScan({"com.m2pool.lease.mapper"}) @MapperScan({"com.m2pool.lease.mapper"})
public class M2poolLeaseApplication { public class M2poolLeaseApplication implements CommandLineRunner {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(M2poolLeaseApplication.class, args); SpringApplication.run(M2poolLeaseApplication.class, args);
} }
@Resource
NettyTcpServer nettyTcpServer;
@Override
public void run(String... args) {
//启动服务端
ChannelFuture start = nettyTcpServer.start();
//服务端管道关闭的监听器并同步阻塞,直到channel关闭,线程才会往下执行,结束进程
start.channel().closeFuture().syncUninterruptibly();
}
} }

View File

@@ -0,0 +1,14 @@
package com.m2pool.lease.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记在方法上,表示需要对请求体进行解密
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Decrypt {
}

View File

@@ -0,0 +1,14 @@
package com.m2pool.lease.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记在字段上,表示该字段需要解密
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptedField {
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
package com.m2pool.lease.annotation;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginRequired {
boolean value() default true;
}

View File

@@ -0,0 +1,127 @@
package com.m2pool.lease.aspect;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.json.JSONUtil;
import com.m2pool.lease.annotation.EncryptedField;
import com.m2pool.lease.exception.RSAException;
import com.m2pool.lease.utils.RsaUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Map;
@Aspect
@Component
public class DecryptAspect {
// 定义切点,拦截所有带 @Decrypt 注解的方法
@Pointcut("@annotation(com.m2pool.lease.annotation.Decrypt)")
public void decryptPointcut() {}
@Around("decryptPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Parameter[] parameters = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameters();
for (int i = 0; i < parameters.length; i++) {
// 找到被 @RequestBody 标记的参数
if (parameters[i].isAnnotationPresent(RequestBody.class)) {
Object requestBody = args[i];
// 递归解密对象中的加密字段
decryptObjectFields(requestBody);
}
}
// 继续执行原方法
return joinPoint.proceed(args);
}
private void decryptObjectFields(Object obj) {
if (obj == null) {
return;
}
// 处理集合或数组类型
if (obj instanceof Collection) {
for (Object item : (Collection<?>) obj) {
decryptObjectFields(item);
}
return;
}
// 处理Map类型
if (obj instanceof Map) {
for (Object value : ((Map<?, ?>) obj).values()) {
decryptObjectFields(value);
}
return;
}
// 处理普通对象
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(EncryptedField.class)) {
handleEncryptedField(obj, field);
} else {
//这里可能是普通对象或者集合或其他非EncryptedField标记的普通属性字段
handleNestedField(obj, field);
}
}
}
private void handleEncryptedField(Object obj, Field field) {
field.setAccessible(true);
try {
Object value = field.get(obj);
if (value != null) {
String encryptedValue = value.toString();
System.out.println("加密前地址:"+value +"类型"+(value instanceof String));
String decryptedValue = RsaUtils.decrypt(encryptedValue);
System.out.println("解密后地址:"+decryptedValue);
field.set(obj, decryptedValue);
}
} catch (Exception e) {
throw new RSAException("校验失败: " + e.getMessage());
} finally {
field.setAccessible(false);
}
}
private void handleNestedField(Object obj, Field field) {
field.setAccessible(true);
try {
Object fieldValue = field.get(obj);
if (fieldValue != null && !isPrimitiveOrWrapper(fieldValue)) {
decryptObjectFields(fieldValue);
}
} catch (IllegalAccessException e) {
// 忽略访问异常
} finally {
field.setAccessible(false);
}
}
private boolean isPrimitiveOrWrapper(Object obj) {
Class<?> clazz = obj.getClass();
return clazz.isPrimitive() ||
clazz == String.class ||
clazz == Integer.class ||
clazz == Long.class ||
clazz == Double.class ||
clazz == Float.class ||
clazz == Boolean.class ||
clazz == Character.class ||
clazz == Byte.class ||
clazz == Short.class ||
clazz == BigDecimal.class;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,90 @@
package com.m2pool.lease.config;
import com.m2pool.common.redis.service.RedisService;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.entity.LeaseUser;
import com.m2pool.lease.exception.AuthException;
import com.m2pool.lease.redis.RedisAuthKey;
import com.m2pool.lease.utils.JwtUtils;
import com.m2pool.lease.utils.UserThreadLocal;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import static com.m2pool.lease.utils.JwtUtils.AUTHENTICATION;
import static com.m2pool.lease.utils.JwtUtils.EXPIRETIME;
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Resource
private RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
String uri = request.getRequestURI();
if (uri.contains("/doc.html") || uri.contains("/webjars/")
|| uri.contains("/swagger-resources") || uri.contains("/v2/api-docs")) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 获取方法上的注解
LoginRequired loginRequired = method.getAnnotation(LoginRequired.class);
// 如果方法上没有注解,获取类上的注解
if (loginRequired == null) {
loginRequired = handlerMethod.getBeanType().getAnnotation(LoginRequired.class);
}
// 如果没有注解或者注解值为true则校验token
if (loginRequired == null || loginRequired.value()) {
String token = request.getHeader(AUTHENTICATION);
System.out.println("用户token:"+token);
if (token == null || !isValidToken(token)) {
throw new AuthException("用户未登录");
}
}
return true;
}
/**
* 验证token 并刷新token
*/
private boolean isValidToken(String token) {
String userEmail = JwtUtils.getUserName(token);
//1.把userEmail存入ThreadLocal 本地线程变量中
UserThreadLocal.setUserEmail(userEmail);
//2.校验token是否过期
String userKey = RedisAuthKey.getUserLoginKey(userEmail);
LeaseUser loginUser = redisService.getCacheObject(userKey);
if (loginUser == null){
return false;
}
//3.刷新token 过期时间
redisService.setCacheObject(userKey, loginUser, EXPIRETIME, TimeUnit.MINUTES);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
UserThreadLocal.remove();
}
}

View File

@@ -1,22 +1,39 @@
//package com.m2pool.lease.config; package com.m2pool.lease.config;
//
//import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
//import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
// import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//@Configuration
//public class WebMvcConfig implements WebMvcConfigurer { import javax.annotation.Resource;
//
// @Autowired @Configuration
// private AuthInterceptor authInterceptor; public class WebMvcConfig implements WebMvcConfigurer {
//
// @Override @Resource
// public void addInterceptors(InterceptorRegistry registry) { private LoginInterceptor loginInterceptor;
// // 注册拦截器并指定拦截路径
// registry.addInterceptor(authInterceptor) @Override
// .addPathPatterns("/**") // 拦截所有请求 public void addInterceptors(InterceptorRegistry registry) {
// .excludePathPatterns("/login", "/register") // 可选:排除不需要拦截的路径 registry.addInterceptor(loginInterceptor)
// .excludePathPatterns("/swagger-ui.html", "/webjars/**", "/v2/api-docs", "/swagger-resources/**"); // 可选排除Swagger相关路径 .addPathPatterns("/**");
// } }
//}
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域请求路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOriginPatterns("*") //或.allowedOriginPatterns("http://www.baidu.com") 指定域名
//是否允许cookie
.allowCredentials(true)
// 设置允许的请求方式
.allowedMethods("GET", "POST", "PUT", "DELETE")
// 设置允许的header属性
.allowedHeaders("*")
// 允许跨域时间
.maxAge(3600);
}
}

View File

@@ -13,13 +13,12 @@ import java.util.Map;
* @Author yyb * @Author yyb
*/ */
public class Algorithm { public class Algorithm {
// GRS 出块间隔时间单位s
public static final String GRS_ALGORITHM= "groestl"; public static final String GRS_ALGORITHM= "groestl";
// Mona 出块间隔时间单位s
public static final String MONA_ALGORITHM= "Lyra2REv2"; public static final String MONA_ALGORITHM= "Lyra2REv2";
// NEXA 出块间隔时间单位s
public static final String NEXA_ALGORITHM= "NexaPow"; public static final String NEXA_ALGORITHM= "NexaPow";
// RXD 出块间隔时间单位s
public static final String RXD_ALGORITHM= "Sha512256D"; public static final String RXD_ALGORITHM= "Sha512256D";
public static final String DGBQ_ALGORITHM= "DigiByte(Qubit)"; public static final String DGBQ_ALGORITHM= "DigiByte(Qubit)";

View File

@@ -3,6 +3,7 @@ package com.m2pool.lease.constant;
import com.m2pool.lease.dto.ChargeDto; import com.m2pool.lease.dto.ChargeDto;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -13,21 +14,24 @@ import java.util.List;
*/ */
public enum CoinCharge { public enum CoinCharge {
ETH_USDT("ETH","USDT", BigDecimal.valueOf(1)), ETH_USDT("ETH","USDT", BigDecimal.valueOf(1), BigDecimal.valueOf(1)),
TRON_USDT("TRON","USDT", BigDecimal.valueOf(1)), ETH_ETH("ETH","ETH", BigDecimal.valueOf(0.00005),BigDecimal.valueOf(0.01)),
TRON_NEXA("TRON","NEXA", BigDecimal.valueOf(1000)); TRON_USDT("TRON","USDT", BigDecimal.valueOf(1),BigDecimal.valueOf(1)),
TRON_NEXA("TRON","NEXA", BigDecimal.valueOf(1000),BigDecimal.valueOf(0.1));
private final String chain; private final String chain;
/** 币种参数名 */ /** 币种参数名 */
private final String coin; private final String coin;
/** 手续费 */ /** 手续费 */
private final BigDecimal amount; private final BigDecimal amount;
/** 费率 */
private final BigDecimal feeRate;
CoinCharge(String chain, String coin, BigDecimal amount, BigDecimal feeRate) {
CoinCharge(String chain, String coin, BigDecimal amount) {
this.chain = chain; this.chain = chain;
this.coin = coin; this.coin = coin;
this.amount = amount; this.amount = amount;
this.feeRate = feeRate;
} }
/** /**
* 根据 chain 和 coin 查找对应的手续费,未找到则返回 1 * 根据 chain 和 coin 查找对应的手续费,未找到则返回 1
@@ -44,6 +48,44 @@ public enum CoinCharge {
return BigDecimal.ONE; return BigDecimal.ONE;
} }
/**
* 根据 chain 和 coin 查找对应的手续费,未找到则返回 1
* @param chain 链名
* @param coin 币种名
* @return 对应的手续费,未找到返回 1
*/
public static BigDecimal getDeductibleAmountByChainAndCoin(String chain, String coin) {
for (CoinCharge charge : CoinCharge.values()) {
if (charge.chain.equals(chain) && charge.coin.equals(coin)) {
return charge.amount.divide(charge.feeRate, 4, RoundingMode.HALF_UP);
}
}
return BigDecimal.ONE;
}
/**
* 根据 chain 和 coin 找到手续费和费率然后比较totalPrice是否小于 费率/手续费
* @param chain 链名
* @param coin 币种名
* @return 对应的手续费,未找到返回 1
*/
public static BigDecimal getFee(String chain, String coin, BigDecimal totalPrice) {
BigDecimal fee = BigDecimal.ONE;
for (CoinCharge charge : CoinCharge.values()) {
if (charge.chain.equals(chain) && charge.coin.equals(coin)) {
BigDecimal feeRate = charge.feeRate;
BigDecimal deductible= charge.amount.divide(feeRate, 4, RoundingMode.HALF_UP);
if(deductible.compareTo(totalPrice) < 0){
fee = BigDecimal.ZERO;
}else{
fee = charge.amount;
}
}
}
return fee;
}
/** /**
* 获取枚举类中所有枚举,并封装成 List<ChargeDto> * 获取枚举类中所有枚举,并封装成 List<ChargeDto>
@@ -55,7 +97,8 @@ public enum CoinCharge {
chargeDtoList.add(new ChargeDto( chargeDtoList.add(new ChargeDto(
charge.amount, charge.amount,
charge.chain, charge.chain,
charge.coin charge.coin,
charge.feeRate
)); ));
} }
return chargeDtoList; return chargeDtoList;

View File

@@ -0,0 +1,47 @@
package com.m2pool.lease.constant;
import com.m2pool.lease.netty.message.GpuMessage;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Description 币种算法
* @Date 2025/8/18 16:19
* @Author yyb
*/
public class GpuBrand {
private static final String NVIDIA= "NVIDIA";
private static final String AMD= "ADM";
private static final String APPLE= "APPLE";
private static final String INTEL= "INTEL";
private static final List<String> BRAND_LIST;
static {
BRAND_LIST = new ArrayList<>();
BRAND_LIST.add(NVIDIA);
BRAND_LIST.add(AMD);
BRAND_LIST.add(APPLE);
BRAND_LIST.add(INTEL);
}
public static List<String> trimBrand(List<String> targetList) {
return targetList.stream()
.map(model -> {
for (String brand : BRAND_LIST) {
if (model.contains(brand)) {
return model.replace(brand, "").trim();
}
}
return model.trim();
})
.collect(Collectors.toList());
}
}

View File

@@ -28,9 +28,9 @@ public class PowerUnit {
HashMap<String, BigDecimal> map = new HashMap<>(); HashMap<String, BigDecimal> map = new HashMap<>();
map.put(KH_UNIT, BigDecimal.valueOf(1000)); map.put(KH_UNIT, BigDecimal.valueOf(1000));
map.put(MH_UNIT, BigDecimal.valueOf(1000 * 1000)); map.put(MH_UNIT, BigDecimal.valueOf(1000 * 1000));
map.put(GH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000)); map.put(GH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000));
map.put(TH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000)); map.put(TH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 ));
map.put(PH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000 * 1000)); map.put(PH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000));
UNIT_MAP = Collections.unmodifiableMap(map); UNIT_MAP = Collections.unmodifiableMap(map);
} }

View File

@@ -0,0 +1,136 @@
package com.m2pool.lease.controller;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.Result;
import com.m2pool.lease.dto.v2.GoogleInfoDto;
import com.m2pool.lease.service.LeaseUserService;
import com.m2pool.lease.vo.EmailCodeVo;
import com.m2pool.lease.vo.UserLoginVo;
import com.m2pool.lease.vo.UserRegisterVo;
import com.m2pool.lease.vo.v2.GoogleBindVo;
import com.m2pool.lease.vo.v2.GoogleCloseVo;
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 javax.validation.Valid;
import java.util.Map;
/**
* <p>
* 用户表 前端控制器
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Api(tags = "用户授权控制器")
@LoginRequired(value = false)
@RestController
@RequestMapping("/auth")
public class LeaseAuthController {
@Resource
private LeaseUserService leaseUserService;
@Decrypt
@PostMapping("/login")
@ApiOperation(value = "用户登录")
public Result<Map<String, Object>> login(@RequestBody UserLoginVo userLoginVo){
return leaseUserService.login(userLoginVo);
}
@Decrypt
@PostMapping("/register")
@ApiOperation(value = "用户注册")
public Result<String> register(@RequestBody UserRegisterVo userRegisterVo){
return leaseUserService.register(userRegisterVo);
}
@Decrypt
@PostMapping("/updatePassword")
@ApiOperation(value = "修改密码")
public Result<String> updatePassword(@RequestBody UserLoginVo userLoginVo){
return leaseUserService.updatePassword(userLoginVo);
}
@PostMapping("/logout")
@ApiOperation(value = "登出")
public Result<String> logout(){
return leaseUserService.logout();
}
@PostMapping("/sendLoginCode")
@ApiOperation(value = "发送用户登录邮箱验证码")
public Result<String> sendLoginCode(@RequestBody @Valid EmailCodeVo emailCodeVo){
return leaseUserService.sendLoginCode(emailCodeVo);
}
@PostMapping("/sendRegisterCode")
@ApiOperation(value = "发送用户注册邮箱验证码")
public Result<String> sendRegisterCode(@RequestBody @Valid EmailCodeVo emailCodeVo){
return leaseUserService.sendRegisterCode(emailCodeVo);
}
@PostMapping("/sendUpdatePwdCode")
@ApiOperation(value = "发送修改密码验证码")
public Result<String> sendUpdatePwdCode(@RequestBody @Valid EmailCodeVo emailCodeVo){
return leaseUserService.sendUpdatePwdCode(emailCodeVo);
}
/*-----------------------------谷歌双重验证接口----------------------------*/
@Decrypt
@LoginRequired
@PostMapping("/bindGoogle")
@ApiOperation(value = "绑定开启谷歌验证")
public Result<String> bindGoogle(@RequestBody @Valid GoogleBindVo googleBindVo){
return leaseUserService.bindGoogle(googleBindVo);
}
@LoginRequired
@PostMapping("/getBindInfo")
@ApiOperation(value = "获取谷歌验证器安全码和验证码")
public Result<GoogleInfoDto> getBindInfo(){
return leaseUserService.getBindInfo();
}
@LoginRequired
@PostMapping("/sendOpenGoogleCode")
@ApiOperation(value = "开启谷歌验证器 发送邮箱验证码")
public Result<String> sendOpenGoogleCode(){
return leaseUserService.sendOpenGoogleCode();
}
@LoginRequired
@PostMapping("/sendCloseGoogleCode")
@ApiOperation(value = "关闭谷歌验证器 发送邮箱验证码")
public Result<String> sendCloseGoogleCode(){
return leaseUserService.sendCloseGoogleCode();
}
@LoginRequired
@PostMapping("/closeStepTwo")
@ApiOperation(value = "关闭双重验证")
public Result<String> closeStepTwo(@Valid @RequestBody GoogleCloseVo vo){
return leaseUserService.closeStepTwo(vo);
}
/*-----------------------------谷歌双重验证接口----------------------------*/
}

View File

@@ -1,20 +0,0 @@
package com.m2pool.lease.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 矿池nexa机器实时平均算力 前端控制器
* </p>
*
* @author yyb
* @since 2025-07-29
*/
@RestController
@RequestMapping("/machine/avg/power")
public class LeaseMachineAvgPowerController {
}

View File

@@ -1,20 +0,0 @@
package com.m2pool.lease.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 已售商品矿工实时算力表 前端控制器
* </p>
*
* @author yyb
* @since 2025-07-25
*/
@RestController
@RequestMapping("/machine/power")
public class LeaseMachinePowerController {
}

View File

@@ -2,6 +2,8 @@ package com.m2pool.lease.controller;
import com.m2pool.common.security.annotation.RequiresLogin; import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.OrderInfoDto; import com.m2pool.lease.dto.OrderInfoDto;
import com.m2pool.lease.dto.PageResult; import com.m2pool.lease.dto.PageResult;
import com.m2pool.lease.dto.PaymentRecordDto; import com.m2pool.lease.dto.PaymentRecordDto;
@@ -28,6 +30,7 @@ import java.util.List;
* @since 2025-07-23 * @since 2025-07-23
*/ */
@Api(tags = "订单控制器") @Api(tags = "订单控制器")
@LoginRequired
@RestController @RestController
@RequestMapping("/order/info") @RequestMapping("/order/info")
public class LeaseOrderInfoController { public class LeaseOrderInfoController {
@@ -38,6 +41,7 @@ public class LeaseOrderInfoController {
@ApiOperation("创建订单及订单详情 + 支付订单(返回二维码内容)") @ApiOperation("创建订单及订单详情 + 支付订单(返回二维码内容)")
@PostMapping("/addOrders") @PostMapping("/addOrders")
@Decrypt
public Result<String> addOrders(@RequestBody OrderAndCodeVo orderAndCodeVo) { public Result<String> addOrders(@RequestBody OrderAndCodeVo orderAndCodeVo) {
return leaseOrderInfoService.addOrders(orderAndCodeVo); return leaseOrderInfoService.addOrders(orderAndCodeVo);
} }

View File

@@ -0,0 +1,78 @@
package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.PageResult;
import com.m2pool.lease.dto.Result;
import com.m2pool.lease.dto.v2.*;
import com.m2pool.lease.service.LeaseOrderInfoService;
import com.m2pool.lease.vo.BaseVo;
import com.m2pool.lease.vo.OrderAndCodeVo;
import com.m2pool.lease.vo.PageVo;
import com.m2pool.lease.vo.v2.CoinAndAlgorithmVo;
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;
/**
* <p>
* 订单表 前端控制器
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Api(tags = "v2版本--订单控制器")
@LoginRequired
@RestController
@RequestMapping("/v2/order/info")
public class LeaseOrderInfoV2Controller {
@Resource
private LeaseOrderInfoService leaseOrderInfoService;
@ApiOperation("算法币种选择框:购物车结算获取选中矿机支持的算法和币种列表")
@PostMapping("/getMachineSupportCoinAndAlgorithm")
public Result<List<CoinAndAlgorithmListDto>> getMachineSupportCoinAndAlgorithm(@RequestBody List<BaseVo> machineIds) {
return leaseOrderInfoService.getMachineSupportCoinAndAlgorithm(machineIds);
}
@ApiOperation("矿池选择框:根据矿机id 获取当前矿机支持的矿池币种信息")
@PostMapping("/getMachineSupportPool")
public Result<List<MiningInfoDto>> getMachineSupportPool(@RequestBody CoinAndAlgorithmVo coinAndAlgorithmVo) {
return leaseOrderInfoService.getMachineSupportPool(coinAndAlgorithmVo);
}
@ApiOperation("创建订单及订单详情 + 支付订单(返回二维码内容)")
@PostMapping("/addOrdersV2")
@Decrypt
public Result<String> addOrdersV2(@RequestBody OrderAndCodeVo orderAndCodeVo) {
return leaseOrderInfoService.addOrdersV2(orderAndCodeVo);
}
@ApiOperation("买家:已购矿机列表")
@PostMapping("/getPurchasedItems")
public PageResult<PurchasedMachineListDto> getPurchasedItems(@RequestBody(required = false) PageVo pageVo) {
if (pageVo == null){
pageVo = new PageVo();
}
return leaseOrderInfoService.getPurchasedItems(pageVo);
}
@ApiOperation("买家:根据id查询已购矿机详情")
@PostMapping("/getPurchasedInfo")
public Result<MiningConfigInfoDto> getPurchasedInfo(@RequestBody BaseVo baseVo) {
return leaseOrderInfoService.getPurchasedInfo(baseVo);
}
}

View File

@@ -1,13 +1,11 @@
package com.m2pool.lease.controller; package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.dto.*; import com.m2pool.lease.dto.*;
import com.m2pool.lease.service.LeaseProductService; import com.m2pool.lease.service.LeaseProductService;
import com.m2pool.lease.service.LeaseUserOwnedProductService; import com.m2pool.lease.service.LeaseUserOwnedProductService;
import com.m2pool.lease.vo.BaseVo; import com.m2pool.lease.vo.*;
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.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -17,6 +15,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/** /**
* <p> * <p>
@@ -56,8 +56,14 @@ public class LeaseProductController {
@ApiOperation("查询单个商品详情(包含商品对应的售卖机器详情列表)") @ApiOperation("查询单个商品详情(包含商品对应的售卖机器详情列表)")
@PostMapping("/getMachineInfo") @PostMapping("/getMachineInfo")
public Result<ProductMachineInfoDto> getProductMachineInfo(@RequestBody BaseVo BaseVo) { public PageResult<ProductMachineDto> getProductMachineInfo(@RequestBody ProductMachineVo productMachineVo) {
return leaseProductService.getProductMachineInfo(BaseVo.getId()); return leaseProductService.getProductMachineInfo(productMachineVo);
}
@ApiOperation("单个商品矿机列表页面---获取支付方式")
@PostMapping("/getPayTypes")
public Result<List<PayConfigDto>> getPayTypes() {
return leaseProductService.getPayTypes();
} }
@@ -96,5 +102,30 @@ public class LeaseProductController {
public Result<UserOwnedProductDto> getOwnedById(@RequestBody BaseVo baseVo) { public Result<UserOwnedProductDto> getOwnedById(@RequestBody BaseVo baseVo) {
return leaseUserOwnedProductService.getOwnedById(baseVo); return leaseUserOwnedProductService.getOwnedById(baseVo);
} }
@ApiOperation("查询用户店铺支持的支付方式")
@PostMapping("/getSupportPayType")
public Result<List<PayTypeDto>> getSupportPayType() {
return leaseProductService.getSupportPayType();
}
//TODO 2025-11-21 查询店铺的矿机列表,不存在商品了
@ApiOperation("获取店铺商品列表用于新增绑定店铺钱包")
@PostMapping("/getProductListForShopWalletConfig")
public Result<List<ProductForWalletConfigDto>> getProductListForShopWalletConfig() {
return leaseProductService.getProductListForShopWalletConfig();
}
//TODO 2025-11-21 修改这些矿机的价格,并且绑定新钱包
@ApiOperation("新增绑定店铺钱包并设置店铺下面每个矿机该钱包币种的售价 + 钱包绑定")
@PostMapping("/updateProductListForShopWalletConfig")
@Decrypt
public Result<String> updateProductListForShopWalletConfig(@RequestBody ProductMachineForWalletConfigVo productMachineForWalletConfigVo) {
return leaseProductService.updateProductListForShopWalletConfig(productMachineForWalletConfigVo);
}
} }

View File

@@ -1,8 +1,11 @@
package com.m2pool.lease.controller; package com.m2pool.lease.controller;
import com.m2pool.common.security.annotation.RequiresLogin; import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.*; 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.service.LeaseProductMachineService; import com.m2pool.lease.service.LeaseProductMachineService;
import com.m2pool.lease.vo.*; import com.m2pool.lease.vo.*;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@@ -25,6 +28,7 @@ import java.util.Map;
* @since 2025-07-23 * @since 2025-07-23
*/ */
@Api(tags = "商品矿机控制器(库存控制器)") @Api(tags = "商品矿机控制器(库存控制器)")
@LoginRequired
@RestController @RestController
@RequestMapping("/product/machine") @RequestMapping("/product/machine")
public class LeaseProductMachineController { public class LeaseProductMachineController {
@@ -33,6 +37,7 @@ public class LeaseProductMachineController {
@Resource @Resource
private LeaseProductMachineService leaseProductMachineService; private LeaseProductMachineService leaseProductMachineService;
@ApiOperation("根据 登录账户 获取挖矿账户及挖矿币种集合----用于用户为商品添加实际出售机器库存") @ApiOperation("根据 登录账户 获取挖矿账户及挖矿币种集合----用于用户为商品添加实际出售机器库存")
@PostMapping("/getUserMinersList") @PostMapping("/getUserMinersList")
public Result<Map<String, List<UserMinerDto>>> getUserMinersList(@RequestBody UserMinerVo userMinerVo) { public Result<Map<String, List<UserMinerDto>>> getUserMinersList(@RequestBody UserMinerVo userMinerVo) {

View File

@@ -0,0 +1,112 @@
package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.*;
import com.m2pool.lease.dto.v2.MachineInfoDto;
import com.m2pool.lease.dto.v2.SellerMachineInfoDto;
import com.m2pool.lease.dto.v2.ShopInfoDto;
import com.m2pool.lease.service.LeaseMachineService;
import com.m2pool.lease.vo.*;
import com.m2pool.lease.vo.v2.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* <p>
* 商品表对应的物品机器表 前端控制器
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Api(tags = "v2版本--矿机控制器类")
@LoginRequired
@RestController
@RequestMapping("/v2/product/machine")
public class LeaseProductMachineV2Controller {
@Resource
private LeaseMachineService leaseMachineService;
@ApiOperation("商城首页---店铺列表")
@LoginRequired(value = false)
@PostMapping("/getShopList")
public PageResult<ShopInfoDto> getShopList(@RequestBody(required = false) ProductPageVo productPageVo) {
if(productPageVo == null){
productPageVo = new ProductPageVo();
}
return leaseMachineService.getShopList(productPageVo);
}
@ApiOperation("商城首页---店铺对应矿机详情列表")
@LoginRequired(value = false)
@PostMapping("/getShopMachineList")
public PageResult<MachineInfoDto> getShopMachineList(@RequestBody ShopMachineVo shopMachineVo) {
return leaseMachineService.getShopMachineList(shopMachineVo);
}
@ApiOperation("卖家页面---矿机列表")
@PostMapping("/getShopMachineListForSeller")
public PageResult<SellerMachineInfoDto> getShopMachineListForSeller(@RequestBody(required = false) SellerMachineVo sellerMachineVo) {
if (sellerMachineVo == null) {
sellerMachineVo = new SellerMachineVo();
}
return leaseMachineService.getShopMachineListForSeller(sellerMachineVo);
}
@ApiOperation("卖家页面---新增ASIC矿机")
@PostMapping("/addAsicMachine")
public Result<String> addAsicMachine(@RequestBody AsicMachineParamsVo asicMachineParamsVo) {
return leaseMachineService.addAsicMachine(asicMachineParamsVo);
}
@ApiOperation("卖家页面---修改ASIC矿机")
@PostMapping("/updateAsicMachine")
public Result<String> updateAsicMachine(@RequestBody AsicMachineParamsVo asicMachineParamsVo) {
return leaseMachineService.updateAsicMachine(asicMachineParamsVo);
}
@ApiOperation("卖家页面--- 批量修改GPU矿机 和 批量上下架")
@PostMapping("/updateGpuMachine")
public Result<String> updateGpuMachine(@RequestBody List<GpuMachineParamsVo> gpuMachineParamsVoList) {
return leaseMachineService.updateGpuMachine(gpuMachineParamsVoList);
}
@ApiOperation("卖家页面---GPU/ASIC矿机上下架")
@PostMapping("/updateMachineState")
public Result<String> updateMachineState(@RequestBody MachineStateVo machineStateVo) {
return leaseMachineService.updateMachineState(machineStateVo);
}
@ApiOperation("卖家页面---根据矿机id删除GPU/ASIC矿机")
@PostMapping("/deleteMachine")
public Result<String> deleteMachine(@RequestBody BaseVo baseVo) {
return leaseMachineService.deleteMachine(baseVo);
}
@ApiOperation("获取租赁系统支持的币种")
@GetMapping("/getSupportCoin")
public Result<List<String>> getSupportCoin() {
return leaseMachineService.getSupportCoin();
}
@ApiOperation("根据币种获取租赁系统支持的算法")
@GetMapping("/getSupportAlgo")
public Result<List<String>> getSupportAlgo(@RequestParam String coin) {
return leaseMachineService.getSupportAlgo(coin);
}
}

View File

@@ -1,6 +1,7 @@
package com.m2pool.lease.controller; package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.*; import com.m2pool.lease.dto.*;
import com.m2pool.lease.service.LeaseShopService; import com.m2pool.lease.service.LeaseShopService;
import com.m2pool.lease.vo.BaseVo; import com.m2pool.lease.vo.BaseVo;
@@ -22,6 +23,7 @@ import java.util.List;
* @since 2025-08-05 * @since 2025-08-05
*/ */
@Api(tags = "店铺控制器") @Api(tags = "店铺控制器")
@LoginRequired
@RestController @RestController
@RequestMapping("/shop") @RequestMapping("/shop")
public class LeaseShopController { public class LeaseShopController {
@@ -121,8 +123,9 @@ public class LeaseShopController {
* @param shopConfigVo 商铺配置信息 * @param shopConfigVo 商铺配置信息
* @return 操作结果 * @return 操作结果
*/ */
@ApiOperation("钱包配置---新增商铺收款钱包绑定配置") @ApiOperation("钱包配置---新增商铺收款钱包绑定配置(弃用,业务移到/product/updateProductListForShopWalletConfig 接口)")
@PostMapping("/addShopConfig") @PostMapping("/addShopConfig")
@Deprecated
public Result<String> addShopConfig(@RequestBody ShopConfigVo shopConfigVo) { public Result<String> addShopConfig(@RequestBody ShopConfigVo shopConfigVo) {
return leaseShopService.addShopConfig(shopConfigVo); return leaseShopService.addShopConfig(shopConfigVo);
} }

View File

@@ -0,0 +1,79 @@
package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LedgerLog;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.PageResult;
import com.m2pool.lease.dto.Result;
import com.m2pool.lease.dto.v2.PayWithdrawSellerRecordDto;
import com.m2pool.lease.dto.v2.ShopWalletInfoDto;
import com.m2pool.lease.service.LeaseShopService;
import com.m2pool.lease.vo.BalanceVo;
import com.m2pool.lease.vo.BaseVo;
import com.m2pool.lease.vo.PageVo;
import com.m2pool.lease.vo.v2.ShopWalletInfoVo;
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;
/**
* <p>
* 店铺表 前端控制器
* </p>
*
* @author yyb
* @since 2025-08-05
*/
@Api(tags = "v2版本--店铺控制器")
@LoginRequired
@RestController
@RequestMapping("/v2/shop")
public class LeaseShopV2Controller {
@Resource
private LeaseShopService leaseShopService;
/**
* 根据店铺id 查询配置信息列表
* @param baseVo
* @return 操作结果
*/
@ApiOperation("钱包配置----根据店铺id查询收款钱包绑定信息列表")
@PostMapping("/getShopConfigV2")
public Result<List<ShopWalletInfoDto>> getShopConfigV2(@RequestBody BaseVo baseVo) {
return leaseShopService.getShopConfigV2(baseVo);
}
@LedgerLog(value = "卖家钱包--余额提现申请")
@Decrypt
@PostMapping("/withdrawBalanceForSeller")
@ApiOperation(value = "卖家店铺钱包余额提现")
public Result<String> withdrawBalanceForSeller(@RequestBody BalanceVo balanceVo){
return leaseShopService.withdrawBalanceForSeller(balanceVo);
}
@ApiOperation("钱包配置----根据配置id 修改商铺收款钱包配置")
@PostMapping("/updateShopConfigV2")
@Decrypt
public Result<String> updateShopConfigV2(@RequestBody ShopWalletInfoVo shopWalletInfoVo) {
return leaseShopService.updateShopConfigV2(shopWalletInfoVo);
}
@PostMapping("/balanceWithdrawList")
@ApiOperation(value = "卖家:余额提现记录列表")
public PageResult<PayWithdrawSellerRecordDto> balanceWithdrawList(@RequestBody PageVo pageVo){
return leaseShopService.balanceWithdrawList(pageVo);
}
}

View File

@@ -1,6 +1,7 @@
package com.m2pool.lease.controller; package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.PageResult; import com.m2pool.lease.dto.PageResult;
import com.m2pool.lease.dto.Result; import com.m2pool.lease.dto.Result;
import com.m2pool.lease.dto.ShopCartDto; import com.m2pool.lease.dto.ShopCartDto;
@@ -28,6 +29,7 @@ import java.util.List;
* @since 2025-07-23 * @since 2025-07-23
*/ */
@Api(tags = "购物车表控制器") @Api(tags = "购物车表控制器")
@LoginRequired
@RestController @RestController
@RequestMapping("/shopping/cart") @RequestMapping("/shopping/cart")
public class LeaseShoppingCartController { public class LeaseShoppingCartController {
@@ -51,6 +53,12 @@ public class LeaseShoppingCartController {
return leaseShoppingCartService.getGoodsList(pageVo); return leaseShoppingCartService.getGoodsList(pageVo);
} }
@ApiOperation("批量删除购物车中商品")
@PostMapping("/deleteBatchGoods")
public Result<String> deleteBatchGoods(@RequestBody List<ProductAndMachineVo> baseVoList) {
return leaseShoppingCartService.deleteBatchGoods(baseVoList);
}
@ApiOperation("删除购物车中商品") @ApiOperation("删除购物车中商品")
@PostMapping("/deleteGoods") @PostMapping("/deleteGoods")
@Deprecated @Deprecated
@@ -58,11 +66,6 @@ public class LeaseShoppingCartController {
return leaseShoppingCartService.deleteGoods(baseVo); return leaseShoppingCartService.deleteGoods(baseVo);
} }
@ApiOperation("批量删除购物车中商品")
@PostMapping("/deleteBatchGoods")
public Result<String> deleteBatchGoods(@RequestBody List<ProductAndMachineVo> baseVoList) {
return leaseShoppingCartService.deleteBatchGoods(baseVoList);
}
@ApiOperation("批量删除购物车中已下架商品") @ApiOperation("批量删除购物车中已下架商品")
@PostMapping("/deleteBatchGoodsForIsDelete") @PostMapping("/deleteBatchGoodsForIsDelete")

View File

@@ -0,0 +1,75 @@
package com.m2pool.lease.controller;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.PageResult;
import com.m2pool.lease.dto.Result;
import com.m2pool.lease.dto.ShopCartDto;
import com.m2pool.lease.dto.v2.ShopCartV2Dto;
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 com.m2pool.lease.vo.v2.AddGoodsVo;
import com.m2pool.lease.vo.v2.CartInfoVo;
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;
/**
* <p>
* 购物车表 前端控制器
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Api(tags = "v2版本---购物车表控制器")
@LoginRequired
@RestController
@RequestMapping("/v2/shopping/cart")
public class LeaseShoppingCartV2Controller {
@Resource
private LeaseShoppingCartService leaseShoppingCartService;
@ApiOperation("添加商品到购物车(批量+单个)")
@PostMapping("/addGoodsV2")
public Result<String> addGoodsV2(@RequestBody List<AddGoodsVo> addGoodsVoList) {
return leaseShoppingCartService.addGoodsV2(addGoodsVoList);
}
@ApiOperation("查询购物车中商品列表")
@PostMapping("/getGoodsListV2")
public PageResult<ShopCartV2Dto> getGoodsListV2(@RequestBody(required = false) PageVo pageVo) {
if (pageVo == null){
pageVo = new PageVo();
}
return leaseShoppingCartService.getGoodsListV2(pageVo);
}
@ApiOperation("批量删除购物车中商品")
@PostMapping("/deleteBatchGoodsV2")
public Result<String> deleteBatchGoodsV2(@RequestBody List<CartInfoVo> baseVoList) {
return leaseShoppingCartService.deleteBatchGoodsV2(baseVoList);
}
@ApiOperation("批量删除购物车中已下架商品")
@PostMapping("/deleteBatchGoodsForIsDeleteV2")
public Result<String> deleteBatchGoodsForIsDeleteV2() {
return leaseShoppingCartService.deleteBatchGoodsForIsDeleteV2();
}
}

View File

@@ -1,18 +1,22 @@
package com.m2pool.lease.controller; package com.m2pool.lease.controller;
import com.m2pool.common.security.annotation.RequiresLogin; import com.m2pool.lease.annotation.Decrypt;
import com.m2pool.lease.annotation.LedgerLog;
import com.m2pool.lease.annotation.LoginRequired;
import com.m2pool.lease.dto.*; import com.m2pool.lease.dto.*;
import com.m2pool.lease.service.LeaseUserService; import com.m2pool.lease.service.LeaseUserService;
import com.m2pool.lease.vo.*; import com.m2pool.lease.vo.BalancePageVo;
import com.m2pool.lease.vo.BalanceVo;
import com.m2pool.lease.vo.ChainAndCoinVo;
import com.m2pool.lease.vo.RecordTypePageVo;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
/** /**
@@ -23,19 +27,14 @@ import java.util.List;
* @author yyb * @author yyb
* @since 2025-07-23 * @since 2025-07-23
*/ */
@Api(tags = "用户控制器") @Api(tags = "用户信息控制器")
@LoginRequired
@RestController @RestController
@RequestMapping("/user") @RequestMapping("/user")
public class LeaseUserController { public class LeaseUserController {
@Resource @Resource
private LeaseUserService leaseUserService; private LeaseUserService leaseUserService;
@PostMapping("/login")
@ApiOperation(value = "用户登录/注册")
@Deprecated
public Result<UserDto> login(@RequestBody UserURDVo userURDVo){
return leaseUserService.login(userURDVo);
}
@PostMapping("/bindWallet") @PostMapping("/bindWallet")
@@ -51,6 +50,8 @@ public class LeaseUserController {
} }
@LedgerLog(value = "买家钱包--余额提现申请")
@Decrypt
@PostMapping("/withdrawBalance") @PostMapping("/withdrawBalance")
@ApiOperation(value = "申请余额提现") @ApiOperation(value = "申请余额提现")
public Result<String> withdrawBalance(@RequestBody BalanceVo balanceVo){ public Result<String> withdrawBalance(@RequestBody BalanceVo balanceVo){
@@ -98,5 +99,18 @@ public class LeaseUserController {
public Result<List<ChargeDto>> getCharge(){ public Result<List<ChargeDto>> getCharge(){
return leaseUserService.getCharge(); return leaseUserService.getCharge();
} }
@GetMapping("/downloadClient")
@ApiOperation(value = "卖家:下载客户端")
public void downloadClient(@RequestParam String userEmail,@RequestParam String type,HttpServletRequest request, HttpServletResponse response){
leaseUserService.downloadClient(userEmail,type,request, response);
}
@GetMapping("/getClientVersion")
@ApiOperation(value = "获取客户端版本号")
public String getClientVersion(){
return leaseUserService.getClientVersion();
}
} }

View File

@@ -0,0 +1,58 @@
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.Objects;
/**
* <p>
* 余额提现请求对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChainAndCoinDto {
private String coin;
private String chain;
private Long shopId;
public ChainAndCoinDto( String coin,String chain) {
this.chain = chain;
this.coin = coin;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ChainAndCoinDto that = (ChainAndCoinDto) o;
return Objects.equals(coin, that.coin) && Objects.equals(chain, that.chain) && Objects.equals(shopId, that.shopId);
}
@Override
public int hashCode() {
return Objects.hash(coin, chain,shopId);
}
@Override
public String toString() {
return "ChainAndCoinDto{" +
"coin='" + coin + '\'' +
", chain='" + chain + '\'' +
", shopId='" + shopId + '\'' +
'}';
}
}

View File

@@ -33,5 +33,7 @@ public class ChargeDto {
@ApiModelProperty(value = "币种",required = true) @ApiModelProperty(value = "币种",required = true)
private String coin; private String coin;
@ApiModelProperty(value = "手续费率",required = true)
private BigDecimal feeRate;
} }

View File

@@ -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.time.LocalDateTime;
/**
* <p>
* 矿机售价配置返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "矿机售价配置返回对象",value = "MachinePayTypeDto" )
public class MachinePayTypeDto {
@ApiModelProperty(value = "矿机币种售价配置id")
private Long payTypeId;
@ApiModelProperty(value = "矿机id忽略")
private Long productMachineId;
@ApiModelProperty(value = "售价")
private BigDecimal price;
@ApiModelProperty(value = "")
private String chain;
@ApiModelProperty(value = "售价单位币种")
private String coin;
}

View File

@@ -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;
/**
* <p>
* 矿机售价配置返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "购物车矿机总价返回对象",value = "MachineTotalPriceDto" )
public class MachineTotalPriceDto {
@ApiModelProperty(value = "售价")
private BigDecimal price;
@ApiModelProperty(value = "")
private String chain;
@ApiModelProperty(value = "售价单位币种")
private String coin;
}

View File

@@ -71,6 +71,10 @@ public class OrderInfoDto {
private LocalDateTime createTime; private LocalDateTime createTime;
@ApiModelProperty(value = "订单完成时间")
private LocalDateTime endTime;
// ---------------------------------------------- 一个普通订单对应一个支付订单多个封装下面四个字段为一个对象并返回list---------------------------------------------------------------------- // ---------------------------------------------- 一个普通订单对应一个支付订单多个封装下面四个字段为一个对象并返回list----------------------------------------------------------------------
@@ -86,6 +90,9 @@ public class OrderInfoDto {
@ApiModelProperty(value = "未支付金额") @ApiModelProperty(value = "未支付金额")
private Double noPayAmount; private Double noPayAmount;
@ApiModelProperty(value = "店铺名称")
private String shopName;
//---------------------------------------------- 一个普通订单对应一个支付订单多个封装下面四个字段为一个对象并返回list- ---------------------------------------------------------------------- //---------------------------------------------- 一个普通订单对应一个支付订单多个封装下面四个字段为一个对象并返回list- ----------------------------------------------------------------------
/** /**
* 订单详情 * 订单详情

View File

@@ -81,5 +81,12 @@ public class OrderItemDto {
private String payCoin; private String payCoin;
@ApiModelProperty(value = "租赁矿机数量")
private Integer numbers;
@ApiModelProperty(value = "矿机类型 0 ASIC 1 GPU")
private Integer type;
} }

View File

@@ -8,6 +8,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@@ -49,11 +50,18 @@ public class PageResult<T> implements Serializable
@ApiModelProperty(value = "查询结果描述", example = "成功") @ApiModelProperty(value = "查询结果描述", example = "成功")
private String msg; private String msg;
@ApiModelProperty(value = "表头信息")
private List<TableHeadersDto> columns;
public static <T> PageResult<T> success(List<T> data) public static <T> PageResult<T> success(List<T> data)
{ {
return setPageResult(data, SUCCESS, "成功"); return setPageResult(data, SUCCESS, "成功");
} }
public static <T> PageResult<T> successColumns(List<T> data) {
return setPageResultAndHeader(data, SUCCESS, "成功");
}
public static <T> PageResult<T> fail(List<T> data, String msg) public static <T> PageResult<T> fail(List<T> data, String msg)
{ {
return setPageResult(data, FAIL, msg); return setPageResult(data, FAIL, msg);
@@ -67,4 +75,43 @@ public class PageResult<T> implements Serializable
rspData.setMsg("查询成功"); rspData.setMsg("查询成功");
return rspData; return rspData;
} }
private static <T> PageResult<T> setPageResultAndHeader(List<T> data, int code, String msg) {
List<TableHeadersDto> columns = new ArrayList<>();
columns.add(TableHeadersDto.builder()
.key("model")
.label("型号")
.type("text")
.fixed("left")
.width(100)
.build());
columns.add(TableHeadersDto.builder()
.key("price")
.label("价格")
.type("amount")
.width(100)
.build());
columns.add(TableHeadersDto.builder()
.key("monthIncome")
.label("最大月收益")
.type("amount")
.currency("USDT")
.period("MONTH")
.width(110)
.build());
columns.add(TableHeadersDto.builder()
.key("maxLeaseDays")
.label("最大租赁天数")
.type("days")
.width(80)
.build());
PageResult<T> rspData = new PageResult<T>();
rspData.setColumns(columns);
rspData.setCode(SUCCESS);
rspData.setRows(data);
rspData.setMsg("查询成功");
return rspData;
}
} }

View File

@@ -8,6 +8,8 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/** /**
* <p> * <p>
* 店铺商品配置返回对象 * 店铺商品配置返回对象
@@ -43,4 +45,10 @@ public class PayConfigDto {
private Long shopId; private Long shopId;
@ApiModelProperty(value = "起付金额")
private BigDecimal deductibleAmount;
@ApiModelProperty(value = "手续费")
private BigDecimal fee;
} }

View File

@@ -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.util.List;
/**
* @Description 店铺支持的支付方式
* @Date 2024/6/14 15:57
* @Author dy
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "店铺支持的支付方式",value = "PayTypeDto")
public class PayTypeDto {
@ApiModelProperty(value = "店铺id(不展示)")
private Long shopId;
@ApiModelProperty(value = "")
private String chain;
@ApiModelProperty(value = "支付币种")
private String coin;
@ApiModelProperty(value = "支付币种图标")
private String image;
}

View File

@@ -1,6 +1,5 @@
package com.m2pool.lease.dto; package com.m2pool.lease.dto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -9,7 +8,6 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
/** /**
* <p> * <p>

View File

@@ -27,14 +27,15 @@ public class ProductDto {
@ApiModelProperty(value = "商品id") @ApiModelProperty(value = "商品id")
private Long id; private Long id;
/** /**
* 店铺id * 店铺id
*/ */
@ApiModelProperty(value = "店铺id") @ApiModelProperty(value = "店铺id")
private Long shopId; private Long shopId;
@ApiModelProperty(value = "店铺名称")
private String shopName;
/** /**
* 商品名称 * 商品名称
*/ */
@@ -59,19 +60,18 @@ public class ProductDto {
@ApiModelProperty(value = "上下架状态0 上架1 下架") @ApiModelProperty(value = "上下架状态0 上架1 下架")
private Integer state; private Integer state;
/**
* 商品机器单机算力(卖方手动填写)
*/
//@ApiModelProperty(value = "商品机器单机理论算力(卖方手动填写)")
//private BigDecimal power;
/** /**
* 库存中机器价格范围 * 库存中机器价格范围
*/ */
@ApiModelProperty(value = "价格范围") @ApiModelProperty(value = "价格范围")
@Deprecated
private String priceRange; private String priceRange;
@ApiModelProperty(value = "店铺支持的支付方式")
private List<PayTypeDto> payTypes;
/** /**
* 算法 * 算法
*/ */
@@ -83,34 +83,6 @@ public class ProductDto {
*/ */
@ApiModelProperty(value = "商品描述") @ApiModelProperty(value = "商品描述")
private String description; 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 * 矿机挖矿币种 nexa rxd dgbo dgbq dgbs alph enx grs mona
*/ */

View File

@@ -0,0 +1,71 @@
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;
/**
* <p>
* 钱包配置修改商品支付方式返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "钱包配置修改商品支付方式返回对象",value = "ProductForWalletConfigDto" )
public class ProductForWalletConfigDto {
@ApiModelProperty(value = "商品id")
private Long productId;
/**
* 商品名称
*/
@ApiModelProperty(value = "商品名称")
private String name;
/**
* 商品图片路径
*/
@ApiModelProperty(value = "商品图片路径")
private String image;
/**
* 上下架状态0 上架1 下架
*/
@ApiModelProperty(value = "上下架状态0 上架1 下架")
private Integer state;
/**
* 算法
*/
@ApiModelProperty(value = "算法")
private String algorithm;
/**
* 商品描述
*/
@ApiModelProperty(value = "商品描述")
private String description;
/**
* 矿机挖矿币种 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 Integer totalMachineNumber;
@ApiModelProperty(value = "矿机列表")
private List<ProductMachineForWalletConfigDto> machineList;
}

View File

@@ -9,6 +9,7 @@ import lombok.NoArgsConstructor;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
/** /**
* <p> * <p>
@@ -28,66 +29,44 @@ public class ProductMachineDto {
@ApiModelProperty(value = "矿机ID") @ApiModelProperty(value = "矿机ID")
private Long id; private Long id;
@ApiModelProperty(value = "购物车详情id")
private Long cartInfoId;
@ApiModelProperty(value = "店铺id") @ApiModelProperty(value = "店铺id")
private Long shopId; private Long shopId;
/**
* 商品 ID
*/
@ApiModelProperty(value = "商品 ID") @ApiModelProperty(value = "商品 ID")
private Long productId; private Long productId;
/**
* 挖矿机器 对应的矿工账号
*/
@ApiModelProperty(value = "挖矿机器 对应的矿工账号") @ApiModelProperty(value = "挖矿机器 对应的矿工账号")
private String user; private String user;
/**
* 挖矿机器型号
*/
@ApiModelProperty(value = "挖矿机器型号") @ApiModelProperty(value = "挖矿机器型号")
private String type; private String type;
/**
* 挖矿机器编号
*/
@ApiModelProperty(value = "挖矿机器编号") @ApiModelProperty(value = "挖矿机器编号")
private String miner; private String miner;
/**
* 单价
*/
@ApiModelProperty(value = "单价") @ApiModelProperty(value = "单价")
private BigDecimal price; private BigDecimal price;
/**
* 实际算力(计算得到,商家不能够自己添加和修改)
*/
@ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)") @ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)")
private BigDecimal computingPower; private BigDecimal computingPower;
/**
* 理论算力
*/
@ApiModelProperty(value = "理论算力(卖方手动填写)") @ApiModelProperty(value = "理论算力(卖方手动填写)")
private BigDecimal theoryPower; private BigDecimal theoryPower;
@ApiModelProperty(value = "算力单位") @ApiModelProperty(value = "算力单位")
private String unit; private String unit;
/**
* 上下架状态0 上架1 下架
*/
@ApiModelProperty(value = "上下架状态0 上架1 下架") @ApiModelProperty(value = "上下架状态0 上架1 下架")
private Integer state; private Integer state;
/**
* 售出状态 0未售出 1已售出 2售出中
*/
@ApiModelProperty(value = "售出状态 0未售出 1已售出 2售出中") @ApiModelProperty(value = "售出状态 0未售出 1已售出 2售出中")
private Integer saleState; private Integer saleState;
@@ -97,9 +76,7 @@ public class ProductMachineDto {
@ApiModelProperty(value = "机器算力最近记录的一次时间") @ApiModelProperty(value = "机器算力最近记录的一次时间")
private LocalDateTime endTime; private LocalDateTime endTime;
/**
* 单机理论收入
*/
@ApiModelProperty(value = "单机理论收入(每日) 单位币种") @ApiModelProperty(value = "单机理论收入(每日) 单位币种")
private BigDecimal theoryIncome; private BigDecimal theoryIncome;
@@ -109,12 +86,6 @@ public class ProductMachineDto {
@ApiModelProperty(value = "租赁天数") @ApiModelProperty(value = "租赁天数")
private Integer leaseTime; private Integer leaseTime;
/**
* 单机预估实际收入
*/
//@ApiModelProperty(value = "单机预估实际收入(每日)")
//private BigDecimal actualIncome;
@ApiModelProperty(value = "算法") @ApiModelProperty(value = "算法")
private String algorithm; private String algorithm;
@@ -124,7 +95,7 @@ public class ProductMachineDto {
@ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7") @ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7")
private Integer maxLeaseDays; private Integer maxLeaseDays;
@ApiModelProperty(value = "币种") @ApiModelProperty(value = "挖矿机器挖矿币种")
private String coin; private String coin;
@ApiModelProperty(value = "商品名称") @ApiModelProperty(value = "商品名称")
@@ -132,4 +103,11 @@ public class ProductMachineDto {
@ApiModelProperty(value = "是否删除 0否 1是") @ApiModelProperty(value = "是否删除 0否 1是")
private Integer del; private Integer del;
@ApiModelProperty(value = "支付币种")
private String payCoin;
@ApiModelProperty(value = "售价集合")
private List<MachinePayTypeDto> priceList;
} }

View File

@@ -0,0 +1,105 @@
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;
/**
* <p>
* 商品对应实际商品返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "钱包配置修改矿机支付方式返回对象",value = "ProductMachineForWalletConfigDto" )
public class ProductMachineForWalletConfigDto {
@ApiModelProperty(value = "矿机ID")
private Long productMachineId;
@ApiModelProperty(value = "商品ID")
private Long productId;
/**
* 挖矿机器 对应的矿工账号
*/
@ApiModelProperty(value = "挖矿机器 对应的矿工账号")
private String user;
/**
* 挖矿机器型号
*/
@ApiModelProperty(value = "挖矿机器型号")
private String type;
/**
* 挖矿机器编号
*/
@ApiModelProperty(value = "挖矿机器编号")
private String miner;
@ApiModelProperty(value = "挖矿币种")
private String coin;
///**
// * 实际算力(计算得到,商家不能够自己添加和修改)
// */
//@ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)")
//private BigDecimal computingPower;
@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 = "理论算力(卖方手动填写)")
private BigDecimal theoryPower;
@ApiModelProperty(value = "单机理论收入(每日) 单位币种")
private BigDecimal theoryIncome;
@ApiModelProperty(value = "单机理论收入(每日) 单位USDT")
private BigDecimal theoryUsdtIncome;
@ApiModelProperty(value = "功耗 单位kw/h",example = "10")
private BigDecimal powerDissipation;
/**
* 单价
*/
@ApiModelProperty(value = "单价")
private BigDecimal price;
@ApiModelProperty(value = "支付链")
private BigDecimal chain;
@ApiModelProperty(value = "支付币种")
private BigDecimal symbol;
}

View File

@@ -0,0 +1,51 @@
package com.m2pool.lease.dto;
import com.m2pool.lease.annotation.EncryptedField;
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;
/**
* <p>
* 商品对应实际商品返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "钱包配置修改矿机支付方式请求对象",value = "ProductMachineForWalletConfigVo" )
public class ProductMachineForWalletConfigVo {
@ApiModelProperty(value = "钱包地址")
@EncryptedField
private String payAddress;
@ApiModelProperty(value = "支付链")
private String chain;
@ApiModelProperty(value = "支付币种,可以多个以逗号隔开")
private String symbol;
@ApiModelProperty(value = "价格列表")
private List<PriceVo> productMachineForWalletConfigVoList;
@Data
@ApiModel(description = "币(二级) 下拉列表返回对象",value = "PriceVo")
public static class PriceVo{
@ApiModelProperty(value = "矿机ID")
private Long productMachineId;
@ApiModelProperty(value = "单价,可以多个以逗号隔开")
private String price;
}
}

View File

@@ -31,4 +31,6 @@ public class ProductMachineInfoDto {
@ApiModelProperty(value = "矿机范围及矿机详情返回对象") @ApiModelProperty(value = "矿机范围及矿机详情返回对象")
private List<ProductMachineRangeInfoDto> machineRangeInfoList; private List<ProductMachineRangeInfoDto> machineRangeInfoList;
} }

View File

@@ -9,6 +9,7 @@ import lombok.NoArgsConstructor;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
/** /**
* <p> * <p>
@@ -50,8 +51,8 @@ public class ProductUpdateMachineDto {
/** /**
* 单价 * 单价
*/ */
@ApiModelProperty(value = "单价") @ApiModelProperty(value = "售价集合")
private BigDecimal price; private List<MachinePayTypeDto> priceList;
/** /**
* 实际算力(计算得到,商家不能够自己添加和修改) * 实际算力(计算得到,商家不能够自己添加和修改)
@@ -59,7 +60,6 @@ public class ProductUpdateMachineDto {
@ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)") @ApiModelProperty(value = "3天算力平均大小---实际实时算力(计算得到,商家不能够自己添加和修改)")
private BigDecimal computingPower; private BigDecimal computingPower;
/** /**
* 理论算力 * 理论算力
*/ */

View File

@@ -38,12 +38,12 @@ public class ShopCartDto {
@ApiModelProperty(value = "店铺下机器总数") @ApiModelProperty(value = "店铺下机器总数")
private Integer totalMachine; private Integer totalMachine;
@ApiModelProperty(value = "总价集合")
private List<MachineTotalPriceDto> totalPriceList;
@ApiModelProperty(value = "商品支持的支付地址") @ApiModelProperty(value = "商品支持的支付地址")
private List<PayConfigDto> payConfigList; private List<PayConfigDto> payConfigList;
//@ApiModelProperty(value = "购物车二层商品列表返回对象")
//List<ShoppingCartInfoDto> shoppingCartInfoDtoList;
@ApiModelProperty(value = "商品机器列表") @ApiModelProperty(value = "商品机器列表")
List<ProductMachineDto> productMachineDtoList; List<ProductMachineDto> productMachineDtoList;
} }

View File

@@ -8,6 +8,8 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/** /**
* <p> * <p>
* 店铺表 * 店铺表
@@ -54,4 +56,8 @@ public class ShopDto {
*/ */
@ApiModelProperty(value = "逻辑删除字段") @ApiModelProperty(value = "逻辑删除字段")
private Boolean del; private Boolean del;
@ApiModelProperty(value = "店铺手续费比例 范围0.01-0.1",example = "0.01")
private BigDecimal feeRate;
} }

View File

@@ -21,52 +21,20 @@ import java.util.List;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ApiModel(description = "购物车二层商品列表返回对象",value = "ShoppingCartInfoDto" ) @ApiModel(description = "购物车二层商品列表返回对象(不再使用)",value = "ShoppingCartInfoDto" )
public class ShoppingCartInfoDto { public class ShoppingCartInfoDto {
/**
* ID
*/
//@ApiModelProperty(value = "购物车详情ID")
//private Long id;
@ApiModelProperty(value = "店铺ID",example = "8")
private Long shopId;
/** /**
* 商品 ID * 商品 ID
*/ */
@ApiModelProperty(value = "商品 ID")
private Long productId; private Long productId;
/** /**
* 商品机器ID * 商品机器ID
*/ */
@ApiModelProperty(value = "商品机器ID")
private Long productMachineId; private Long productMachineId;
/** /**
* 商品名称 * 租期
*/ */
@ApiModelProperty(value = "商品名称") private Integer leaseTime;
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<ProductMachineDto> productMachineDtoList;
} }

View File

@@ -0,0 +1,66 @@
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;
/**
* @Description 表头信息
* @Date 2025/11/28 13:31
* @Author yyb
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "表头信息",value = "TableHeadersDto" )
public class TableHeadersDto {
/**
* 动态列第几列
*/
@ApiModelProperty(value = "动态列第几列")
private String key;
/**
* 列名
*/
@ApiModelProperty(value = "列名")
private String label;
/**
* 类型 text/amount/hashrate/days
*/
@ApiModelProperty(value = "类型 text/amount/hashrate/days")
private String type;
/**
* 固定列 left/right/不传
*/
@ApiModelProperty(value = "固定列 left/right/不传")
private String fixed;
@ApiModelProperty(value = "价格单位")
private String currency;
@ApiModelProperty(value = "时间间隔")
private String period;
/**
* 算力单位
*/
@ApiModelProperty(value = "算力单位")
private String unit;
@ApiModelProperty(value = "图标")
private String icon;
/**
* 宽度
*/
@ApiModelProperty(value = "宽度")
private Integer width;
}

View File

@@ -0,0 +1,30 @@
package com.m2pool.lease.dto.v2;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
* 商品列表分页请求对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "商品对应算法",value = "AlgorithmShopIdMapDto" )
public class AlgorithmShopIdMapDto {
@ApiModelProperty(value = "店铺id",example = "1")
private Long shopId;
@ApiModelProperty(value = "算法")
private String algorithm;
}

View File

@@ -0,0 +1,44 @@
package com.m2pool.lease.dto.v2;
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;
/**
* <p>
* 机器参数请求对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "asic 矿机新增 算力,币种返回对象",value = "AsicCoinAndAlgoDto" )
public class AsicCoinAndAlgoDto {
@ApiModelProperty(value = "币种算力配置id")
private Long coinAndPowerId;
@ApiModelProperty(value = "矿机id忽略")
private Long productMachineId;
@ApiModelProperty(value = "币种(多个逗号隔开)")
private String coin;
@ApiModelProperty(value = "算法(多个逗号隔开)")
private String algorithm;
@ApiModelProperty(value = "理论算力)",example = "0.01")
private BigDecimal theoryPower;
@ApiModelProperty(value = "商品机器单机算力单位",example = "TH/S")
private String unit;
}

View File

@@ -0,0 +1,108 @@
package com.m2pool.lease.dto.v2;
import com.m2pool.lease.dto.MachinePayTypeDto;
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;
/**
* <p>
* 商品对应实际商品返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "购物车列表返回对象",value = "CartMachineInfoDto" )
public class CartMachineInfoDto{
@ApiModelProperty(value = "矿机ID")
private Long id;
@ApiModelProperty(value = "购物车详情id")
private Long cartInfoId;
@ApiModelProperty(value = "店铺id")
private Long shopId;
@ApiModelProperty(value = " gpu名称型号 或asic 名称型号")
private String name;
@ApiModelProperty(value = "矿工账号 (gpu)")
private String user;
@ApiModelProperty(value = "矿机型号 0 ASIC 1 GPU")
private Integer type;
@ApiModelProperty(value = "矿机编号(gpu)")
private String miner;
@ApiModelProperty(value = "上下架状态0 上架1 下架")
private Integer state;
@ApiModelProperty(value = "售出状态 0未售出 1已售出")
private Integer saleState;
@ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7")
private Integer maxLeaseDays;
@ApiModelProperty(value = "是否删除 0否 1是")
private Integer del;
@ApiModelProperty(value = "最大月收益 usdt")
private BigDecimal monthIncome;
@ApiModelProperty(value = "最大收益币种功耗 单位kw/h",example = "10")
private BigDecimal powerDissipation;
@ApiModelProperty(value = "理论算力(卖方手动填写)")
private BigDecimal theoryPower;
@ApiModelProperty(value = "最大收益币种算力单位")
private String unit;
@ApiModelProperty(value = "最大收益币种算法")
private String algorithm;
@ApiModelProperty(value = "售价")
private BigDecimal price;
@ApiModelProperty(value = "最大收益对应币种")
private String coin;
@ApiModelProperty(value = "租赁天数")
private Integer leaseTime;
private Long configId;
@ApiModelProperty(value = "支付币种")
private String payCoin;
@ApiModelProperty(value = "asic 租赁数量")
private Integer numbers;
@ApiModelProperty(value = "矿机客户端在离线情况 0 离线 1 在线")
private Boolean onlineStatus;
@ApiModelProperty(value = "可售数量")
private Integer canSaleNumbers;
@ApiModelProperty(value = "gpu和asic对应币种算力和月收益信息")
private List<PowerIncomeInfoDto> powerIncomeInfoList;
@ApiModelProperty(value = "店铺售价集合")
private List<MachinePayTypeDto> priceList;
}

View File

@@ -0,0 +1,62 @@
package com.m2pool.lease.dto.v2;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CoinAndAlgorithmDto {
/**
* 币种名称
*/
private String coin;
/**
* 算法名称
*/
private String algorithm;
/**
* 矿机id,多个已逗号隔开
*/
private String machineIds;
/**
* 是否生效
*/
private Boolean isEffect;
/**
* gpu名称
*/
private String model;
/**
* gpu 功耗
*/
private BigDecimal powerDissipation;
/**
* gpu 理论算力
*/
private BigDecimal hashRate;
/**
* 月收入
*/
private BigDecimal monthIncome;
/**
* 是否新增 gpu 配置
*/
private Boolean isAdd;
}

View File

@@ -0,0 +1,39 @@
package com.m2pool.lease.dto.v2;
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;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "币种算法返回对象",value = "CoinAndAlgorithmListDto")
public class CoinAndAlgorithmListDto {
@ApiModelProperty(value = "币种")
private String coin;
@ApiModelProperty(value = "币种对应算法返回对象")
private List<AlgorithmListDto> algorithmList;
@Data
@ApiModel(description = "币种对应算法返回对象",value = "AlgorithmListDto")
public static class AlgorithmListDto{
@ApiModelProperty(value = "算法")
private String algorithm;
@ApiModelProperty(value = "支持该算法的矿机id集合")
private List<Long> machineIds;
}
}

View File

@@ -0,0 +1,15 @@
package com.m2pool.lease.dto.v2;
import lombok.Data;
import java.io.Serializable;
@Data
public class GoogleInfoDto implements Serializable {
/** 谷歌验证码 */
private String secret;
/** 二维码 */
private String img;
}

View File

@@ -0,0 +1,39 @@
package com.m2pool.lease.dto.v2;
import com.m2pool.lease.dto.MachinePayTypeDto;
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;
/**
* <p>
* 商品对应实际商品返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "gpu公共配置返回对象",value = "GpuConfigDto" )
public class GpuConfigDto {
@ApiModelProperty(value = "gpu名称/型号")
private String name;
@ApiModelProperty(value = "gpu品牌")
private String brand;
private Integer memory;
}

View File

@@ -0,0 +1,66 @@
package com.m2pool.lease.dto.v2;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import lombok.*;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* <p>
* GPU对应币种挖矿算力(只要gpu类型相同那么就使用这个配置)
* </p>
*
* @author yyb
* @since 2025-11-27
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MachineConfigDto {
private Long id;
/**
* 机器id
*/
private Long machineId;
/**
* gpu/asic品牌
*/
private String brand;
/**
* gpu 名称/型号
*/
private String name;
/**
* 内存单位M
*/
private Integer memory;
/**
* 支持的币种
*/
private String coin;
/**
* 算法
*/
private String algorithm;
/**
* 是否是临时信息
*/
private Boolean isTemp;
}

View File

@@ -0,0 +1,15 @@
package com.m2pool.lease.dto.v2;
import lombok.Data;
/**
* @Description 矿机是否能够上架
* @Date 2025/12/12 14:41
* @Author yyb
*/
@Data
public class MachineEffectDto {
private Long machineId;
private Integer effect;
}

View File

@@ -0,0 +1,27 @@
package com.m2pool.lease.dto.v2;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* <p>
* 商品列表分页请求对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MachineHashRateMapDto {
private Long machineId;
private BigDecimal hashRate;
}

View File

@@ -0,0 +1,101 @@
package com.m2pool.lease.dto.v2;
import com.m2pool.lease.dto.MachinePayTypeDto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.math.BigDecimal;
import java.util.List;
/**
* <p>
* 商品对应实际商品返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "矿机返回对象",value = "MachineInfoDto" )
public class MachineInfoDto {
private Integer type;
private BigDecimal theoryPower;
@ApiModelProperty(value = "矿机ID")
private Long id;
@ApiModelProperty(value = "gpu名称 或asic 名称")
private String model;
@ApiModelProperty(value = "矿机mac地址")
private String hostMac;
@ApiModelProperty(value = "上下架状态0 上架1 下架")
private Integer state;
@ApiModelProperty(value = "售出状态 0未售出 1已售出")
private Integer saleState;
@ApiModelProperty(value = "最大可租借天数(默认七天)",example = "7")
private Integer maxLeaseDays;
@ApiModelProperty(value = "最大月收益 usdt")
private BigDecimal monthIncome;
@ApiModelProperty(value = "最大收益币种算法")
private String algorithm;
@ApiModelProperty(value = "售价")
private BigDecimal price;
@ApiModelProperty(value = "最大收益对应币种")
private String coin;
@ApiModelProperty(value = "矿机客户端在离线情况 0 离线 1 在线")
private Boolean onlineStatus;
@ApiModelProperty(value = "可出售机器数量")
private Integer saleNumbers;
@ApiModelProperty(value = "已售出数量")
private Integer saleOutNumbers;
//动态列名(方便前端显示)
private String c1;
private String c2;
private String c3;
private String c4;
private String c5;
private String c6;
private String c7;
private String c8;
private String c9;
private String c10;
//@ApiModelProperty(value = "币种动态列集合")
//private List<PowerIncomeInfoDto> powerIncomeInfoList;
@ApiModelProperty(value = "店铺售价集合")
private List<MachinePayTypeDto> priceList;
}

View File

@@ -0,0 +1,14 @@
package com.m2pool.lease.dto.v2;
import java.math.BigDecimal;
import java.util.List;
public interface MachineInfoInterface {
Integer getType();
Long getId();
String getCoin();
String getAlgorithm();
BigDecimal getTheoryPower();
BigDecimal getMonthIncome();
void setPowerIncomeInfoList(List<PowerIncomeInfoDto> powerIncomeInfoList);
}

View File

@@ -0,0 +1,43 @@
package com.m2pool.lease.dto.v2;
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;
/**
* @Description 矿机对应的矿池配置信息
* @Date 2025/11/26 14:19
* @Author yyb
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "矿池对应币种返回对象",value = "MiningCoinInfoDto" )
public class MiningCoinInfoDto {
@ApiModelProperty(value = "矿池配置id")
private Long coinConfigId;
@ApiModelProperty(value = "挖矿币种")
private String coin;
@ApiModelProperty(value = "挖矿算法")
private String algorithm;
@ApiModelProperty(value = "挖矿地址 TCP GPU")
private String miningTcpGpuUrl;
@ApiModelProperty(value = "分配模式名")
private String modelName;
@ApiModelProperty(value = "分配模式手续费")
private BigDecimal modelFee;
@ApiModelProperty(value = "是否支持钱包支付0 不支持 1 支持")
private Boolean walletMining;
}

View File

@@ -0,0 +1,48 @@
package com.m2pool.lease.dto.v2;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Description 矿机对应的矿池配置信息
* @Date 2025/11/26 14:19
* @Author yyb
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MiningConfigDto {
private Long id;
@ApiModelProperty(value = "挖矿币种")
private String coin;
@ApiModelProperty(value = "挖矿算法")
private String algo;
@ApiModelProperty(value = "矿池名称")
private String pool;
@ApiModelProperty(value = "是否支持钱包挖矿 0 不支持 1支持")
private Boolean wallet_mining;
@ApiModelProperty(value = "挖矿地址")
private String pool_url;
@ApiModelProperty(value = "收款钱包")
private String wallet_address;
@ApiModelProperty(value = "挖矿账户")
private String pool_user;
@ApiModelProperty(value = "矿工号")
private String worker_id;
@ApiModelProperty(value = "挖矿结束时间")
private Long end_timestamp;
}

View File

@@ -0,0 +1,56 @@
package com.m2pool.lease.dto.v2;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import scala.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 挖矿中订单
* </p>
*
* @author yyb
* @since 2025-12-02
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "已购商品挖矿配置详情返回对象",value = "MiningConfigInfoDto" )
public class MiningConfigInfoDto {
@ApiModelProperty(value = "矿池所挖币种")
private String coin;
@ApiModelProperty(value = "币种对应算法")
private String algorithm;
@ApiModelProperty(value = "矿池名称")
private String pool;
@ApiModelProperty(value = "矿池挖矿地址")
private String poolUrl;
@ApiModelProperty(value = "矿池挖矿账户")
private String poolUser;
@ApiModelProperty(value = "收款钱包")
private String walletAddress;
@ApiModelProperty(value = "挖矿信息页面地址")
private String watchUrl;
@ApiModelProperty(value = "已购矿机信息")
private List<PurchasedMachineDto> purchasedMachines;
}

View File

@@ -0,0 +1,49 @@
package com.m2pool.lease.dto.v2;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @Description 矿机对应的矿池配置信息
* @Date 2025/11/26 14:19
* @Author yyb
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MiningConfigSelectDto {
@ApiModelProperty(value = "矿池配置id")
private Long coinConfigId;
@ApiModelProperty(value = "矿池id")
private Long poolId;
@ApiModelProperty(value = "挖矿币种")
private String coin;
@ApiModelProperty(value = "挖矿算法")
private String algorithm;
@ApiModelProperty(value = "矿池名称")
private String poolName;
@ApiModelProperty(value = "是否支持钱包支付0 不支持 1 支持")
private Boolean walletMining;
@ApiModelProperty(value = "挖矿地址 TCP GPU")
private String miningTcpGpuUrl;
@ApiModelProperty(value = "分配模式名")
private String modelName;
@ApiModelProperty(value = "分配模式手续费")
private BigDecimal modelFee;
}

View File

@@ -0,0 +1,36 @@
package com.m2pool.lease.dto.v2;
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;
/**
* <p>
* GPU对应币种挖矿算力(只要gpu类型相同那么就使用这个配置)
* </p>
*
* @author yyb
* @since 2025-11-27
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "矿机对应实时算力放回对象",value = "MiningHashrateInfoDto" )
public class MiningHashrateInfoDto {
@ApiModelProperty(value = "实时算力")
private BigDecimal power;
@ApiModelProperty(value = "最近实时算力记录时间")
private LocalDateTime recordTime;
@ApiModelProperty(value = "矿工号")
private String miner;
}

View File

@@ -0,0 +1,31 @@
package com.m2pool.lease.dto.v2;
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 2025/11/26 14:19
* @Author yyb
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "矿池列表返回对象",value = "MiningInfoDto" )
public class MiningInfoDto {
@ApiModelProperty(value = "矿池id")
private Long poolId;
@ApiModelProperty(value = "矿池名称")
private String poolName;
@ApiModelProperty(value = "矿池支持对应币种信息")
private List<MiningCoinInfoDto> miningCoinInfoList;
}

View File

@@ -0,0 +1,48 @@
package com.m2pool.lease.dto.v2;
import com.m2pool.lease.annotation.EncryptedField;
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 2025/11/26 14:19
* @Author yyb
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "矿池列表返回对象",value = "OrderMiningInfoDto" )
public class OrderMiningInfoDto {
@ApiModelProperty(value = "矿池名称")
private String poolName;
@ApiModelProperty(value = "矿池配置id")
private Long coinConfigId;
@ApiModelProperty(value = "是否钱包挖矿 0 不支持 1 支持")
private Boolean walletMining;
@ApiModelProperty(value = "矿机id")
private Long machineId;
@ApiModelProperty(value = "挖矿钱包(用户自己输入)")
@EncryptedField
private String walletAddress;
@ApiModelProperty(value = "挖矿账号(用户自己输入)")
private String poolUser;
@ApiModelProperty(value = "矿工号(用户自己输入)")
private String workerId;
@ApiModelProperty(value = "挖矿钱包币种")
private String coin;
}

View File

@@ -0,0 +1,39 @@
package com.m2pool.lease.dto.v2;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
/**
* <p>
* 订单状态修改返回对象
* </p>
*
* @author yyb
* @since 2025-07-23
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderTimeInfoDto {
private Long id;
private Long orderId;
private Long orderItemId;
private Integer leaseTime;
private LocalDateTime startTime;
private BigDecimal price;
private Integer numbers;
}

Some files were not shown because too many files have changed in this diff Show More