ThunderPhone 2.0 sasa inapatikana.Anza mwenyewe, kuanzia 2¢/dakika.Soma tangazo

Operations

Thibitisha sahihi za webhook

Kila ombi la webhook na zana linalotumwa na ThunderPhone husainiwa. Thibitisha sahihi mara moja kwa kutumia utaratibu ulio hapa, kisha tumia tena ukaguzi huo huo kwenye kila endpoint unayoendesha.

Kila ombi tunalotuma kwa seva yako — uwasilishaji wa webhook na uitishaji wa endpoint za zana — hubeba sahihi ya HMAC-SHA256 katika kichwa cha X-ThunderPhone-Signature. Fanya uthibitishaji kwa usahihi mara moja na utumie kisadizi hichohicho katika kila kidhibiti.

Algoriti

  1. Soma mwili ghafi wa ombi — baiti kamili tulizotuma kwako kwa POST.
  2. Kokotoa hmac_sha256(secret, body).hexdigest().
  3. Linganisha kwa muda usiobadilika na X-ThunderPhone-Signature. (Ulinganishaji wa kawaida wa mifuatano huvuja taarifa za muda.)

Tunatia sahihi baiti kamili tunazotuma, kwa hivyo kuthibitisha mwili ghafi hufanya kazi kila wakati. Baiti hizo pia ni uundaji sanifu wa JSON wa mzigo — funguo zimepangwa kialfabeti, vitenganishi vifupi (, na : bila nafasi), UTF-8. Hilo hukupa mbinu ya pili iliyo sawa kabisa wakati fremu yako hutoa JSON iliyochanganuliwa pekee: unda upya kwa muundo sanifu kisha utumie HMAC kwa huo.

# Equivalent to hashing the raw body:
import json
canonical = json.dumps(payload, separators=(",", ":"), sort_keys=True).encode("utf-8")

Pendelea mwili ghafi — ni hatua moja pungufu na hauathiriwi na changamoto za ubadilishaji wa namba za JSON kwenda na kurudi katika baadhi ya lugha.

Siri ipi?

ChanzoSiri
Endpoint ya webhook (/v1/developer/webhook-endpoints)secret ya kila endpoint (herufi 48 za heksadesimali) inayorejeshwa mara moja wakati wa kuunda
Webhook ya zamani ya URL mojasecret ya kila shirika inayorejeshwa kwenye GET /v1/webhook
Uitishaji wa endpoint ya zana (mwito wa moja kwa moja kwa endpoint.url yako)Siri ya webhook ya kiwango cha shirika (sawa na ile ya webhook ya zamani ya URL moja) — si siri ya kila endpoint

Hifadhi siri katika kidhibiti chako cha siri au kigeu cha mazingira — usiiweke kamwe kwenye commit.

Utekelezaji wa marejeleo

Zote nne huthibitisha mwili ghafi wa ombi:

Python
import hashlib
import hmac
 
 
def verify(body: bytes, signature: str, secret: str) -> bool:
    """Constant-time HMAC-SHA256 verification."""
    expected = hmac.new(
        secret.encode("utf-8"),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature or "")
Node.js
import crypto from "node:crypto";
 
export function verify(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  if (!signature || expected.length !== signature.length) return false;
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature),
  );
}
Go
package webhook
 
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
)
 
func Verify(body []byte, signature, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signature))
}
Ruby
require "openssl"
 
def verify(body, signature, secret)
  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, body)
  Rack::Utils.secure_compare(expected, signature.to_s)
end

Uunganishaji mahususi wa framework

FastAPI
from fastapi import FastAPI, HTTPException, Request
 
app = FastAPI()
 
@app.post("/thunderphone-webhook")
async def hook(request: Request):
    body = await request.body()           # raw bytes, NOT request.json()
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    if not verify(body, sig, SECRET):
        raise HTTPException(status_code=401)
 
    import json
    event = json.loads(body)
    # … dispatch on event["type"] …
    return {"ok": True}
Express
import express from "express";
 
const app = express();
 
app.post(
  "/thunderphone-webhook",
  // IMPORTANT: parse as raw; do NOT use express.json() here.
  express.raw({ type: "application/json" }),
  (req, res) => {
    const sig = req.header("X-ThunderPhone-Signature") || "";
    if (!verify(req.body, sig, process.env.WEBHOOK_SECRET)) {
      return res.sendStatus(401);
    }
    const event = JSON.parse(req.body.toString("utf8"));
    // … dispatch on event.type …
    res.sendStatus(204);
  },
);
Django
import json
 
from django.http import JsonResponse, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
 
 
@csrf_exempt
@require_POST
def hook(request):
    body = request.body  # raw bytes
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    if not verify(body, sig, SECRET):
        return HttpResponseForbidden("invalid signature")
    event = json.loads(body)
    # … dispatch on event["type"] …
    return JsonResponse({"ok": True})

Kuthibitisha miito ya zana

Ejenti inapoitisha moja kwa moja mojawapo ya zana zako za function (zana ina endpoint), ombi hubeba header mbili za ThunderPhone pamoja na endpoint.headers ulizosanidi:

  • X-ThunderPhone-Call-ID — kitambulisho cha nambari cha simu inayoendelea.
  • X-ThunderPhone-Signature — HMAC-SHA256, yenye ufunguo wa siri ya webhook ya kiwango cha shirika, juu ya baiti halisi za mwili wa ombi.

Kisaidizi kilekile cha verify() hufanya kazi bila mabadiliko, kwa mambo mawili ya kuzingatia:

  1. Zana za GET / DELETE hazina mwili. Hoja hupitishwa kama vigezo vya query, na sahihi huhesabiwa juu ya mfuatano tupu wa baiti — kwa hivyo verify(b"", sig, secret) (Python) au verify(Buffer.alloc(0), sig, secret) (Node). Usihesabu hash ya mfuatano wa query.
  2. Mashirika yasiyo na webhook ya zamani iliyosanidiwa hayana siri ya shirika. Katika hali hiyo miito ya zana hubeba X-ThunderPhone-Call-ID pekee na haina header ya sahihi. Sanidi webhook ya zamani (PUT /v1/webhook) ili kupata siri ya kutia sahihi, au thibitisha miito ya zana kwa header yako mwenyewe kupitia endpoint.headers.
@app.post("/tools/search-appointments")
async def tool(request: Request):
    body = await request.body()  # b"" for GET/DELETE tools
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    call_id = request.headers.get("X-ThunderPhone-Call-ID", "")
    if not verify(body, sig, ORG_WEBHOOK_SECRET):
        raise HTTPException(status_code=401)
    args = json.loads(body)
    ...

Usambazaji wa zana katika hali ya webhook (zana zisizo na endpoint, zinazoletwa kwenye webhook ya shirika lako kama telephony.tool / web.tool) ni webhook ya kawaida iliyotiwa sahihi — utaratibu wa kawaida hapo juu unatumika. Tazama Zana za Function kwa miundo yote miwili ya ombi.

Changamoto za kawaida

Kusajili upya kwa uumbizaji chaguo-msingi

Kuchanganua mwili na kuutoa tena kwa chaguo-msingi za maktaba yako ya JSON (nafasi baada ya , / :, funguo zilizo kwa mpangilio wa uingizaji) huzalisha baiti tofauti na kuharibu HMAC. Thibitisha mwili ghafi — au ikiwa ni lazima uusajili upya, linganisha muundo wetu wa kanoni hasa: funguo zilizopangwa, vitenganishi fupi, UTF-8.

Framework huchanganua JSON kiotomatiki

Middleware ya express.json() ya Express hutumia mtiririko wa mwili na unapoteza baiti ghafi. Tumia express.raw() mahsusi kwenye njia ya webhook, au hifadhi mwili ghafi kwenye pre-middleware. Hali ni sawa kwa NestJS / Koa — angalia nyaraka zao za "raw body".

Ulinganisho usio salama kwa muda

expected === signature katika JS au expected == signature katika Python ni ulinganisho unaobadilika kulingana na muda. Tumia crypto.timingSafeEqual au hmac.compare_digest mtawalia. Tofauti ya utendaji haipo.

Siri isiyo sahihi kwa endpoint za zana

Miito ya moja kwa moja ya endpoint za zana husainiwa kwa siri ya webhook ya kiwango cha shirika (GET /v1/webhook) — si kwa siri yoyote ya kila endpoint kutoka /v1/developer/webhook-endpoints. Tumia tena kitendakazi kilekile cha verify(), lakini hakikisha unakipa siri ya shirika kwenye njia za zana.

Kuheshi mfuatano wa hoja kwenye zana za GET/DELETE

Kwa mbinu za zana zisizo na mwili, sahihi hufunika mfuatano tupu wa baiti, ikidumisha utaratibu mmoja wa jumla: HMAC mwili ghafi wa ombi, wowote ulivyo. Kuheshi URL au mfuatano wa hoja hakutalingana kamwe.

Kutorejesha 401 kunapokuwa na kutolingana

Kurejesha 200 uthibitishaji unaposhindwa hufanya kishughulikiaji kuwa lengo la mashambulizi ya kurudia ombi. Daima jibu kwa hali isiyo ya 2xx uthibitishaji unaposhindwa.


Hatua zinazofuata