1523 lines
65 KiB
HTML
1523 lines
65 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>M2Pool Payment System v2</title>
|
||
<style>
|
||
/* From extension vscode.github */
|
||
/*---------------------------------------------------------------------------------------------
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||
*--------------------------------------------------------------------------------------------*/
|
||
|
||
.vscode-dark img[src$=\#gh-light-mode-only],
|
||
.vscode-light img[src$=\#gh-dark-mode-only],
|
||
.vscode-high-contrast:not(.vscode-high-contrast-light) img[src$=\#gh-light-mode-only],
|
||
.vscode-high-contrast-light img[src$=\#gh-dark-mode-only] {
|
||
display: none;
|
||
}
|
||
|
||
</style>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex/dist/katex.min.css">
|
||
<link href="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css" rel="stylesheet" type="text/css">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
|
||
<style>
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', system-ui, 'Ubuntu', 'Droid Sans', sans-serif;
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
}
|
||
</style>
|
||
<style>
|
||
.task-list-item {
|
||
list-style-type: none;
|
||
}
|
||
|
||
.task-list-item-checkbox {
|
||
margin-left: -20px;
|
||
vertical-align: middle;
|
||
pointer-events: none;
|
||
}
|
||
</style>
|
||
<style>
|
||
:root {
|
||
--color-note: #0969da;
|
||
--color-tip: #1a7f37;
|
||
--color-warning: #9a6700;
|
||
--color-severe: #bc4c00;
|
||
--color-caution: #d1242f;
|
||
--color-important: #8250df;
|
||
}
|
||
|
||
</style>
|
||
<style>
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--color-note: #2f81f7;
|
||
--color-tip: #3fb950;
|
||
--color-warning: #d29922;
|
||
--color-severe: #db6d28;
|
||
--color-caution: #f85149;
|
||
--color-important: #a371f7;
|
||
}
|
||
}
|
||
|
||
</style>
|
||
<style>
|
||
.markdown-alert {
|
||
padding: 0.5rem 1rem;
|
||
margin-bottom: 16px;
|
||
color: inherit;
|
||
border-left: .25em solid #888;
|
||
}
|
||
|
||
.markdown-alert>:first-child {
|
||
margin-top: 0
|
||
}
|
||
|
||
.markdown-alert>:last-child {
|
||
margin-bottom: 0
|
||
}
|
||
|
||
.markdown-alert .markdown-alert-title {
|
||
display: flex;
|
||
font-weight: 500;
|
||
align-items: center;
|
||
line-height: 1
|
||
}
|
||
|
||
.markdown-alert .markdown-alert-title .octicon {
|
||
margin-right: 0.5rem;
|
||
display: inline-block;
|
||
overflow: visible !important;
|
||
vertical-align: text-bottom;
|
||
fill: currentColor;
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-note {
|
||
border-left-color: var(--color-note);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-note .markdown-alert-title {
|
||
color: var(--color-note);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-important {
|
||
border-left-color: var(--color-important);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-important .markdown-alert-title {
|
||
color: var(--color-important);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-warning {
|
||
border-left-color: var(--color-warning);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-warning .markdown-alert-title {
|
||
color: var(--color-warning);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-tip {
|
||
border-left-color: var(--color-tip);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-tip .markdown-alert-title {
|
||
color: var(--color-tip);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-caution {
|
||
border-left-color: var(--color-caution);
|
||
}
|
||
|
||
.markdown-alert.markdown-alert-caution .markdown-alert-title {
|
||
color: var(--color-caution);
|
||
}
|
||
|
||
</style>
|
||
|
||
</head>
|
||
<body class="vscode-body vscode-light">
|
||
<h1 id="m2pool-payment-system-v2">M2Pool Payment System v2</h1>
|
||
<div align="center">
|
||
<p><strong>基于以太坊区块链的分布式支付系统</strong></p>
|
||
<p><a href="https://golang.org"><img src="https://img.shields.io/badge/Go-1.24+-00ADD8?style=flat&logo=go" alt="Go Version"></a>
|
||
<a href="https://ethereum.org"><img src="https://img.shields.io/badge/Ethereum-Mainnet-3C3C3D?style=flat&logo=ethereum" alt="Ethereum"></a>
|
||
<a href="https://www.rabbitmq.com"><img src="https://img.shields.io/badge/RabbitMQ-3.x-FF6600?style=flat&logo=rabbitmq" alt="RabbitMQ"></a>
|
||
<a href="https://www.mysql.com"><img src="https://img.shields.io/badge/MySQL-8.0+-4479A1?style=flat&logo=mysql" alt="MySQL"></a>
|
||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License"></a></p>
|
||
<p>支持 <strong>充值</strong>、<strong>提现</strong>、<strong>支付</strong> 三大核心功能,实时监听链上交易,自动确认到账。</p>
|
||
<p>基于 Go 1.24 + Ethereum + RabbitMQ + MySQL 技术栈构建的企业级支付解决方案。</p>
|
||
<p><a href="#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B">快速开始</a> • <a href="#%E9%A1%B9%E7%9B%AE%E6%9E%B6%E6%9E%84">项目架构</a> • <a href="#%E5%8A%9F%E8%83%BD%E7%89%B9%E6%80%A7">功能特性</a> • <a href="#%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95">性能测试</a> • <a href="#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98">常见问题</a></p>
|
||
</div>
|
||
<hr>
|
||
<h2 id="-目录">📋 目录</h2>
|
||
<ul>
|
||
<li><a href="#%E9%A1%B9%E7%9B%AE%E7%AE%80%E4%BB%8B">项目简介</a></li>
|
||
<li><a href="#%E9%A1%B9%E7%9B%AE%E6%9E%B6%E6%9E%84">项目架构</a></li>
|
||
<li><a href="#%E5%8A%9F%E8%83%BD%E7%89%B9%E6%80%A7">功能特性</a></li>
|
||
<li><a href="#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B">快速开始</a></li>
|
||
<li><a href="#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E">配置说明</a></li>
|
||
<li><a href="#%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B">使用示例</a></li>
|
||
<li><a href="#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98">常见问题</a></li>
|
||
<li><a href="#%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97">部署指南</a></li>
|
||
<li><a href="#%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95">性能测试</a></li>
|
||
<li><a href="#%E8%B4%A1%E7%8C%AE%E6%8C%87%E5%8D%97">贡献指南</a></li>
|
||
</ul>
|
||
<hr>
|
||
<h2 id="项目简介">项目简介</h2>
|
||
<p>M2Pool Payment System v2 是一个基于以太坊区块链的<strong>分布式支付解决方案</strong>,提供完整的数字货币充值、提现、支付功能。</p>
|
||
<h3 id="核心能力">核心能力</h3>
|
||
<ul>
|
||
<li>🔍 <strong>实时监听</strong>:订阅链上事件,实时检测 USDT 转账</li>
|
||
<li>⚡ <strong>快速确认</strong>:20 个区块确认,约 4-5 分钟到账</li>
|
||
<li>🔒 <strong>安全可靠</strong>:私钥加密存储,签名验证机制</li>
|
||
<li>📊 <strong>高并发</strong>:支持中等并发(50-200 TPS)</li>
|
||
<li>🔄 <strong>自动重连</strong>:WebSocket 断开自动重连</li>
|
||
<li>📨 <strong>消息队列</strong>:基于 RabbitMQ 的异步通信</li>
|
||
</ul>
|
||
<h3 id="技术栈">技术栈</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>组件</th>
|
||
<th>技术</th>
|
||
<th>版本</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>语言</strong></td>
|
||
<td>Go</td>
|
||
<td>1.24+</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>区块链</strong></td>
|
||
<td>Ethereum</td>
|
||
<td>go-ethereum v1.16.4</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>消息队列</strong></td>
|
||
<td>RabbitMQ</td>
|
||
<td>amqp091-go v1.10.0</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>数据库</strong></td>
|
||
<td>MySQL</td>
|
||
<td>8.0+</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>网络协议</strong></td>
|
||
<td>WebSocket + RPC</td>
|
||
<td>-</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr>
|
||
<h2 id="项目架构">项目架构</h2>
|
||
<h3 id="系统架构图">系统架构图</h3>
|
||
<pre><code>┌─────────────────────────────────────────────────────────────┐
|
||
│ 业务系统 │
|
||
│ (Web/App/API Server) │
|
||
└────────────┬────────────────────────────┬───────────────────┘
|
||
│ │
|
||
│ 请求 │ 响应
|
||
↓ ↑
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ RabbitMQ │
|
||
│ ┌─────────┐ ┌──────────┐ ┌────────┐ │
|
||
│ │ topup │ │ withdraw │ │ pay │ 请求队列 │
|
||
│ └─────────┘ └──────────┘ └────────┘ │
|
||
│ ┌─────────┐ ┌──────────┐ ┌────────┐ │
|
||
│ │topup_ │ │withdraw_ │ │ pay_ │ 响应队列 │
|
||
│ │ resp │ │ resp │ │ resp │ │
|
||
│ └─────────┘ └──────────┘ └────────┘ │
|
||
└────────────┬────────────────────────────┬───────────────────┘
|
||
│ │
|
||
↓ ↑
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ M2Pool Payment System v2 │
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ RabbitMQ │ │ Blockchain │ │ Database │ │
|
||
│ │ Consumer │─>│ Manager │─>│ (MySQL) │ │
|
||
│ └──────────────┘ └──────┬───────┘ └──────────────┘ │
|
||
│ │ │
|
||
│ │ WebSocket + RPC │
|
||
└────────────────────────────┼─────────────────────────────────┘
|
||
│
|
||
↓
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 以太坊区块链网络 │
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ 新区块 │ │ USDT Transfer │ │
|
||
│ │ (NewHead) │ │ 事件 │ │
|
||
│ └──────────────┘ └──────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
</code></pre>
|
||
<h3 id="核心模块">核心模块</h3>
|
||
<h4 id="1-blockchain-manager-internalblockchain">1. Blockchain Manager (<code>internal/blockchain/</code>)</h4>
|
||
<ul>
|
||
<li><strong>blockchain.go</strong>:统一的区块链接口定义</li>
|
||
<li><strong>eth/eth.go</strong>:以太坊节点实现
|
||
<ul>
|
||
<li>监听 USDT Transfer 事件(实时检测充值)</li>
|
||
<li>监听新区块产生(触发交易确认)</li>
|
||
<li>管理待确认交易池(UnConfirmTxs)</li>
|
||
<li>执行 ERC20 转账(提现/支付)</li>
|
||
<li>自动重连机制</li>
|
||
<li>地址统一小写处理</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="2-message-queue-internalqueue">2. Message Queue (<code>internal/queue/</code>)</h4>
|
||
<ul>
|
||
<li><strong>rabbitmq.go</strong>:RabbitMQ 消息队列服务
|
||
<ul>
|
||
<li>消费 3 个请求队列(充值/提现/支付)</li>
|
||
<li>发布 3 个响应队列(交易确认结果)</li>
|
||
<li>自动重连和错误重试</li>
|
||
<li>消息持久化</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="3-database-internaldb">3. Database (<code>internal/db/</code>)</h4>
|
||
<ul>
|
||
<li><strong>db.go</strong>:MySQL 数据库连接池
|
||
<ul>
|
||
<li>存储钱包私钥(加密)</li>
|
||
<li>连接池管理</li>
|
||
<li>事务支持</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="4-message-internalmsg">4. Message (<code>internal/msg/</code>)</h4>
|
||
<ul>
|
||
<li><strong>msg.go</strong>:消息结构定义
|
||
<ul>
|
||
<li>请求消息(TopupMsg_req, WithdrawMsg_req, PayMsg_req)</li>
|
||
<li>响应消息(TopupMsg_resp, WithdrawMsg_resp, PayMsg_resp)</li>
|
||
<li>配置结构(Config, RMQConfig, ETHConfig)</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="5-utils-internalutils">5. Utils (<code>internal/utils/</code>)</h4>
|
||
<ul>
|
||
<li><strong>utils.go</strong>:工具函数
|
||
<ul>
|
||
<li>数值转换(BigInt ↔ Float64)</li>
|
||
<li>哈希计算</li>
|
||
<li>加密解密</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="6-crypto-internalcrypto">6. Crypto (<code>internal/crypto/</code>)</h4>
|
||
<ul>
|
||
<li><strong>crypto.go</strong>:加密工具
|
||
<ul>
|
||
<li>SHA256 哈希</li>
|
||
<li>签名验证</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="7-server-internalservergo">7. Server (<code>internal/server.go</code>)</h4>
|
||
<ul>
|
||
<li>服务启动和管理</li>
|
||
<li>消息路由和处理</li>
|
||
<li>优雅关闭</li>
|
||
</ul>
|
||
<h3 id="项目结构">项目结构</h3>
|
||
<pre><code>m2pool-payment-v2/
|
||
├── cmd/ # 主程序入口
|
||
│ └── main.go # 程序入口,解析命令行参数
|
||
├── internal/ # 内部包(不对外暴露)
|
||
│ ├── server.go # 服务启动和管理
|
||
│ ├── blockchain/ # 区块链交互模块
|
||
│ │ ├── blockchain.go # 统一的区块链接口定义
|
||
│ │ ├── eth/ # 以太坊实现
|
||
│ │ │ └── eth.go # USDT 监听、转账、确认
|
||
│ │ └── tron/ # TRON 实现(待开发)
|
||
│ ├── crypto/ # 加密工具
|
||
│ │ └── crypto.go # SHA256、签名验证
|
||
│ ├── db/ # 数据库
|
||
│ │ ├── db.go # MySQL 连接池管理
|
||
│ │ └── sqlite.go # SQLite 本地存储
|
||
│ ├── msg/ # 消息定义
|
||
│ │ └── msg.go # 请求/响应结构体定义
|
||
│ ├── queue/ # 消息队列
|
||
│ │ ├── rabbitmq.go # RabbitMQ 客户端封装
|
||
│ │ └── README.md # RabbitMQ 使用文档
|
||
│ ├── logger/ # 日志记录
|
||
│ │ └── transaction_logger.go # 交易日志
|
||
│ └── utils/ # 工具函数
|
||
│ └── utils.go # 类型转换、格式化
|
||
├── public/ # 公共资源
|
||
│ ├── SQLite3.sql # SQLite 表结构
|
||
│ └── migration.sql # 数据库迁移脚本
|
||
├── test/ # 测试和示例
|
||
│ ├── test.go # 测试程序(独立运行)
|
||
│ └── config.json # 配置文件
|
||
├── go.mod # Go 模块定义
|
||
├── go.sum # 依赖版本锁定
|
||
└── README.md # 项目文档(本文件)
|
||
</code></pre>
|
||
<h3 id="核心特性详解">核心特性详解</h3>
|
||
<h4 id="1-双重监听机制-">1. 双重监听机制 🎯</h4>
|
||
<p>系统同时监听两种链上事件:</p>
|
||
<p><strong>① USDT Transfer 事件监听</strong></p>
|
||
<pre><code class="language-go"><span class="hljs-comment">// 检测 USDT 转账,用于充值检测和交易确认触发</span>
|
||
e.WsClient.SubscribeFilterLogs(query, e.USDT.LogsChan)
|
||
</code></pre>
|
||
<p><strong>② 新区块头监听</strong></p>
|
||
<pre><code class="language-go"><span class="hljs-comment">// 每个新区块触发交易确认检查,确保及时确认</span>
|
||
e.WsClient.SubscribeNewHead(e.Ctx, headers)
|
||
</code></pre>
|
||
<h4 id="2-智能交易确认-">2. 智能交易确认 ⚡</h4>
|
||
<p><strong>事件驱动 + 区块驱动</strong>:</p>
|
||
<ul>
|
||
<li>Transfer 事件到达时立即检查</li>
|
||
<li>每个新区块产生时也检查</li>
|
||
<li><strong>确保交易在第 20 个区块后立即确认</strong></li>
|
||
</ul>
|
||
<h4 id="3-地址统一规范-">3. 地址统一规范 🔡</h4>
|
||
<p>所有以太坊地址<strong>统一转换为小写</strong>:</p>
|
||
<ul>
|
||
<li>存储时转换</li>
|
||
<li>比较时转换</li>
|
||
<li>查询时转换</li>
|
||
</ul>
|
||
<p>避免大小写不一致导致的匹配失败。</p>
|
||
<h4 id="4-并发安全设计-">4. 并发安全设计 🔒</h4>
|
||
<ul>
|
||
<li><code>sync.Map</code> 用于高并发地址监听</li>
|
||
<li><code>sync.Mutex</code> 保护共享数据结构</li>
|
||
<li>Channel 缓冲区防止阻塞</li>
|
||
<li>Goroutine panic 恢复机制</li>
|
||
</ul>
|
||
<h4 id="5-余额智能管理-">5. 余额智能管理 💰</h4>
|
||
<p><strong>自动归集钱包切换:</strong></p>
|
||
<pre><code>用户钱包余额 < 转账金额
|
||
↓
|
||
自动使用归集钱包
|
||
↓
|
||
确保交易成功
|
||
</code></pre>
|
||
<h4 id="6-gas-费用检查-">6. Gas 费用检查 ⛽</h4>
|
||
<p>转账前自动检查:</p>
|
||
<ul>
|
||
<li>USDT 余额是否足够</li>
|
||
<li>ETH 余额是否足够支付 Gas</li>
|
||
<li>预估 Gas 价格</li>
|
||
</ul>
|
||
<hr>
|
||
<h2 id="功能特性">功能特性</h2>
|
||
<h3 id="1-充值功能-">1. 充值功能 💰</h3>
|
||
<pre><code>用户转账 → 实时检测 → 待确认通知 → 区块确认 → 最终通知
|
||
</code></pre>
|
||
<p><strong>特点:</strong></p>
|
||
<ul>
|
||
<li>✅ 实时检测到账</li>
|
||
<li>✅ 发送<strong>两次</strong>通知:待确认 + 最终确认</li>
|
||
<li>✅ 支持多币种(当前支持 USDT)</li>
|
||
<li>✅ 自动地址监听管理</li>
|
||
</ul>
|
||
<p><strong>消息流:</strong></p>
|
||
<ol>
|
||
<li>业务系统发送充值请求 → RabbitMQ</li>
|
||
<li>系统添加地址监听</li>
|
||
<li>用户转账 → 立即通知(status=2 待确认)</li>
|
||
<li>等待 20 个区块 → 最终通知(status=1 成功 / 0 失败)</li>
|
||
</ol>
|
||
<h3 id="2-提现功能-">2. 提现功能 💸</h3>
|
||
<pre><code>提现请求 → 验证余额 → 发送交易 → 等待确认 → 返回结果
|
||
</code></pre>
|
||
<p><strong>特点:</strong></p>
|
||
<ul>
|
||
<li>✅ 自动余额检查</li>
|
||
<li>✅ 余额不足时使用归集钱包</li>
|
||
<li>✅ 发送<strong>一次</strong>通知:最终确认</li>
|
||
<li>✅ Gas 费用检查</li>
|
||
</ul>
|
||
<p><strong>消息流:</strong></p>
|
||
<ol>
|
||
<li>业务系统发送提现请求 → RabbitMQ</li>
|
||
<li>系统验证余额并发送交易</li>
|
||
<li>等待 20 个区块确认</li>
|
||
<li>返回结果(status=1 成功 / 0 失败)</li>
|
||
</ol>
|
||
<h3 id="3-支付功能-">3. 支付功能 💳</h3>
|
||
<pre><code>支付请求 → 验证余额 → 发送交易 → 等待确认 → 返回结果
|
||
</code></pre>
|
||
<p><strong>特点:</strong></p>
|
||
<ul>
|
||
<li>✅ 订单关联</li>
|
||
<li>✅ 自动余额检查</li>
|
||
<li>✅ 发送<strong>一次</strong>通知:最终确认</li>
|
||
<li>✅ 支持商户收款</li>
|
||
</ul>
|
||
<p><strong>消息流:</strong></p>
|
||
<ol>
|
||
<li>业务系统发送支付请求(含订单ID)→ RabbitMQ</li>
|
||
<li>系统验证余额并发送交易</li>
|
||
<li>等待 20 个区块确认</li>
|
||
<li>返回结果(status=1 成功 / 0 失败)</li>
|
||
</ol>
|
||
<hr>
|
||
<h2 id="快速开始">快速开始</h2>
|
||
<h3 id="前置条件">前置条件</h3>
|
||
<ul>
|
||
<li>✅ Go 1.24 或更高版本</li>
|
||
<li>✅ MySQL 8.0+</li>
|
||
<li>✅ RabbitMQ 3.x+</li>
|
||
<li>✅ 以太坊节点(支持 WebSocket 和 RPC)</li>
|
||
</ul>
|
||
<h3 id="安装步骤">安装步骤</h3>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 1. 克隆项目</span>
|
||
git <span class="hljs-built_in">clone</span> <repository-url>
|
||
<span class="hljs-built_in">cd</span> m2pool-payment-v2
|
||
|
||
<span class="hljs-comment"># 2. 安装依赖</span>
|
||
go mod download
|
||
|
||
<span class="hljs-comment"># 3. 创建数据库</span>
|
||
mysql -u root -p
|
||
</code></pre>
|
||
<pre><code class="language-sql"><span class="hljs-keyword">CREATE</span> DATABASE payment <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8mb4 <span class="hljs-keyword">COLLATE</span> utf8mb4_unicode_ci;
|
||
USE payment;
|
||
|
||
<span class="hljs-comment">-- 创建钱包余额表</span>
|
||
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `eth_balance` (
|
||
`id` <span class="hljs-type">INT</span> AUTO_INCREMENT <span class="hljs-keyword">PRIMARY</span> KEY,
|
||
`address` <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">42</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">UNIQUE</span>,
|
||
`private_key` <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">'加密后的私钥'</span>,
|
||
`balance` <span class="hljs-type">DECIMAL</span>(<span class="hljs-number">20</span>, <span class="hljs-number">8</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span>,
|
||
`created_at` <span class="hljs-type">TIMESTAMP</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span>,
|
||
`updated_at` <span class="hljs-type">TIMESTAMP</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span>,
|
||
INDEX `idx_address` (`address`)
|
||
) ENGINE<span class="hljs-operator">=</span>InnoDB <span class="hljs-keyword">DEFAULT</span> CHARSET<span class="hljs-operator">=</span>utf8mb4 COMMENT<span class="hljs-operator">=</span><span class="hljs-string">'ETH钱包表'</span>;
|
||
</code></pre>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 4. 配置文件</span>
|
||
<span class="hljs-built_in">cd</span> <span class="hljs-built_in">test</span>
|
||
<span class="hljs-built_in">cp</span> config.json config.json.backup
|
||
<span class="hljs-comment"># 编辑 config.json,填入实际配置</span>
|
||
|
||
<span class="hljs-comment"># 5. 编译主程序</span>
|
||
<span class="hljs-built_in">cd</span> ..
|
||
go build -o m2pool-payment cmd/main.go
|
||
|
||
<span class="hljs-comment"># 6. 运行(指定通信密钥)</span>
|
||
./m2pool-payment -key=your_secret_key
|
||
|
||
<span class="hljs-comment"># 或者运行测试程序</span>
|
||
<span class="hljs-built_in">cd</span> <span class="hljs-built_in">test</span>
|
||
go run test.go
|
||
</code></pre>
|
||
<h3 id="配置文件示例">配置文件示例</h3>
|
||
<p>创建 <code>test/config.json</code>:</p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"rmq_config"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"sub_addr"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"amqp://m2pool:m2pool@localhost:5672"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"pay"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.auto.queue"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"exchange"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.exchange"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"routing"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"pay.auto.routing.key"</span><span class="hljs-punctuation">]</span>
|
||
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"topup"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.recharge.queue"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"exchange"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.exchange"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"routing"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"pay.recharge.routing.key"</span><span class="hljs-punctuation">]</span>
|
||
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"withdraw"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.withdraw.queue"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"exchange"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.exchange"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"routing"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"pay.withdraw.routing.key"</span><span class="hljs-punctuation">]</span>
|
||
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"pay_resp"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.auto.return.queue"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"exchange"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.exchange"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"routing"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"pay.auto.return.routing.key"</span><span class="hljs-punctuation">]</span>
|
||
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"topup_resp"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.recharge.return.queue"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"exchange"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.exchange"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"routing"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"pay.recharge.return.routing.key"</span><span class="hljs-punctuation">]</span>
|
||
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"withdraw_resp"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.withdraw.return.queue"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"exchange"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay.exchange"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"routing"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"pay.withdraw.return.routing.key"</span><span class="hljs-punctuation">]</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"eth_config"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"rpcUrl"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"http://localhost:8545"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"wsUrl"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ws://localhost:8546"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"confirmHeight"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">20</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"dbConfig"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"user"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"root"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"password"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"your_password"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"host"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"127.0.0.1"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"port"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">3306</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"database"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"payment"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"maxOpenConns"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">20</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"maxIdleCoons"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">20</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"connMaxLife"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">120</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<hr>
|
||
<h2 id="配置说明">配置说明</h2>
|
||
<h3 id="配置项说明">配置项说明</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>配置项</th>
|
||
<th>说明</th>
|
||
<th>默认值</th>
|
||
<th>必填</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>rmq_config.sub_addr</code></td>
|
||
<td>RabbitMQ 连接地址</td>
|
||
<td>-</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>eth_config.rpcUrl</code></td>
|
||
<td>以太坊 RPC 地址</td>
|
||
<td>-</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>eth_config.wsUrl</code></td>
|
||
<td>以太坊 WebSocket 地址</td>
|
||
<td>-</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>eth_config.confirmHeight</code></td>
|
||
<td>确认区块数</td>
|
||
<td>20</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>dbConfig.user</code></td>
|
||
<td>数据库用户名</td>
|
||
<td>root</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>dbConfig.password</code></td>
|
||
<td>数据库密码</td>
|
||
<td>-</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>dbConfig.database</code></td>
|
||
<td>数据库名称</td>
|
||
<td>payment</td>
|
||
<td>✅</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr>
|
||
<h2 id="使用示例">使用示例</h2>
|
||
<h3 id="1-充值流程">1. 充值流程</h3>
|
||
<p><strong>步骤 1:业务系统发送充值请求</strong></p>
|
||
<p>发送到 RabbitMQ 队列:<code>pay.recharge.queue</code></p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x4e5b2e1dc63f6b91cb6cd759936495434c7e972f"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"timestamp"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1758610297</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"sign"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"signature_hash"</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<p><strong>步骤 2:用户转账</strong></p>
|
||
<p>用户向指定地址转账 USDT</p>
|
||
<p><strong>步骤 3:接收通知</strong></p>
|
||
<p>从 RabbitMQ 队列:<code>pay.recharge.return.queue</code> 接收<strong>两次</strong>消息:</p>
|
||
<p>第一次(待确认):</p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x4e5b2e1dc63f6b91cb6cd759936495434c7e972f"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">2</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"amount"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">100.5</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"tx_hash"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0xabc..."</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<p>第二次(最终确认):</p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x4e5b2e1dc63f6b91cb6cd759936495434c7e972f"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"amount"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">100.5</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"tx_hash"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0xabc..."</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<h3 id="2-提现流程">2. 提现流程</h3>
|
||
<p><strong>步骤 1:业务系统发送提现请求</strong></p>
|
||
<p>发送到 RabbitMQ 队列:<code>pay.withdraw.queue</code></p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"withdraw_123"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"from_address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x1111..."</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"to_address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x2222..."</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"amount"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">50.0</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"timestamp"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1758610297</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"sign"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"signature_hash"</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<p><strong>步骤 2:系统处理</strong></p>
|
||
<ul>
|
||
<li>验证签名</li>
|
||
<li>检查余额</li>
|
||
<li>发送链上交易</li>
|
||
<li>等待确认</li>
|
||
</ul>
|
||
<p><strong>步骤 3:接收通知</strong></p>
|
||
<p>从 RabbitMQ 队列:<code>pay.withdraw.return.queue</code> 接收<strong>一次</strong>消息:</p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"withdraw_123"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"amount"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">50.0</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"tx_hash"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0xdef..."</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<h3 id="3-支付流程">3. 支付流程</h3>
|
||
<p><strong>步骤 1:业务系统发送支付请求</strong></p>
|
||
<p>发送到 RabbitMQ 队列:<code>pay.auto.queue</code></p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay_456"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"from_address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x1111..."</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"to_address"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0x3333..."</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"amount"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">200.0</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"order_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"order_789"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"timestamp"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1758610297</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"sign"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"signature_hash"</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<p><strong>步骤 2:系统处理</strong></p>
|
||
<ul>
|
||
<li>验证签名</li>
|
||
<li>检查余额</li>
|
||
<li>发送链上交易</li>
|
||
<li>等待确认</li>
|
||
</ul>
|
||
<p><strong>步骤 3:接收通知</strong></p>
|
||
<p>从 RabbitMQ 队列:<code>pay.auto.return.queue</code> 接收<strong>一次</strong>消息:</p>
|
||
<pre><code class="language-json"><span class="hljs-punctuation">{</span>
|
||
<span class="hljs-attr">"queue_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"pay_456"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"amount"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">200.0</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"chain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ETH"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"symbol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USDT"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"order_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"order_789"</span><span class="hljs-punctuation">,</span>
|
||
<span class="hljs-attr">"tx_hash"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0xghi..."</span>
|
||
<span class="hljs-punctuation">}</span>
|
||
</code></pre>
|
||
<hr>
|
||
<h2 id="常见问题">常见问题</h2>
|
||
<h3 id="q1-为什么充值会收到两次通知">Q1: 为什么充值会收到两次通知?</h3>
|
||
<p><strong>A:</strong> 这是设计特性!</p>
|
||
<ul>
|
||
<li><strong>第一次</strong>(status=2):检测到交易,提醒用户"正在确认"</li>
|
||
<li><strong>第二次</strong>(status=1/0):交易确认,通知最终结果</li>
|
||
</ul>
|
||
<p>业务系统应该:</p>
|
||
<ul>
|
||
<li>status=2:显示进度,<strong>不增加余额</strong></li>
|
||
<li>status=1:增加余额</li>
|
||
</ul>
|
||
<h3 id="q2-提现支付为什么只有一次通知">Q2: 提现/支付为什么只有一次通知?</h3>
|
||
<p><strong>A:</strong> 因为是系统主动发起的交易,用户已经知道在处理中,不需要额外的待确认通知。</p>
|
||
<h3 id="q3-如何处理交易失败">Q3: 如何处理交易失败?</h3>
|
||
<p><strong>A:</strong> 系统会返回 status=0 的消息,业务系统应该:</p>
|
||
<ul>
|
||
<li>充值失败:不增加余额,提示用户联系客服</li>
|
||
<li>提现失败:退回用户余额</li>
|
||
<li>支付失败:恢复订单状态,退回余额</li>
|
||
</ul>
|
||
<h3 id="q4-确认需要多长时间">Q4: 确认需要多长时间?</h3>
|
||
<p><strong>A:</strong> 配置为 20 个区块确认,以太坊约 12 秒/块:</p>
|
||
<ul>
|
||
<li>理论时间:20 × 12 = 240 秒(4 分钟)</li>
|
||
<li>实际时间:4-5 分钟(包括网络延迟)</li>
|
||
</ul>
|
||
<h3 id="q5-如何保证私钥安全">Q5: 如何保证私钥安全?</h3>
|
||
<p><strong>A:</strong></p>
|
||
<ol>
|
||
<li><strong>私钥加密存储</strong>:数据库中存储加密后的私钥</li>
|
||
<li><strong>临时解密</strong>:仅在转账时临时解密,用完立即释放</li>
|
||
<li><strong>访问控制</strong>:数据库限制访问权限</li>
|
||
<li><strong>建议方案</strong>:
|
||
<ul>
|
||
<li>使用 AES-256 加密私钥</li>
|
||
<li>使用 HSM(硬件安全模块)</li>
|
||
<li>使用云服务商的 KMS(密钥管理服务)</li>
|
||
<li>使用环境变量传递解密密钥</li>
|
||
</ul>
|
||
</li>
|
||
</ol>
|
||
<p>⚠️ <strong>重要</strong>:当前代码中的解密逻辑是<strong>占位代码</strong>,生产环境必须替换为真实的加密算法!</p>
|
||
<h3 id="q6-余额不足时如何处理">Q6: 余额不足时如何处理?</h3>
|
||
<p><strong>A:</strong> 系统会自动使用<strong>归集钱包</strong>转账。归集钱包应该:</p>
|
||
<ul>
|
||
<li>保持足够的余额</li>
|
||
<li>定期从各个钱包归集资金</li>
|
||
<li>设置余额告警</li>
|
||
</ul>
|
||
<h3 id="q7-支持哪些网络">Q7: 支持哪些网络?</h3>
|
||
<p><strong>A:</strong></p>
|
||
<ul>
|
||
<li>✅ 以太坊主网(Mainnet)</li>
|
||
<li>✅ 以太坊测试网(Goerli, Sepolia)</li>
|
||
<li>✅ 私有链</li>
|
||
<li>⚠️ 需要修改 USDT 合约地址</li>
|
||
</ul>
|
||
<h3 id="q8-gas-费用谁承担">Q8: Gas 费用谁承担?</h3>
|
||
<p><strong>A:</strong></p>
|
||
<ul>
|
||
<li><strong>充值</strong>:用户承担(用户自己发送交易)</li>
|
||
<li><strong>提现</strong>:平台承担(系统发送交易)</li>
|
||
<li><strong>支付</strong>:平台承担(系统发送交易)</li>
|
||
</ul>
|
||
<p>建议:提现/支付时从用户金额中扣除 Gas 费</p>
|
||
<hr>
|
||
<h2 id="部署指南">部署指南</h2>
|
||
<h3 id="docker-部署推荐">Docker 部署(推荐)</h3>
|
||
<pre><code class="language-dockerfile"><span class="hljs-comment"># Dockerfile</span>
|
||
<span class="hljs-keyword">FROM</span> golang:<span class="hljs-number">1.24</span>-alpine AS builder
|
||
|
||
<span class="hljs-keyword">WORKDIR</span><span class="language-bash"> /app</span>
|
||
<span class="hljs-keyword">COPY</span><span class="language-bash"> . .</span>
|
||
<span class="hljs-keyword">RUN</span><span class="language-bash"> go mod download</span>
|
||
<span class="hljs-keyword">RUN</span><span class="language-bash"> CGO_ENABLED=0 GOOS=linux go build -o m2pool-payment cmd/main.go</span>
|
||
|
||
<span class="hljs-keyword">FROM</span> alpine:latest
|
||
<span class="hljs-keyword">RUN</span><span class="language-bash"> apk --no-cache add ca-certificates</span>
|
||
<span class="hljs-keyword">WORKDIR</span><span class="language-bash"> /root/</span>
|
||
|
||
<span class="hljs-keyword">COPY</span><span class="language-bash"> --from=builder /app/m2pool-payment .</span>
|
||
<span class="hljs-keyword">COPY</span><span class="language-bash"> --from=builder /app/test/config.json .</span>
|
||
|
||
<span class="hljs-keyword">CMD</span><span class="language-bash"> [<span class="hljs-string">"./m2pool-payment"</span>]</span>
|
||
</code></pre>
|
||
<pre><code class="language-yaml"><span class="hljs-comment"># docker-compose.yml</span>
|
||
<span class="hljs-attr">version:</span> <span class="hljs-string">'3.8'</span>
|
||
|
||
<span class="hljs-attr">services:</span>
|
||
<span class="hljs-attr">payment:</span>
|
||
<span class="hljs-attr">build:</span> <span class="hljs-string">.</span>
|
||
<span class="hljs-attr">depends_on:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">mysql</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">rabbitmq</span>
|
||
<span class="hljs-attr">environment:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">CONFIG_PATH=/root/config.json</span>
|
||
<span class="hljs-attr">volumes:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">./config.json:/root/config.json</span>
|
||
<span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>
|
||
|
||
<span class="hljs-attr">mysql:</span>
|
||
<span class="hljs-attr">image:</span> <span class="hljs-string">mysql:8.0</span>
|
||
<span class="hljs-attr">environment:</span>
|
||
<span class="hljs-attr">MYSQL_ROOT_PASSWORD:</span> <span class="hljs-string">${MYSQL_PASSWORD}</span>
|
||
<span class="hljs-attr">MYSQL_DATABASE:</span> <span class="hljs-string">payment</span>
|
||
<span class="hljs-attr">ports:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">"3306:3306"</span>
|
||
<span class="hljs-attr">volumes:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">mysql_data:/var/lib/mysql</span>
|
||
|
||
<span class="hljs-attr">rabbitmq:</span>
|
||
<span class="hljs-attr">image:</span> <span class="hljs-string">rabbitmq:3-management</span>
|
||
<span class="hljs-attr">environment:</span>
|
||
<span class="hljs-attr">RABBITMQ_DEFAULT_USER:</span> <span class="hljs-string">m2pool</span>
|
||
<span class="hljs-attr">RABBITMQ_DEFAULT_PASS:</span> <span class="hljs-string">m2pool</span>
|
||
<span class="hljs-attr">ports:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">"5672:5672"</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">"15672:15672"</span>
|
||
<span class="hljs-attr">volumes:</span>
|
||
<span class="hljs-bullet">-</span> <span class="hljs-string">rabbitmq_data:/var/lib/rabbitmq</span>
|
||
|
||
<span class="hljs-attr">volumes:</span>
|
||
<span class="hljs-attr">mysql_data:</span>
|
||
<span class="hljs-attr">rabbitmq_data:</span>
|
||
</code></pre>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 启动</span>
|
||
docker-compose up -d
|
||
|
||
<span class="hljs-comment"># 查看日志</span>
|
||
docker-compose logs -f payment
|
||
|
||
<span class="hljs-comment"># 停止</span>
|
||
docker-compose down
|
||
</code></pre>
|
||
<h3 id="系统服务部署">系统服务部署</h3>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 1. 创建系统用户</span>
|
||
sudo useradd -r -s /bin/false m2pool
|
||
|
||
<span class="hljs-comment"># 2. 创建服务文件</span>
|
||
sudo nano /etc/systemd/system/m2pool-payment.service
|
||
</code></pre>
|
||
<pre><code class="language-ini"><span class="hljs-section">[Unit]</span>
|
||
<span class="hljs-attr">Description</span>=M2Pool Payment System
|
||
<span class="hljs-attr">After</span>=network.target mysql.service rabbitmq-server.service
|
||
|
||
<span class="hljs-section">[Service]</span>
|
||
<span class="hljs-attr">Type</span>=simple
|
||
<span class="hljs-attr">User</span>=m2pool
|
||
<span class="hljs-attr">WorkingDirectory</span>=/opt/m2pool-payment
|
||
<span class="hljs-attr">ExecStart</span>=/opt/m2pool-payment/m2pool-payment
|
||
<span class="hljs-attr">Restart</span>=<span class="hljs-literal">on</span>-failure
|
||
<span class="hljs-attr">RestartSec</span>=<span class="hljs-number">10</span>
|
||
|
||
<span class="hljs-section">[Install]</span>
|
||
<span class="hljs-attr">WantedBy</span>=multi-user.target
|
||
</code></pre>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 3. 启动服务</span>
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl <span class="hljs-built_in">enable</span> m2pool-payment
|
||
sudo systemctl start m2pool-payment
|
||
|
||
<span class="hljs-comment"># 4. 查看状态</span>
|
||
sudo systemctl status m2pool-payment
|
||
|
||
<span class="hljs-comment"># 5. 查看日志</span>
|
||
sudo journalctl -u m2pool-payment -f
|
||
</code></pre>
|
||
<hr>
|
||
<h2 id="性能测试">性能测试</h2>
|
||
<h3 id="压测环境配置">压测环境配置</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>配置项</th>
|
||
<th>规格</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>CPU</strong></td>
|
||
<td>4核 2.4GHz</td>
|
||
<td>Intel/AMD x64</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>内存</strong></td>
|
||
<td>8GB DDR4</td>
|
||
<td>系统 + 缓存</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>网络</strong></td>
|
||
<td>100Mbps</td>
|
||
<td>公网带宽</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>数据库</strong></td>
|
||
<td>MySQL 8.0</td>
|
||
<td>本地部署</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>消息队列</strong></td>
|
||
<td>RabbitMQ 3.x</td>
|
||
<td>本地部署</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>区块链节点</strong></td>
|
||
<td>Infura/Alchemy</td>
|
||
<td>云端服务</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="预估压测结果">预估压测结果</h3>
|
||
<h4 id="1-充值功能压测">1. 充值功能压测</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>并发用户数</th>
|
||
<th>TPS</th>
|
||
<th>响应时间</th>
|
||
<th>成功率</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>10</strong></td>
|
||
<td>50-80</td>
|
||
<td>< 2秒</td>
|
||
<td>99.9%</td>
|
||
<td>轻量负载,性能优秀</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>50</strong></td>
|
||
<td>200-300</td>
|
||
<td>2-5秒</td>
|
||
<td>99.5%</td>
|
||
<td>中等负载,性能良好</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>100</strong></td>
|
||
<td>300-500</td>
|
||
<td>5-10秒</td>
|
||
<td>99.0%</td>
|
||
<td>高负载,性能稳定</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>200</strong></td>
|
||
<td>400-600</td>
|
||
<td>10-20秒</td>
|
||
<td>98.5%</td>
|
||
<td>极限负载,性能下降</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>500+</strong></td>
|
||
<td>500-800</td>
|
||
<td>> 20秒</td>
|
||
<td>< 98%</td>
|
||
<td>超负载,不建议</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>特点:</strong></p>
|
||
<ul>
|
||
<li>✅ 充值检测性能优秀(纯监听,无链上操作)</li>
|
||
<li>✅ 内存占用低(仅地址监听)</li>
|
||
<li>✅ 网络带宽消耗小</li>
|
||
</ul>
|
||
<h4 id="2-提现功能压测">2. 提现功能压测</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>并发用户数</th>
|
||
<th>TPS</th>
|
||
<th>响应时间</th>
|
||
<th>成功率</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>5</strong></td>
|
||
<td>20-30</td>
|
||
<td>3-8秒</td>
|
||
<td>99.8%</td>
|
||
<td>轻量负载,性能优秀</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>20</strong></td>
|
||
<td>50-80</td>
|
||
<td>8-15秒</td>
|
||
<td>99.0%</td>
|
||
<td>中等负载,性能良好</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>50</strong></td>
|
||
<td>80-120</td>
|
||
<td>15-30秒</td>
|
||
<td>98.5%</td>
|
||
<td>高负载,性能稳定</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>100</strong></td>
|
||
<td>100-150</td>
|
||
<td>30-60秒</td>
|
||
<td>97.0%</td>
|
||
<td>极限负载,性能下降</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>200+</strong></td>
|
||
<td>120-200</td>
|
||
<td>> 60秒</td>
|
||
<td>< 95%</td>
|
||
<td>超负载,不建议</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>特点:</strong></p>
|
||
<ul>
|
||
<li>⚠️ 受链上交易确认时间影响(4-5分钟)</li>
|
||
<li>⚠️ 数据库查询和私钥解密开销</li>
|
||
<li>⚠️ Gas费用波动影响成功率</li>
|
||
</ul>
|
||
<h4 id="3-支付功能压测">3. 支付功能压测</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>并发用户数</th>
|
||
<th>TPS</th>
|
||
<th>响应时间</th>
|
||
<th>成功率</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>5</strong></td>
|
||
<td>20-30</td>
|
||
<td>3-8秒</td>
|
||
<td>99.8%</td>
|
||
<td>轻量负载,性能优秀</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>20</strong></td>
|
||
<td>50-80</td>
|
||
<td>8-15秒</td>
|
||
<td>99.0%</td>
|
||
<td>中等负载,性能良好</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>50</strong></td>
|
||
<td>80-120</td>
|
||
<td>15-30秒</td>
|
||
<td>98.5%</td>
|
||
<td>高负载,性能稳定</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>100</strong></td>
|
||
<td>100-150</td>
|
||
<td>30-60秒</td>
|
||
<td>97.0%</td>
|
||
<td>极限负载,性能下降</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>200+</strong></td>
|
||
<td>120-200</td>
|
||
<td>> 60秒</td>
|
||
<td>< 95%</td>
|
||
<td>超负载,不建议</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>特点:</strong></p>
|
||
<ul>
|
||
<li>⚠️ 与提现功能性能相近</li>
|
||
<li>⚠️ 订单ID处理增加少量开销</li>
|
||
<li>⚠️ 商户地址验证开销</li>
|
||
</ul>
|
||
<h3 id="系统资源占用">系统资源占用</h3>
|
||
<h4 id="内存使用情况">内存使用情况</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>并发数</th>
|
||
<th>基础内存</th>
|
||
<th>峰值内存</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>10</strong></td>
|
||
<td>100MB</td>
|
||
<td>150MB</td>
|
||
<td>轻量运行</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>50</strong></td>
|
||
<td>200MB</td>
|
||
<td>350MB</td>
|
||
<td>中等负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>100</strong></td>
|
||
<td>300MB</td>
|
||
<td>500MB</td>
|
||
<td>高负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>200</strong></td>
|
||
<td>500MB</td>
|
||
<td>800MB</td>
|
||
<td>极限负载</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h4 id="cpu使用情况">CPU使用情况</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>并发数</th>
|
||
<th>基础CPU</th>
|
||
<th>峰值CPU</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>10</strong></td>
|
||
<td>5%</td>
|
||
<td>15%</td>
|
||
<td>轻量运行</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>50</strong></td>
|
||
<td>15%</td>
|
||
<td>35%</td>
|
||
<td>中等负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>100</strong></td>
|
||
<td>25%</td>
|
||
<td>50%</td>
|
||
<td>高负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>200</strong></td>
|
||
<td>40%</td>
|
||
<td>70%</td>
|
||
<td>极限负载</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h4 id="网络带宽使用">网络带宽使用</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>并发数</th>
|
||
<th>上行带宽</th>
|
||
<th>下行带宽</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>10</strong></td>
|
||
<td>1Mbps</td>
|
||
<td>2Mbps</td>
|
||
<td>轻量运行</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>50</strong></td>
|
||
<td>3Mbps</td>
|
||
<td>5Mbps</td>
|
||
<td>中等负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>100</strong></td>
|
||
<td>5Mbps</td>
|
||
<td>8Mbps</td>
|
||
<td>高负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>200</strong></td>
|
||
<td>8Mbps</td>
|
||
<td>12Mbps</td>
|
||
<td>极限负载</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="性能瓶颈分析">性能瓶颈分析</h3>
|
||
<h4 id="1-主要瓶颈">1. 主要瓶颈</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>瓶颈类型</th>
|
||
<th>影响程度</th>
|
||
<th>解决方案</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>区块链确认时间</strong></td>
|
||
<td>🔴 高</td>
|
||
<td>使用Layer2或侧链</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>数据库查询</strong></td>
|
||
<td>🟡 中</td>
|
||
<td>添加索引,使用缓存</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>私钥解密</strong></td>
|
||
<td>🟡 中</td>
|
||
<td>优化加密算法</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>网络延迟</strong></td>
|
||
<td>🟡 中</td>
|
||
<td>使用CDN,就近部署</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Gas费用波动</strong></td>
|
||
<td>🟡 中</td>
|
||
<td>动态Gas价格调整</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h4 id="2-优化建议">2. 优化建议</h4>
|
||
<p><strong>短期优化(1-2周):</strong></p>
|
||
<ul>
|
||
<li>✅ 添加数据库索引</li>
|
||
<li>✅ 优化SQL查询语句</li>
|
||
<li>✅ 增加Channel缓冲区大小</li>
|
||
<li>✅ 使用连接池复用</li>
|
||
</ul>
|
||
<p><strong>中期优化(1-2月):</strong></p>
|
||
<ul>
|
||
<li>🔄 实现Redis缓存</li>
|
||
<li>🔄 优化私钥加密算法</li>
|
||
<li>🔄 添加负载均衡</li>
|
||
<li>🔄 实现读写分离</li>
|
||
</ul>
|
||
<p><strong>长期优化(3-6月):</strong></p>
|
||
<ul>
|
||
<li>🚀 支持Layer2网络</li>
|
||
<li>🚀 实现微服务架构</li>
|
||
<li>🚀 添加水平扩展</li>
|
||
<li>🚀 使用分布式数据库</li>
|
||
</ul>
|
||
<h3 id="压测工具推荐">压测工具推荐</h3>
|
||
<h4 id="1-消息队列压测">1. 消息队列压测</h4>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 使用 RabbitMQ 压测工具</span>
|
||
docker run --<span class="hljs-built_in">rm</span> -it \
|
||
-e RABBITMQ_HOST=localhost \
|
||
-e RABBITMQ_PORT=5672 \
|
||
-e RABBITMQ_USER=m2pool \
|
||
-e RABBITMQ_PASS=m2pool \
|
||
rabbitmq-perf-test:latest \
|
||
--rate 100 --time 60 --queue pay.withdraw.queue
|
||
</code></pre>
|
||
<h4 id="2-数据库压测">2. 数据库压测</h4>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 使用 sysbench 压测 MySQL</span>
|
||
sysbench mysql \
|
||
--mysql-host=localhost \
|
||
--mysql-port=3306 \
|
||
--mysql-user=root \
|
||
--mysql-password=password \
|
||
--mysql-db=payment \
|
||
--tables=1 \
|
||
--table-size=10000 \
|
||
--threads=10 \
|
||
--time=60 \
|
||
run
|
||
</code></pre>
|
||
<h4 id="3-系统监控">3. 系统监控</h4>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 监控系统资源</span>
|
||
htop <span class="hljs-comment"># CPU和内存监控</span>
|
||
iotop <span class="hljs-comment"># 磁盘IO监控</span>
|
||
nethogs <span class="hljs-comment"># 网络带宽监控</span>
|
||
</code></pre>
|
||
<h3 id="生产环境建议">生产环境建议</h3>
|
||
<h4 id="1-推荐配置">1. 推荐配置</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>环境</th>
|
||
<th>CPU</th>
|
||
<th>内存</th>
|
||
<th>并发数</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>开发环境</strong></td>
|
||
<td>2核</td>
|
||
<td>4GB</td>
|
||
<td>< 10</td>
|
||
<td>功能测试</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>测试环境</strong></td>
|
||
<td>4核</td>
|
||
<td>8GB</td>
|
||
<td>< 50</td>
|
||
<td>压力测试</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>生产环境</strong></td>
|
||
<td>8核</td>
|
||
<td>16GB</td>
|
||
<td>< 100</td>
|
||
<td>稳定运行</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>高可用环境</strong></td>
|
||
<td>16核</td>
|
||
<td>32GB</td>
|
||
<td>< 200</td>
|
||
<td>负载均衡</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h4 id="2-监控指标">2. 监控指标</h4>
|
||
<pre><code class="language-go"><span class="hljs-comment">// 关键监控指标</span>
|
||
<span class="hljs-keyword">type</span> Metrics <span class="hljs-keyword">struct</span> {
|
||
TotalTransactions <span class="hljs-type">int64</span> <span class="hljs-comment">// 总交易数</span>
|
||
PendingTransactions <span class="hljs-type">int</span> <span class="hljs-comment">// 待确认交易数</span>
|
||
FailedTransactions <span class="hljs-type">int64</span> <span class="hljs-comment">// 失败交易数</span>
|
||
ChannelUsage <span class="hljs-type">int</span> <span class="hljs-comment">// Channel使用率</span>
|
||
LastBlockHeight <span class="hljs-type">uint64</span> <span class="hljs-comment">// 最新区块高度</span>
|
||
MemoryUsage <span class="hljs-type">int64</span> <span class="hljs-comment">// 内存使用量</span>
|
||
CPUUsage <span class="hljs-type">float64</span> <span class="hljs-comment">// CPU使用率</span>
|
||
}
|
||
</code></pre>
|
||
<h4 id="3-告警阈值">3. 告警阈值</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>指标</th>
|
||
<th>警告阈值</th>
|
||
<th>严重阈值</th>
|
||
<th>说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>待确认交易数</strong></td>
|
||
<td>> 100</td>
|
||
<td>> 500</td>
|
||
<td>交易积压</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Channel使用率</strong></td>
|
||
<td>> 80%</td>
|
||
<td>> 95%</td>
|
||
<td>消息积压</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>交易失败率</strong></td>
|
||
<td>> 5%</td>
|
||
<td>> 10%</td>
|
||
<td>系统异常</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>内存使用率</strong></td>
|
||
<td>> 80%</td>
|
||
<td>> 95%</td>
|
||
<td>内存不足</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>CPU使用率</strong></td>
|
||
<td>> 70%</td>
|
||
<td>> 90%</td>
|
||
<td>CPU过载</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr>
|
||
<h2 id="重要修复说明">重要修复说明</h2>
|
||
<h3 id="-已修复的问题">🔧 已修复的问题</h3>
|
||
<h4 id="1-queueid-重复问题">1. QueueId 重复问题</h4>
|
||
<p><strong>问题</strong>:两笔不同的交易出现相同的 QueueId</p>
|
||
<p><strong>原因</strong>:数据库表主键设计错误,使用 <code>(from_addr, to_addr)</code> 作为主键</p>
|
||
<p><strong>修复</strong>:</p>
|
||
<ul>
|
||
<li>修改数据库表结构,将主键改为 <code>queueId</code></li>
|
||
<li>创建数据库迁移脚本 <code>public/migration.sql</code></li>
|
||
<li>修复 SQL 插入语句的参数数量不匹配问题</li>
|
||
</ul>
|
||
<h4 id="2-重复发送响应问题">2. 重复发送响应问题</h4>
|
||
<p><strong>问题</strong>:提现和支付会发送两次响应</p>
|
||
<p><strong>原因</strong>:转账失败时,先发送失败响应,然后仍然进入链上确认流程</p>
|
||
<p><strong>修复</strong>:</p>
|
||
<ul>
|
||
<li>在转账失败时添加 <code>return</code> 语句</li>
|
||
<li>确保转账失败时不进入链上确认流程</li>
|
||
<li>只有转账成功才会进入链上监听和确认</li>
|
||
</ul>
|
||
<h3 id="-修复后的消息发送次数">📊 修复后的消息发送次数</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>场景</th>
|
||
<th>消息处理阶段</th>
|
||
<th>链上确认阶段</th>
|
||
<th>总发送次数</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>转账失败</strong></td>
|
||
<td>发送失败响应</td>
|
||
<td>不进入(已return)</td>
|
||
<td><strong>1次</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>转账成功</strong></td>
|
||
<td>不发送响应</td>
|
||
<td>发送成功响应</td>
|
||
<td><strong>1次</strong></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr>
|
||
<h2 id="贡献指南">贡献指南</h2>
|
||
<p>欢迎贡献代码!请遵循以下步骤:</p>
|
||
<h3 id="提交流程">提交流程</h3>
|
||
<ol>
|
||
<li>Fork 本项目</li>
|
||
<li>创建功能分支 (<code>git checkout -b feature/AmazingFeature</code>)</li>
|
||
<li>提交更改 (<code>git commit -m 'feat: Add some AmazingFeature'</code>)</li>
|
||
<li>推送到分支 (<code>git push origin feature/AmazingFeature</code>)</li>
|
||
<li>开启 Pull Request</li>
|
||
</ol>
|
||
<h3 id="代码规范">代码规范</h3>
|
||
<ul>
|
||
<li>✅ 使用 <code>gofmt</code> 格式化代码</li>
|
||
<li>✅ 遵循 Go 命名规范</li>
|
||
<li>✅ 添加必要的注释</li>
|
||
<li>✅ 所有地址统一小写处理</li>
|
||
<li>✅ 使用状态码常量(不要硬编码数字)</li>
|
||
<li>✅ 添加错误处理和日志</li>
|
||
<li>✅ 更新相关文档</li>
|
||
</ul>
|
||
<h3 id="commit-规范">Commit 规范</h3>
|
||
<pre><code class="language-bash"><span class="hljs-comment"># 新功能</span>
|
||
feat: 添加 BTC 网络支持
|
||
|
||
<span class="hljs-comment"># Bug 修复</span>
|
||
fix: 修复充值消息重复发送问题
|
||
|
||
<span class="hljs-comment"># 文档更新</span>
|
||
docs: 更新 API 文档
|
||
|
||
<span class="hljs-comment"># 性能优化</span>
|
||
perf: 优化交易确认性能
|
||
|
||
<span class="hljs-comment"># 代码重构</span>
|
||
refactor: 重构数据库连接池
|
||
|
||
<span class="hljs-comment"># 测试</span>
|
||
<span class="hljs-built_in">test</span>: 添加单元测试
|
||
</code></pre>
|
||
<hr>
|
||
<h2 id="许可证">许可证</h2>
|
||
<p>MIT License</p>
|
||
<p>Copyright (c) 2025 M2Pool Team</p>
|
||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:</p>
|
||
<p>The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.</p>
|
||
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.</p>
|
||
<hr>
|
||
<div align="center">
|
||
<p><strong>⭐ 如果这个项目对你有帮助,请给一个 Star!⭐</strong></p>
|
||
<p>Made with ❤️ by M2Pool Team</p>
|
||
</div>
|
||
<script async src="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js"></script>
|
||
|
||
</body>
|
||
</html> |