Webhook 与通知
与其循环轮询 GET /order/{id},不如让 TRONAgg 在事件发生时主动推送给你。只需连接一次 Webhook(或 Telegram),你订阅的每个事件都会以带签名的 JSON 请求送达。
GET /order/{id} 仍可用于按需查询。但订单状态无需轮询——订阅 order.status_changed Webhook,当 COMPLETED / FAILED 事件到达时更新你自己的记录即可。
渠道
通知通过以下两种渠道之一送达,两者的事件与偏好设置完全一致:
- Webhook——向你的后端发送带签名的 JSON
POST。面向开发者与自动化。 - Telegram——在 Telegram 会话中收到可读的提醒。无需代码。
配置 Webhook
Webhook 在 Workspace 中配置,而非通过 API:
- 打开 Workspace → Notifications → Delivery methods → Webhook → Connect。
- 填写名称和一个返回
2xx的 HTTPS URL。 - 复制签名密钥(signing secret)——它只显示一次。请作为服务端密钥保存,验证每次投递都需要它。
- 在 Notifications 标签页选择哪些事件发往该 Webhook。用 Send test 发送一条示例投递,用 Delivery history 查看最近的尝试记录。
事件格式
每次投递都是一个 JSON 请求体的 POST,结构如下:
{
"id": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"type": "order.status_changed",
"created_at": "2026-07-12T10:30:00Z",
"audience": "customer",
"data": {
"order_id": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"status": "COMPLETED",
"resource_type": "ENERGY",
"resource_amount": "65000",
"receiver_address": "TC7UXt...GbQs",
"total_price_sun": 3500000,
"error_message": null
}
}
| 字段 | 含义 |
|---|---|
id | 唯一事件 id——用于去重(投递为至少一次)。 |
type | 事件类型(见 事件)。 |
created_at | 事件发生时间(ISO-8601,UTC)。 |
audience | customer 或 reseller。 |
data | 与事件相关的负载。 |
请求头
| 请求头 | 值 |
|---|---|
Content-Type | application/json |
X-TronAgg-Event | 事件 type。 |
X-TronAgg-Delivery | 唯一投递 id(同一投递重试时保持不变)。 |
X-TronAgg-Timestamp | 签名时的 Unix 秒。 |
X-TronAgg-Signature | v1=<hex>——HMAC 签名(见下)。 |
验证签名
在信任任何投递之前务必先验证。签名为:
hex( HMAC_SHA256( secret, timestamp + "." + rawBody ) )
请在原始请求体(而非重新序列化后的对象)与 X-TronAgg-Timestamp 头上计算,然后用常量时间比较与 v1= 之后的十六进制值对比。拒绝时间戳过旧的投递以防重放攻击。
import hashlib
import hmac
import time
def verify(secret: str, headers: dict, raw_body: bytes) -> bool:
timestamp = headers["X-TronAgg-Timestamp"]
signature = headers["X-TronAgg-Signature"].removeprefix("v1=")
# 拒绝超过 5 分钟的请求(重放保护)。
if abs(time.time() - int(timestamp)) > 300:
return False
expected = hmac.new(
secret.encode(),
timestamp.encode() + b"." + raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
import crypto from 'node:crypto';
function verify(secret, headers, rawBody) {
const timestamp = headers['x-tronagg-timestamp'];
const signature = headers['x-tronagg-signature'].replace(/^v1=/, '');
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
事件
在 Workspace 中按事件订阅。对集成最有用的是 order.status_changed。
| 事件 | 触发时机 |
|---|---|
order.status_changed | 订单进入终态——data.status 为 COMPLETED 或 FAILED。用它替代轮询。 |
balance.credited | 一笔充值或转账到账。 |
balance.low | 余额跌破你设定的阈值(每次跌破发送一次)。 |
account.daily_summary | 订单、能量与消费的每日汇总。 |
autoenergy.activated | 某地址的 AutoEnergy 订阅已激活。 |
autoenergy.delegated | AutoEnergy 对订阅地址的一笔转账计费(可选开启——每笔转账触发)。 |
autoenergy.closed | AutoEnergy 订阅已关闭——data.close_reason 说明原因(idle、quota、expired、insufficient_balance、manual 等)。 |
order.status_changed 的 data 包含 order_id、status、resource_type、resource_amount、receiver_address、total_price_sun 及 error_message(FAILED 时给出)。发往 reseller 受众的投递还包含客户与每单收益。
AutoEnergy 的 data 字段:autoenergy.activated 包含 subscription_id 与 address;autoenergy.delegated 另含 energy_class(65k/131k)、billed_sun 与 used_tx_id;autoenergy.closed 另含 close_reason 与 tx_used_total。每个事件的示例载荷见 Workspace 通知页。
Webhook 的 data.status 为大写(COMPLETED / FAILED),与线上 API 一致。
投递与重试
- 当你的端点在 10 秒内返回
2xx时,投递成功。不跟随重定向。 - 失败的投递按退避策略重试(约 1m → 5m → 30m → 2h → 12h)后放弃。
- 投递为至少一次——同一事件可能到达多次。请按事件
id(或X-TronAgg-Delivery)去重。 - 尽快返回
2xx并异步处理;把重活移出请求路径。