Files
m2pool_payment/internal/server.go
2025-11-14 17:43:25 +08:00

274 lines
7.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package server
import (
"encoding/hex"
"encoding/json"
"fmt"
"log"
"m2pool-payment/internal/blockchain"
"m2pool-payment/internal/blockchain/eth"
"m2pool-payment/internal/constant"
"m2pool-payment/internal/crypto"
"m2pool-payment/internal/listen"
"m2pool-payment/internal/logger"
message "m2pool-payment/internal/msg"
rmq "m2pool-payment/internal/queue"
"os"
"os/signal"
"strings"
"syscall"
)
type ServerCtx struct {
msgKey string // 解密msg-sign的密钥启动命令参数传入
Config message.Config
blockChainServer *blockchain.BlockChainServer
rmqServer *rmq.RabbitMQServer
messageServer *listen.ListenServer
}
func loadConfig() message.Config {
file, err := os.ReadFile("config.json")
if err != nil {
panic(fmt.Sprintf("读取配置文件失败: %v", err))
}
var result message.Config
err = json.Unmarshal(file, &result)
if err != nil {
panic(fmt.Sprintf("解析配置文件失败: %v", err))
}
return result
}
func NewServer(msgKey string) *ServerCtx {
cfg := loadConfig()
l := listen.NewListenServer(cfg)
eth_node, err := eth.NewETHNode(cfg, msgKey, l)
if err != nil {
panic(err)
}
node_server := blockchain.NewBlockChainServer()
node_server.RegisterChain("ETH", eth_node)
rmq_server, err := rmq.NewRabbitMQServer(cfg.RmqConfig)
if err != nil {
panic(err)
}
return &ServerCtx{
msgKey: msgKey,
Config: cfg,
blockChainServer: node_server,
rmqServer: rmq_server,
messageServer: l,
}
}
// verifyMessage 验证消息签名
func (s *ServerCtx) verifyMessage(timestamp uint64, sign string) bool {
hash_byte := crypto.Sha256Hash(fmt.Sprintf("%x", timestamp) + s.msgKey)
hash := hex.EncodeToString(hash_byte)
return hash == sign
}
func (s *ServerCtx) handleTopupMsg() {
s.rmqServer.OnTopupMsg = func(msg message.TopupMsg_req) {
msg.Address = strings.ToLower(msg.Address)
// 验证签名
if !s.verifyMessage(msg.Timestamp, msg.Sign) {
err := s.rmqServer.PublishTopupResp(message.TopupMsg_resp{
QueueId: msg.QueueId,
Address: msg.Address,
Status: constant.STATUS_VERIFY_FAILED,
Chain: msg.Chain,
Symbol: msg.Symbol,
})
if err != nil {
log.Printf("❌ 发布充值失败响应失败: %v", err)
}
return
}
s.messageServer.ChFromRmqServer <- msg
}
}
func (s *ServerCtx) handleWithdrawMsg() {
s.rmqServer.OnWithdrawMsg = func(msg message.WithdrawMsg_req) {
msg.FromAddress = strings.ToLower(msg.FromAddress)
msg.ToAddress = strings.ToLower(msg.ToAddress)
// 验证签名
if !s.verifyMessage(msg.Timestamp, msg.Sign) {
err := s.rmqServer.PublishWithdrawResp(message.WithdrawMsg_resp{
QueueId: msg.QueueId,
Chain: msg.Chain,
Symbol: msg.Symbol,
Status: constant.STATUS_VERIFY_FAILED,
FromAddress: msg.FromAddress,
ToAddress: msg.ToAddress,
})
if err != nil {
log.Printf("❌ 发布提现失败响应失败: %v", err)
}
return
}
s.messageServer.ChFromRmqServer <- msg
}
}
func (s *ServerCtx) handlePayMsg() {
s.rmqServer.OnPayMsg = func(msg message.PayMsg_req) {
msg.FromAddress = strings.ToLower(msg.FromAddress)
// 验证签名
if !s.verifyMessage(msg.Timestamp, msg.Sign) {
err := s.rmqServer.PublishPayResp(message.PayMsg_resp{
QueueId: msg.QueueId,
FromAddress: msg.FromAddress,
Status: constant.STATUS_VERIFY_FAILED,
})
if err != nil {
log.Printf("❌ 发布支付失败响应失败: %v", err)
}
return
}
s.messageServer.ChFromRmqServer <- msg
}
}
func (s *ServerCtx) handleRemoveMsg() {
s.rmqServer.OnRemoveMsg = func(msg message.RemoveListenMsg_req) {
msg.Address = strings.ToLower(msg.Address)
// 验证签名
if !s.verifyMessage(msg.Timestamp, msg.Sign) {
err := s.rmqServer.PublishRemoveResp(message.RemoveListenMsg_resp{
QueueId: msg.QueueId,
MsgType: msg.MsgType,
Chain: msg.Chain,
Symbol: msg.Symbol,
Address: msg.Address,
Status: constant.STATUS_VERIFY_FAILED,
})
if err != nil {
log.Printf("❌ 发布移除监听失败响应失败: %v", err)
}
return
}
s.messageServer.ChFromRmqServer <- msg
}
}
func (s *ServerCtx) handleRespMsg() {
for msg := range s.messageServer.ChToRmqServer {
switch v := msg.(type) {
case message.TopupMsg_resp:
log.Printf("📨[充值响应]QueueID=%s, Address=%s, Chain=%s, Symbol=%s, TxHash=%s, Status=%d, Amount=%f", v.QueueId, v.Address, v.Chain, v.Symbol, v.TxHash, v.Status, v.Amount)
err := s.rmqServer.PublishTopupResp(v)
if err != nil {
log.Printf("❌ 发送充值响应失败: %v", err)
return
}
case message.WithdrawMsg_resp:
log.Printf("📨[提现响应]QueueID=%s, Chain=%s, Symbol=%s, FromAddress=%s, ToAddress=%s, TxHash=%s, Status=%d, Amount=%f", v.QueueId, v.Chain, v.Symbol, v.FromAddress, v.ToAddress, v.TxHash, v.Status, v.Amount)
err := s.rmqServer.PublishWithdrawResp(v)
if err != nil {
log.Printf("❌ 发送提现响应失败: %v", err)
return
}
case message.PayMsg_resp:
log.Printf("📨[提现响应]QueueID=%s, Chain=%s, Symbol=%s, FromAddress=%s, Status=%d", v.QueueId, v.Chain, v.Symbol, v.FromAddress, v.Status)
err := s.rmqServer.PublishPayResp(v)
if err != nil {
log.Printf("❌ 发送支付响应失败: %v", err)
return
}
case message.RemoveListenMsg_resp:
log.Printf("📨[充值响应]QueueID=%s, Address=%s, Chain=%s, Symbol=%s,Status=%d", v.QueueId, v.Address, v.Chain, v.Symbol, v.Status)
err := s.rmqServer.PublishRemoveResp(v)
if err != nil {
log.Printf("❌ 发送移除监听响应失败: %v", err)
return
}
default:
log.Printf("❌ 错误响应结构: %v", v)
return
}
}
}
func (s *ServerCtx) initDB() {
// msgDB_path := s.Config.MsgConfig.SqlitePath
// ethDB_path := s.Config.ETHConfig.SqlitePath
msg_sql_script_path := "../public/msg.sql"
msg_sql_byte, err := os.ReadFile(msg_sql_script_path)
if err != nil {
log.Fatalf("open msg-sql file error: %v", err)
return
}
err = s.messageServer.SqliteDB.CreateTable(string(msg_sql_byte))
if err != nil {
log.Fatalf("exec msg-sql error: %v", err)
return
}
}
func Start(msgKey string) {
log.Println("========================================")
log.Println("🚀 M2Pool Payment System Starting...")
log.Println("========================================")
server := NewServer(msgKey)
server.initDB()
// 启动消息处理
go server.handleTopupMsg()
go server.handleWithdrawMsg()
go server.handlePayMsg()
go server.handleRemoveMsg()
go server.handleRespMsg()
// 启动 RabbitMQ 服务
if err := server.rmqServer.Start(); err != nil {
log.Fatalf("❌ 启动 RabbitMQ 服务失败: %v", err)
}
log.Println("✅ RabbitMQ 服务启动成功")
// 启动消息服务器监听
go server.messageServer.RmqMsgIn()
go server.messageServer.NetMsgIn()
log.Println("✅ 消息服务器监听启动成功")
// 启动区块链监听
if err := server.blockChainServer.Listen("ETH", nil); err != nil {
log.Fatalf("❌ 启动区块链监听失败: %v", err)
}
log.Println("✅ 区块链监听启动成功")
// 启动区块链消息监听
if err := server.blockChainServer.ListenMsg("ETH"); err != nil {
log.Fatalf("❌ 启动区块链消息监听失败: %v", err)
}
log.Println("✅ 区块链消息监听启动成功")
log.Println("========================================")
log.Println("🎉 所有服务启动完成!")
log.Println("========================================")
// ================== 等待退出信号 ==================
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
// 优雅关闭
log.Println("========================================")
log.Println("🛑 收到退出信号,正在关闭服务...")
log.Println("========================================")
server.blockChainServer.Stop("ETH")
server.rmqServer.Close()
logger.CloseTransactionLogger()
log.Println("👋 服务已全部关闭")
}