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 } // 记录 RMQ -> Listen 充值请求 logger.LogRmqToListenTopupReq(msg.QueueId, msg.Chain, msg.Symbol, msg.Address, msg.Timestamp) 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 } // 记录 RMQ -> Listen 提现请求 logger.LogRmqToListenWithdrawReq(msg.QueueId, msg.Chain, msg.Symbol, msg.FromAddress, msg.ToAddress, msg.Amount, msg.Fee, msg.Timestamp) 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 } // 记录 RMQ -> Listen 支付请求 logger.LogRmqToListenPayReq(msg.QueueId, msg.Chain, msg.Symbol, msg.FromAddress, msg.ToAddress, msg.Amount, msg.Fee, msg.Timestamp) 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 } // 记录 RMQ -> Listen 移除监听请求 logger.LogRmqToListenRemoveReq(msg.QueueId, msg.MsgType, msg.Chain, msg.Symbol, msg.Address, msg.Timestamp) 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) // 记录 Listen -> RMQ 充值响应 logger.LogListenToRmqTopupResp(v.QueueId, v.Chain, v.Symbol, v.Address, v.FromAddress, v.TxHash, v.Amount, v.BlockHeight, v.Status) 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) // 记录 Listen -> RMQ 提现响应 logger.LogListenToRmqWithdrawResp(v.QueueId, v.Chain, v.Symbol, v.FromAddress, v.ToAddress, v.TxHash, v.Amount, v.Fee, v.BlockHeight, v.Status) 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) // 记录 Listen -> RMQ 支付响应 logger.LogListenToRmqPayResp(v.QueueId, v.Chain, v.Symbol, v.FromAddress, v.ToAddress, v.TxHash, v.Amount, v.Fee, v.BlockHeight, 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) // 记录 Listen -> RMQ 移除监听响应 logger.LogListenToRmqRemoveResp(v.QueueId, v.MsgType, v.Chain, v.Symbol, v.Address, 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("👋 服务已全部关闭") }