跳到主要内容

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:

  1. 打开 Workspace → Notifications → Delivery methods → Webhook → Connect
  2. 填写名称和一个返回 2xx 的 HTTPS URL。
  3. 复制签名密钥(signing secret)——它只显示一次。请作为服务端密钥保存,验证每次投递都需要它。
  4. 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)。
audiencecustomerreseller
data与事件相关的负载。

请求头

请求头
Content-Typeapplication/json
X-TronAgg-Event事件 type
X-TronAgg-Delivery唯一投递 id(同一投递重试时保持不变)。
X-TronAgg-Timestamp签名时的 Unix 秒。
X-TronAgg-Signaturev1=<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.statusCOMPLETEDFAILED用它替代轮询。
balance.credited一笔充值或转账到账。
balance.low余额跌破你设定的阈值(每次跌破发送一次)。
account.daily_summary订单、能量与消费的每日汇总。
autoenergy.activated某地址的 AutoEnergy 订阅已激活。
autoenergy.delegatedAutoEnergy 对订阅地址的一笔转账计费(可选开启——每笔转账触发)。
autoenergy.closedAutoEnergy 订阅已关闭——data.close_reason 说明原因(idlequotaexpiredinsufficient_balancemanual 等)。

order.status_changeddata 包含 order_idstatusresource_typeresource_amountreceiver_addresstotal_price_sunerror_messageFAILED 时给出)。发往 reseller 受众的投递还包含客户与每单收益。

AutoEnergy 的 data 字段:autoenergy.activated 包含 subscription_idaddressautoenergy.delegated 另含 energy_class65k/131k)、billed_sunused_tx_idautoenergy.closed 另含 close_reasontx_used_total。每个事件的示例载荷见 Workspace 通知页。

状态大小写

Webhook 的 data.status 为大写(COMPLETED / FAILED),与线上 API 一致。

投递与重试

  • 当你的端点在 10 秒内返回 2xx 时,投递成功。不跟随重定向。
  • 失败的投递按退避策略重试(约 1m → 5m → 30m → 2h → 12h)后放弃。
  • 投递为至少一次——同一事件可能到达多次。请按事件 id(或 X-TronAgg-Delivery)去重。
  • 尽快返回 2xx 并异步处理;把重活移出请求路径。

下一步