选择语言

Webhook

在你的服务器上实时接收激活事件,验证 SmsGrab-Signature 请求头,并了解重试、测试推送和自动停用。

本页内容
  1. 事件
  2. 创建 Webhook
  3. 推送格式
  4. 验证签名
  5. 快速响应
  6. 重试
  7. 自动停用
  8. 测试与重新推送

Webhook 会在事件发生时立即推送到你的服务器,你无需反复查询。一个 Webhook 属于一个 API 密钥。它接收用该密钥购买的号码的事件,以及你账号的余额不足提醒。

事件

事件 触发时机
activation.created 购买了号码
activation.code_received 每条新短信,附带目前为止的所有消息
activation.completed 由你完成,或收到验证码后时间结束
activation.cancelled 在任何验证码前取消,已退款
activation.expired 未及时收到验证码,已退款
activation.refunded 每笔扣款退款
balance.low 余额降到你设置的阈值以下
webhook.test 你发起的测试推送

创建 Webhook

在 账号 > 开发者 中打开一个密钥,填写 URL、需要的事件和可选的描述,即可添加 Webhook。每个密钥最多可以有 3 个 Webhook。

URL 必须:

  • 以 https:// 开头;
  • 使用主机名,而不是 IP 地址;
  • 指向公网地址。私有网络、localhost 以及类似网段会被拒绝。

你会收到一个以 whsec_ 开头的签名密钥。与 API 密钥一样,它只显示一次。你之后可以更换它,更换时同样需要输入密码。

推送格式

HTTP
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: SmsGrab-Webhooks/1.0
SmsGrab-Event: activation.code_received
SmsGrab-Delivery: 9f7d6c1e-2b44-4c1a-8f0e-6a3d2c1b0e9f
SmsGrab-Signature: t=1790503200,v1=3b9a0c…

{ "id": "evt_4e1f…", "type": "activation.code_received", "created_at": "2026-09-27T10:06:12.004Z",
  "api_version": "2026-09-27", "data": { "activation": { "id": "5c1d0c2e-…", "status": "CODE_RECEIVED" } } }

验证签名

SmsGrab-Signature 包含时间戳 t 和 v1。v1 是以你的签名密钥为密钥,对 t、一个句点和原始请求体拼接后计算的 HMAC-SHA256。请拒绝时间戳与你的时钟相差超过 300 秒的推送,并以恒定时间比较签名。

PHP
[$t, $v1] = (function (string $h): array {
    parse_str(str_replace(',', '&', $h), $p);
    return [(int) ($p['t'] ?? 0), (string) ($p['v1'] ?? '')];
})($_SERVER['HTTP_SMSGRAB_SIGNATURE'] ?? '');
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $t.'.'.$body, getenv('SMSGRAB_WEBHOOK_SECRET'));
$ok = abs(time() - $t) <= 300 && hash_equals($expected, $v1);
Python
import hmac, hashlib, time

def verify(header: str, body: bytes, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return abs(time.time() - t) <= 300 and hmac.compare_digest(expected, parts.get("v1", ""))
JavaScript
import crypto from 'node:crypto';

export function verify(header, rawBody, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const t = Number(parts.t ?? 0);
  const expected = crypto.createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest('hex');
  const given = Buffer.from(parts.v1 ?? '', 'utf8');
  return Math.abs(Date.now() / 1000 - t) <= 300 && given.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(expected, 'utf8'), given);
}

请始终在解析 JSON 之前,用收到的原始请求体进行验证。

快速响应

请在 10 秒内 返回任意 2xx 状态,耗时的工作之后再处理,例如放入队列。不会跟随重定向。

重试

推送失败后,会在 1 分钟、5 分钟、15 分钟、1 小时、3 小时、6 小时、12 小时和 24 小时后重试。重试会携带相同的事件 id,因此请保存已处理的 ID 并跳过重复推送。同一激活的事件会按顺序到达。

自动停用

  • 返回 410 Gone 会立即停用 Webhook。
  • 在至少 24 小时内连续失败 50 次后,Webhook 会被停用,你会收到通知。修复你的接口后,请重新启用 Webhook。
  • 吊销密钥会停用其 Webhook。

测试与重新推送

在 Webhook 页面发送 webhook.test 事件,即可立即看到状态码、响应时间和任何错误。推送记录会保存每次推送 30 天,你可以重新推送其中任意一条。

这篇文章对您有帮助吗?

仍需要帮助?

给我们留言。我们会回复每一条消息,通常在几小时内。

或发送邮件至 support@smsgrab.com