Webhooks
SubHub 通过 Webhook 向你的服务端推送购买与权益变更事件。所有请求使用 HTTPS POST,带签名验证。
概述
当平台发生购买完成、退款、权益发放或撤销等事件时,SubHub 向你配置的 HTTPS 端点发送 POST 请求。
Webhook 在工作区(Workspace)级别配置 — 同一工作区下所有 iOS / Android 应用的事件统一投递,无需按应用重复配置。
这与 App Store / Google Play 的 Inbound 商店通知不同:后者按应用分配接收地址,由 SubHub 自动处理。
事件类型
| 事件 | 触发时机 |
|---|---|
| purchase.completed | 购买验证通过 |
| purchase.refunded | Provider 确认退款 |
| purchase.pending | 购买已上报,待 Provider 确认 |
| entitlement.granted | Entitlement 实例写入 |
| entitlement.revoked | Entitlement 失效 |
| member.created | SDK 首次初始化 |
| member.identified | identify() 关联身份 |
Payload 结构
purchase.completed
{
"id": "evt_a1b2c3d4",
"type": "purchase.completed",
"created_at": "2026-06-27T18:32:00.000Z",
"data": {
"purchase": {
"id": "pur_001",
"member_id": "mem_001",
"product_id": "prod_01PROMO",
"provider": "apple",
"status": "completed",
"amount": 18,
"currency": "CNY"
}
}
}签名验证
每个 Webhook 请求包含 SubHub-Signature 请求头。使用 Webhook Secret 验证 payload 完整性。
签名算法:HMAC-SHA256,timestamp 防重放。
Node.js 验证示例
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const [t, v1] = signature.split(',').map(s => s.split('=')[1]);
const expected = crypto
.createHmac('sha256', secret)
.update(`${t}.${payload}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(v1), Buffer.from(expected)
);
}重试机制
投递失败时,平台采用指数退避自动重试:1 分钟、5 分钟、15 分钟,最多 3 次。
你的端点应返回 2xx 状态码确认接收。非 2xx 响应触发重试。
可在 Webhook 详情页查看投递日志与重试历史。
最佳实践
- 端点必须在 30 秒内响应
- 先验证签名,再处理业务逻辑
- 使用 idempotency — 同一 event id 可能重投
- 异步处理耗时操作,快速返回 200
- Staging 环境使用独立 Webhook 端点