文档
使用 SMetaGateway 进行开发。
从服务器创建 USDT TRC20 发票、引导买家进入收银台并通过签名 Webhook 确认付款所需的一切。
概述
SMetaGateway 是 TRON 上 USDT 的非托管发票层。商户登记公开收款地址,买家直接向该地址付款。网关为每张发票分配唯一的精确金额,跟踪其状态,记录会计数据并通知您的服务器。
所有 API 端点都位于本网站同源的 /api/v1 下。金额始终为最多六位小数的十进制字符串——绝不使用浮点数。
- 您的服务器 → SMetaGateway1POST /api/v1/invoices,并附带 Idempotency-Key
- SMetaGateway → 您的服务器2返回包含 payable_amount 和 checkout_url 的发票
- 您的服务器 → 买家3将买家重定向到 checkout_url
- 买家 → SMetaGateway4买家打开付款页并扫描二维码
- 买家 → 您的 TRON 钱包5买家向您的地址发送精确的 USDT 金额
- SMetaGateway6网关在链上找到精确金额并确认发票
- SMetaGateway → 您的服务器7已签名的 invoice.confirmed Webhook
- 您的服务器 → SMetaGateway8GET /api/v1/invoices/{id} 核实后再履行订单
数据路径资金路径
快速开始
1. 创建工作区并添加 TRON 收款地址,复制其钱包 ID。
2. 打开“开发者 → API 密钥”,创建一个带有效期的密钥。密钥以 smg_ 开头,只显示一次,请妥善保存。
3. 使用下方请求从服务器创建发票。保存发票 ID 和精确的 payable_amount。
4. 将买家重定向到 checkout_url。只有在验证 invoice.confirmed Webhook 并在服务器端查询发票后,才能将订单标记为已付款。
curl -X POST "https://smg.sabco24.com/api/v1/invoices" \
-H "Authorization: Bearer $SMETA_API_KEY" \
-H "Idempotency-Key: order-1001" \
-H "Content-Type: application/json" \
-d '{"merchant_order_id":"1001","amount":"49.95","wallet_id":"WALLET_ID","description":"Example order","expires_in_minutes":20}'身份验证
服务器集成使用 bearer API 密钥进行认证:Authorization: Bearer smg_…。密钥具有 invoices:read、invoices:write 和 ledger:read 权限,并可设置在 30、90 或 365 天后过期。过期密钥会返回 401 api_key_expired;可在控制台中轮换以获取新密钥。请将密钥保存在服务器上,切勿放入浏览器或移动应用。
官方控制台使用 HttpOnly 会话 Cookie。账户、钱包登记、API 密钥和 Webhook 管理均需要所有者会话,无法通过 API 密钥执行。
curl "https://smg.sabco24.com/api/v1/invoices/INVOICE_ID" \
-H "Authorization: Bearer $SMETA_API_KEY"金额与识别
以十进制字符串(如 "49.95")提交基础价格。网关会添加正向识别调整额——低于 100 USDT 时为 0.000001 至 0.009999 USDT,100 USDT 及以上为 0.000001 至 0.999999 USDT——并分别返回 base_amount、adjustment 和 payable_amount。
精确应付总额在所有商户之间按相同网络、代币和收款地址保留 90 天。优先使用未用过的总额;复用的总额会使发票进入 review 状态,而不会自动确认。
按网络、代币和收款地址保留 90 天
{
"base_amount": "49.950000",
"adjustment": "0.003821",
"payable_amount": "49.953821"
}发票与幂等性
POST /api/v1/invoices 需要 Idempotency-Key 请求头。使用相同密钥重复相同请求会返回原发票并带有 idempotent_replay: true;以不同内容复用密钥会返回 409 idempotency_conflict。
每个 merchant_order_id 只能对应一张发票。请将返回的发票 ID 和 payable_amount 与订单一起保存,并在 Webhook 到达时进行比对。
POST /invoices + Idempotency-Key- 新的密钥201 — 创建新发票
- 相同密钥、相同请求体返回原发票,idempotent_replay: true
- 相同密钥、不同请求体409 idempotency_conflict
{
"invoice": {
"id": "6f1c…",
"merchant_order_id": "1001",
"base_amount": "49.950000",
"adjustment": "0.003821",
"payable_amount": "49.953821",
"status": "pending",
"mode": "live",
"checkout_url": "https://smg.sabco24.com/checkout/…",
"expires_at": "2026-10-21T12:20:00.000Z",
"reserved_until": "2027-01-19T12:00:00.000Z"
},
"idempotent_replay": false
}收银台与发票状态
checkout_url 是一个授权链接:持有者即可查看对付款人安全的信息,请妥善保密。收银台显示商户名称、金额明细、收款地址、二维码和有效期,绝不显示您的元数据或内部 ID。
发票状态为 pending、confirmed、expired 或 review 之一。收银台在 expires_in_minutes(默认 20,最大 1440)后过期;金额保留期独立持续 90 天。
pending- 收到精确金额
confirmed - 付款时间已到
expired - 金额被复用或需人工核查
review
签名 Webhook
在控制台中登记公开的 HTTPS 端点(443 端口)。签名密钥只显示一次。事件包括 invoice.created、invoice.confirmed、invoice.expired、invoice.review 和 webhook.test。投递最多重试八次,也可手动重试。
每个请求都带有 X-SMeta-Event-Id、X-SMeta-Timestamp 和 X-SMeta-Signature 请求头。对 timestamp + "." + 原始请求体计算 HMAC-SHA256,进行常量时间比较,拒绝超过五分钟的时间戳,然后再解析 JSON。每个事件 ID 只处理一次。
- 1读取原始请求体和 X-SMeta-* 请求头
- 2时间戳是否在 5 分钟内?拒绝(4xx)
- 3HMAC-SHA256(timestamp + "." + body)
- 4与 X-SMeta-Signature 进行恒定时间比较拒绝(4xx)
- 5该事件 ID 是否已处理?返回 2xx,跳过
- 6更新订单并返回 2xx
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody: Buffer, headers: Record<string, string>, secret: string) {
const timestamp = headers['x-smeta-timestamp'];
const signature = headers['x-smeta-signature'] ?? '';
if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return null;
const expected = 'sha256=' + createHmac('sha256', secret)
.update(timestamp + '.').update(rawBody).digest('hex');
const a = Buffer.from(expected), b = Buffer.from(signature);
if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
const event = JSON.parse(rawBody.toString('utf8'));
return event.id === headers['x-smeta-event-id'] ? event : null;
}错误与速率限制
错误返回包含 error.code 和 error.message 的 JSON。常见状态码:400 校验失败、401 未认证、403 权限或来源不符、404 不存在、409 冲突或需审核、429 请求过多。
每个商户每分钟最多创建 120 张发票。对 429 和 5xx 响应请使用退避策略,并使用相同的 Idempotency-Key 重试。
{
"error": {
"code": "idempotency_conflict",
"message": "This idempotency key was used with different invoice details."
},
"mode": "live"
}集成
控制台提供 32 个可复制示例,涵盖 Node.js、NestJS、PHP、Laravel、Python、Django、Go、Java、C#、Ruby、React、Next.js、Vue 以及 WooCommerce、Magento、Shopware 等电商平台。可下载的 WooCommerce 插件为预览版,尚不支持正式环境 API 密钥。
这些示例并非正式发布的 SDK。前端示例调用您自己的后端,由后端保管 API 密钥。
付款确认
网关通过 TronGrid 读取 TRON 主网,查找转入每个有未结发票的收款地址的已确认 USDT TRC20 转账,并用成功的固化交易回执逐笔复核。在发票创建与过期之间转入精确 payable_amount 的转账会确认该发票,交易哈希保存为 tx_hash。
过期后到账、与曾使用过的金额相同,或对应已在审核中的发票的转账,会将状态设为 review,绝不会自动确认。检测通常需要几分钟。零佣金和非托管设计本身并不构成免税或监管授权。