XPayLabs 部署全攻略:从零搭建你自己的多链加密货币支付网关

0 阅读6分钟

og-image.png

XPayLabs 部署全攻略:从零搭建你自己的多链加密货币支付网关

XPayLabs 是一款生产级的自托管加密货币支付网关,支持多链收款和多商家架构。本文将从零开始,完整演示部署全过程。

你要部署的是什么东西?

整个 XPayLabs 由 11 个 Docker 服务组成:

服务职责技术栈
mysql持久化数据库MySQL 8.0
redis缓存、队列、nonce 存储Redis 7 Alpine
sui-node-serviceSUI 区块链 RPC 代理Express (Node.js)
xpay-tronTRON 链扫描器Spring Boot 3.4 (Java 17)
xpay-suiSUI 链扫描器Spring Boot 3.4 (Java 17)
xpay-ethEVM 扫描器 (ETH, BSC, Polygon, Avalanche)Spring Boot 3.4 (Java 17)
xpay-user用户端 API(收款订单、余额查询等)Spring Boot 3.4 (Java 17)
xpay-merchant商家后台 APISpring Boot 3.4 (Java 17)
merchant-vue商家管理后台前端Vue 3 + Element Plus (Nginx)
checkout收银台支付页面Vue 3 + Vite 7 (Nginx)
gateway反向代理(统一入口)Nginx Alpine

所有 Java 服务共用同一个基础镜像 ghcr.io/yan253319066/xpay-java,通过 command 参数启动不同的 JAR 包。

前置条件

  • Docker 24+ 和 Docker Compose v2+
  • Linux 服务器(最低 4 GB 内存,推荐 8 GB)
  • 两个域名(商家后台 + 收银台)
  • SSL 证书(Let's Encrypt 免费或商业证书)
  • 各区块链的 RPC 节点地址

第一步:克隆部署仓库

git clone https://github.com/yan253319066/XPayLabs-docker.git
cd XPayLabs-docker

这个仓库包含了部署所需的一切:docker-compose.yml、Nginx 配置、SQL 初始化脚本、环境变量模板。

第二步:配置环境变量

cp .env.example .env

编辑 .env 文件,逐项说明如下:

数据库与缓存

MYSQL_ROOT_PASSWORD=<强随机密码>
DB_USERNAME=root
DB_PASSWORD=<与上面相同或不同>
REDIS_PASSWORD=<可选,留空则不设密码>

MySQL 首次启动时自动执行 ./sql/init.sql 初始化数据库。Redis 密码留空表示不启用认证。

加密密钥(关键)

ENCRYPTION_KEY=<必须恰好32个字符>
JWT_SECRET_KEY=<随机字符串>
SKIP_SIGN_SECRET=<64位十六进制密钥>
  • ENCRYPTION_KEY:AES-256-CBC 密钥,必须恰好 32 个字符。用于 sui-node-servicexpay-sui 加密 SUI 私钥
  • JWT_SECRET_KEYxpay-merchant 用于签发商家后台会话的 JWT Token
  • SKIP_SIGN_SECRET:SkipSign 功能的 HMAC-SHA256 签名密钥,用于服务间内部请求签名

公网域名

XPAY_PAY_DOMAIN=https://pay.your-domain.com/checkout
XPAY_API_DOMAIN=https://api.your-domain.com

Java 服务会使用这两个域名构造回调 URL 和收银台跳转地址。配置好 DNS 后必须改为你实际的域名。

区块链 RPC 配置

EVM 链(ETH, BSC, Polygon, Avalanche):

ETH_NETWORKS=ETH,ETH_SEPOLIA,BSC,BSC_TEST,POLYGON,POLYGON_AMOY,AVAX_C_CHAIN,AVAX_FUJI_TEST
RPC_ETH=https://0xrpc.io/eth,https://rpc.flashbots.net
SCAN_ETH=15
  • ETH_NETWORKS:逗号分隔的活跃网络列表
  • RPC_*:逗号分隔的 RPC 地址(扫描器按顺序依次尝试,实现故障转移)
  • SCAN_*:区块扫描间隔(秒)

主网建议使用商业 RPC 服务商(Alchemy、Infura、QuickNode),测试网可以用公共 RPC。

TRON:

TRON_NETWORKS=TRON,TRON_TEST
NODE_TRON=grpc.trongrid.io:50051
SOLIDITY_TRON=grpc.trongrid.io:50052
APIKEY_TRON=<你的trongrid-api-key>

TRON 使用 gRPC 协议而非 JSON-RPC。扫描器同时连接 full node 和 solidity node。生产环境需要在 trongrid.io 申请 API Key。

SUI:

SUI 无需在 .env 中配置 RPC。xpay-sui 扫描器通过 Docker 内网连接 sui-node-service(Express RPC 代理),地址为 http://sui-node-service:3001

端口映射

HOST_PORT_GATEWAY_HTTP=180
HOST_PORT_MYSQL=13306
HOST_PORT_REDIS=16379
HOST_PORT_XPAY_USER=18077
HOST_PORT_XPAY_MERCHANT=18078
HOST_PORT_XPAY_ETH=18076
HOST_PORT_XPAY_TRON=18075
HOST_PORT_XPAY_SUI=18074
HOST_PORT_SUI_NODE=13001

只有 180 端口(Nginx 网关)需要暴露到公网。其他端口仅供内部通信和调试使用。

第三步:启动服务

docker compose up -d

Docker Compose 按依赖顺序启动服务:

  1. mysqlredis 最先启动
  2. 链扫描器(xpay-tronxpay-ethxpay-sui + sui-node-service)在 MySQL 就绪后启动
  3. xpay-user 在扫描器之后启动
  4. xpay-merchantxpay-user 之后启动
  5. 前端服务(merchant-vuecheckout)在后端就绪后启动
  6. gateway(Nginx)最后启动

验证部署

# 检查所有服务运行状态
docker compose ps

# 查看日志
docker compose logs xpay-user
docker compose logs xpay-eth

# 测试 API
curl http://localhost:180/api/symbol/supportSymbols

第四步:配置 DNS 和 SSL

DNS 记录

将域名指向服务器的公网 IP:

merchant.your-domain.com A <服务器IP>
pay.your-domain.com       A <服务器IP>
api.your-domain.com       A <服务器IP>

Nginx 网关按路径前缀路由流量:

  • /checkout/* → 收银台服务(支付页面)
  • /api/* → xpay-user API
  • /prod-api/* → xpay-merchant API
  • /* → 商家管理后台(默认)

使用 Let's Encrypt 配置 SSL

  1. 获取证书:
docker run -it --rm -p 80:80 -v "$(pwd)/certs:/etc/letsencrypt" certbot/certbot certonly --standalone -d merchant.your-domain.com -d pay.your-domain.com
  1. 复制证书:
cp certs/live/merchant.your-domain.com/fullchain.pem certs/merchant.crt
cp certs/live/merchant.your-domain.com/privkey.pem certs/merchant.key
  1. 修改 docker-compose.yml 启用 SSL:
gateway:
  ports:
    - "180:80"
    - "1443:443"   # 取消注释
  volumes:
    - ./nginx/gateway.conf:/etc/nginx/conf.d/default.conf
    # 替换为:
    # - ./nginx/gateway-ssl.conf:/etc/nginx/conf.d/default.conf
    - ./certs:/etc/nginx/certs   # 取消注释
  1. 修改 .envHOST_PORT_GATEWAY_HTTPS=1443

  2. 重启网关:

docker compose restart gateway

第五步:创建第一个商家

访问 http://localhost:180(或你的域名)进入商家管理后台:

  1. 注册账号 — 使用邮箱和密码创建商家账户
  2. 获取 API 凭证 — 登录后进入 设置 → API 密钥,生成 API Key 和 Secret
  3. 配置 Webhook — 设置支付通知的回调 URL
  4. 开始收款 — 系统使用 HD 钱包自动为每笔订单生成充值地址,无需手动配置

使用 API

拿到 API Key 和 Secret 后:

curl -X POST https://api.your-domain.com/v1/collection/create \
  -H "Content-Type: application/json" \
  -d '{
    "sign": "<hmac签名>",
    "timestamp": 1717000000000,
    "nonce": "<uuid>",
    "data": {
      "amount": "100.00",
      "symbol": "USDT",
      "chain": "tron",
      "orderId": "order_001"
    }
  }'

SDK 会自动处理签名逻辑:

  • Node.js:npm install @xpaylabs/node-sdk
  • Java:Maven Central com.xpaylabs:xpay-java-sdk

架构详解

多商家设计

XPayLabs 采用平台运营模式。一个部署可入驻无限商家,每个商家拥有:

  • 独立的数据隔离(通过 merchant_id 字段作用域)
  • 独立的 API 凭证(HMAC 密钥对)
  • 独立的 Webhook 配置
  • 可配置的费率(运营者自主定价)

HD 钱包密钥管理

网关采用 BIP-44 分层确定性钱包派生:

m / 44' / coin_type' / 0' / 0 / address_index
  • 主种子通过环境变量注入(此 Docker 部署中种子内置于扫描器服务)
  • 数据库仅存储派生索引,不存储私钥
  • 恢复方式:恢复种子短语 + 重放区块链历史

区块链扫描器原理

每条链有独立的扫描器服务:

  1. 按配置间隔(2-15 秒)轮询 RPC 节点
  2. 获取涉及追踪地址的 Transfer 事件
  3. 将事件与待处理的收款订单匹配
  4. 更新订单状态并加入 Webhook 投递队列
  5. 等待链特定的确认数后标记为成功
检测方式出块时间建议确认数
TRONTRON Grid gRPC API~3 秒1-2
EthereumJSON-RPC eth_getLogs~12 秒12-30
BSCJSON-RPC 轮询~3 秒15-30
PolygonJSON-RPC 轮询~2 秒30-100
AvalancheJSON-RPC 轮询~2 秒10-20
ArbitrumJSON-RPC 轮询~1 秒10-20
SUISUI RPC(通过 sui-node-service)~2 秒5-10

生产运维

日常监控

  • 查看服务状态:docker compose ps
  • 查看日志:docker compose logs -f --tail=100 <服务名>
  • 日志持久化在 ./logs/ 目录,每个服务有独立的子目录
  • 建议使用 Uptime Kuma 等工具监控网关可用性

数据库备份

# 手动备份
docker exec xpay-mysql mysqldump -u root -p xpaylabs > backup_$(date +%Y%m%d).sql

# crontab 自动备份(每天凌晨 3 点)
0 3 * * * docker exec xpay-mysql mysqldump -u root -p$MYSQL_ROOT_PASSWORD xpaylabs > /backups/xpaylabs_$(date +\%Y\%m\%d).sql

更新服务

docker compose pull        # 拉取最新镜像
docker compose up -d       # 用新镜像重启

ghcr.io/yan253319066/xpay-java 镜像包含所有 Java JAR 包。新版本发布后更新 docker-compose.yml 中的镜像标签即可。

水平扩展

当前架构为单实例部署。如需扩展:

  • 读副本:添加 MySQL 从库分担查询压力
  • 多扫描器:使用不同 RPC 提供商运行多个扫描器实例实现冗余
  • 负载均衡:将多个网关实例放在 TCP 负载均衡器后面

常见问题排查

ghcr.io 镜像拉取失败

镜像托管在公开的 GitHub Container Registry 上,无需登录即可拉取。常见原因:

  • 网络环境被屏蔽 — 尝试配置 Docker 代理或使用镜像加速器
  • ghcr.io 限流 — 稍后再试

如果确实无法拉取,可以从源码自行构建:

# 构建 Java 服务
cd XPayLabs-java
mvn clean install -P prod -DskipTests
docker build -t ghcr.io/yan253319066/xpay-java .

# 构建前端服务
cd XPayLabs-checkout
docker build -t ghcr.io/yan253319066/checkout .
cd XPayLabs-merchant-vue
docker build -t ghcr.io/yan253319066/merchant-vue .

然后在 docker-compose.yml 中设置 pull_policy: never,或用本地镜像标签覆盖远程镜像名。

MySQL 连接被拒绝

MySQL 首次启动需要 30-60 秒初始化(尤其是导入 SQL 初始化脚本)。检查健康状态:

docker compose logs mysql
docker compose exec mysql mysqladmin ping -h localhost

扫描器检测不到交易

  1. 检查扫描器日志中的 RPC 错误
  2. 确认容器可以访问 RPC 地址
  3. 确认充值地址派生路径与链匹配
  4. 检查 TRON_NETWORKSETH_NETWORKS 中包含正确的网络名

端口冲突

如果宿主机 180 端口已被占用,修改 .env 中的 HOST_PORT_GATEWAY_HTTP 为其他可用端口(如 8080)。所有内部服务端口均可重新映射。

运营成本分析

作为支付平台运营者运行 XPayLabs:

项目月成本
服务器 (4 GB 内存, 2 vCPU)~¥140-280
RPC 节点 (主网)~¥360-1,400 (按链数浮动)
域名 + SSL~¥7-35
合计~¥500-1,700/月

假设向商家收取 0.5% 手续费,月处理 50 万美元流水:

收入项月收入
交易手续费 (0.5%)$2,500
服务器成本-$70-250
净利润~$2,250-2,430/月

总结

XPayLabs 让一条 docker compose up 命令就能拥有完整的加密货币支付基础设施。作为运营者,你需要承担以下运维职责:

  1. 保护主种子 — 离线生成,存放在硬件钱包或加密保险库中
  2. 监控服务健康 — 关注扫描器日志和网关可用性
  3. 备份数据库 — 定期执行 MySQL 备份
  4. 维护 RPC 节点 — 使用可靠的服务商并配置故障转移

SDK(Node.js 和 Java)、收银台 UI 和商家管理后台以 MIT 协议开源在 github.com/yan25331906…。核心网关引擎为源可用许可(XPay Enterprise License)。

SDK 地址:npm | Maven Central