274 lines
7.8 KiB
Go
274 lines
7.8 KiB
Go
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("👋 服务已全部关闭")
|
||
}
|