Appearance
Webhook 与签名校验
这页属于高级接入参考。Taria Pay 会把支付状态变化以 POST JSON 的形式发送到商户 webhook endpoint,用于把支付结果回写到你的系统。
如果你是从 Dashboard 的 /developers 开始接入,这页对应的就是:
Webhooks:创建 endpoint、保存 signing secretDelivery Logs:查看投递状态、重试次数和失败原因
如何创建 webhook endpoint
当前仓库支持两种入口:
- Dashboard Developers 页面
POST /internal/merchant-api/webhook-endpoints
示例:
bash
curl -X POST "http://localhost:8080/internal/merchant-api/webhook-endpoints" \
-H "Authorization: Bearer $INTERNAL_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"merchantId":"merchant_demo",
"url":"https://merchant.example/webhooks/payments",
"events":["payment_intent.confirmed","payment_intent.failed"]
}'如果不传 events,当前实现默认只订阅:
text
payment_intent.confirmed如果你通过 Dashboard 的 Developers 页面创建 endpoint,建议至少先订阅:
payment_intent.confirmedpayment_intent.failed
请求头
| Header | 说明 |
|---|---|
x-tariapay-signature | HMAC-SHA256 签名 |
x-tariapay-timestamp | Unix 秒级时间戳 |
x-tariapay-event | 事件名 |
x-tariapay-delivery-id | 单次投递 ID |
兼容期内,服务端也会继续发送旧的 x-pay-* 头。
验签算法
签名原文:
text
${timestamp}.${raw_body}推荐直接用 SDK:
ts
import { TariaPay } from "@tariapay/sdk";
const tariapay = new TariaPay({
secretKey: process.env.TARIAPAY_SECRET_KEY!,
});
const event = tariapay.webhooks.constructEvent(
rawBody,
headers,
process.env.TARIAPAY_WEBHOOK_SECRET!,
);Next.js Route Handler 示例:
ts
import { TariaPay } from "@tariapay/sdk";
const tariapay = new TariaPay({
secretKey: process.env.TARIAPAY_SECRET_KEY!,
baseUrl: process.env.TARIAPAY_API_BASE_URL,
});
export async function POST(req: Request) {
const rawBody = await req.text();
const event = tariapay.webhooks.constructEvent(
rawBody,
req.headers,
process.env.TARIAPAY_WEBHOOK_SECRET!,
);
const paymentIntent = event.data.paymentIntent;
switch (event.type) {
case "payment_intent.confirmed":
// 用 paymentId 或 orderId 幂等更新订单
break;
case "payment_intent.failed":
// 标记订单失败,允许用户重试
break;
default:
break;
}
return Response.json({ received: true });
}如果你不用 SDK,Node.js 原始实现是:
ts
const payloadToVerify = `${headers["x-tariapay-timestamp"]}.${rawBody}`;
const signature = crypto
.createHmac("sha256", signingSecret)
.update(payloadToVerify)
.digest("hex");
const isValid = signature === headers["x-tariapay-signature"];Payload 结构
json
{
"id": "evt_123",
"type": "payment_intent.confirmed",
"createdAt": "2026-03-29T12:00:00.000Z",
"data": {
"paymentIntent": {
"paymentId": "pi_123",
"id": "pi_123",
"orderId": "order_1001",
"status": "confirmed",
"currency": "USDC",
"amount": "49.99",
"checkoutUrl": "https://checkout.tariapay.com/checkout/payment-intents/pi_123",
"txHash": "0x..."
}
}
}投递与重试语义
- endpoint 返回
2xx视为成功 - 非
2xx或超时进入重试 - 当前实现最多尝试 5 次
- Cloud Run 部署推荐每分钟由调度器调用一次
POST /internal/process-webhooks - 手动排查时也可以直接调用该接口推进队列
接入建议
- 先验签,再解析 JSON
- 按
paymentIntent.paymentId或orderId做幂等写入 - webhook 处理尽量快速返回
200 - 用查询接口做兜底,不要把前端页面状态当唯一真相
- 先在 Developers 的 Delivery Logs 看失败原因,再决定是否升级排查
常见排查顺序
- 先确认 endpoint URL 是否可公网访问
- 再确认 signing secret 是否和 Dashboard 里保存的一致
- 看 Delivery Logs 里的响应码、attempt 次数和
last error - 最后再用 payment intent 查询接口或
txHash做状态补偿
相关文档: