Megérkezett a ThunderPhone 2.0.Önkiszolgáló használat már 2 cent/perctől.Olvassa el a bejelentést

Webhooks

Webhookok áttekintése

Megtudhatja, hogyan kézbesíti a ThunderPhone a valós idejű eseményeket, hogyan ellenőrizheti az aláírásokat, és hogyan hasonlíthatók össze a régi és a végpont-alapú kézbesítési modellek.

ThunderPhone HTTP POST kéréseket küld az Ön szerverére, amikor egy hívás során esemény történik — bejövő hívás indul, hívás ér véget, értékelési futtatás fejeződik be, riasztás aktiválódik stb. Két kézbesítési modell áll rendelkezésre:

Az eseménykatalógusban szereplő mind a tíz eseménytípus webhook-végpontokon keresztül kerül kézbesítésre. A hat hívás-életciklus esemény (telephony.incoming, telephony.complete, telephony.tool, web.incoming, web.complete, web.tool) szintén elküldésre kerül a régi, egy URL-es webhooknak — ha régi URL-je és egyező végpontja is van, az eseményt mindkét útvonalon megkapja. A blokkoló működés (a telephony.incoming / web.incoming konfigurációs adatcsere és a webhook módú eszközindítás) kizárólag a régi útvonalon érhető el; minden végpontkézbesítés küldés és továbblépés típusú értesítés.

Hasznos teher formátuma

A végpontkézbesítések data, event_id és type mezőket tartalmazó JSON-objektumok:

{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}

Az event_id minden kibocsátott eseményhez egyedi. Azonos az újrapróbálkozások során és minden, az eseményt fogadó végponton — ennek alapján végezzen duplikációszűrést.

A régi, egy URL-es webhook ugyanazt a type és data értéket küldi, de event_id nélkül:

{
  "type": "telephony.incoming",
  "data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}

Átvitelkor minden törzs kanonikusan van szerializálva — a kulcsok ábécérendben szerepelnek, nincs szóköz, a kódolás UTF-8. A dokumentációban látható, formázott példák kizárólag az olvashatóságot szolgálják.

Az eseménytípusok és a hasznos teher mezőinek teljes listáját az Eseménykatalógusban találja.

Aláírás-ellenőrzés

Minden kérés HMAC-SHA256-aláírást tartalmaz a nyers kéréstörzsön a X-ThunderPhone-Signature fejlécben. Az aláírókulcs a végpont secret értéke (vagy régi kézbesítések esetén a szervezeti szintű webhook secret értéke).

Lépések

  1. Bármilyen feldolgozás előtt olvassa be a nyers kéréstörzset.
  2. Számítsa ki a hmac_sha256(secret, body).hexdigest() értékét.
  3. Hasonlítsa össze konstans időben a X-ThunderPhone-Signature fejléccel.

Pontosan azokat a bájtokat írjuk alá, amelyeket továbbítunk, és ezek a kanonikus JSON-sorosítás bájtjai (rendezett kulcsok, tömör elválasztók). Ezért a nyers törzshöz viszonyított ellenőrzés mindig működik — és ha a keretrendszere csak feldolgozott JSON-t ad át, annak rendezett kulcsokkal és tömör elválasztókkal történő újrasorosítása azonos bájtokat eredményez. Mindkét módszert ismerteti az ellenőrzési útmutató.

Python
import hmac
import hashlib
 
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature or "")
 
# Example Flask handler
from flask import Flask, request, abort
app = Flask(__name__)
 
@app.post("/thunderphone-webhook")
def handle():
    body = request.get_data()
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    if not verify_signature(body, sig, WEBHOOK_SECRET):
        abort(401)
    event = request.get_json()
    # dispatch on event["type"] …
    return "", 204
Node.js (Express)
import crypto from "node:crypto";
import express from "express";
 
function verifySignature(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),
  );
}
 
const app = express();
app.post(
  "/thunderphone-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const sig = req.header("X-ThunderPhone-Signature") || "";
    if (!verifySignature(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);
  },
);

Kézbesítési szemantika

Ezek a szemantikák a végpontokra történő kézbesítésekre vonatkoznak. Az örökölt, egyetlen URL-es webhook egyetlen szinkron kísérletet használ, újrapróbálkozás nélkül.

Újrapróbálkozások

Minden eseményt azonnal egyszer megkísérlünk kézbesíteni. Bármely 2xx válasz nyugtázza a kézbesítést. Minden egyéb esetben (nem 2xx, kapcsolati hiba, időtúllépés) újrapróbálkozunk az első kísérlet után 1 perc, 5 perc, 30 perc, 2 óra, 6 óra, 12 óra és 24 óra elteltével — ez 8 kísérlet 24 órán belül. Ha minden kísérlet sikertelen, a kézbesítés leáll, és a végpont status="failing" jelölést kap a webhook-végpontoknál. Adjon vissza 2xx választ, amint a hasznos adat tartósan fogadásra került; dolgozza fel aszinkron módon.

Sorrendiség

A kézbesítési sorrend csak legjobb szándék szerinti. A gyakorlatban az eseményeket a kibocsátásuk sorrendjében kézbesítjük, de hibák esetén az újrapróbálkozások megváltoztathatják a sorrendet. Mindig végezzen deduplikációt és egyeztetést call_id / objektumazonosító alapján.

Duplikátumok

A kézbesítés legalább egyszeri: egy általunk nem észlelt válasz utáni újrapróbálkozás duplikálhat egy eseményt. Minden újrapróbálkozás ugyanazt az event_id azonosítót tartalmazza, ezért tárolja a feldolgozott azonosítókat, és hagyja ki az ismétlődéseket. Az event_id a végpontok között is megosztott — két, ugyanarra az eseményre feliratkozott végpont ugyanazt az event_id azonosítót kapja.

Időtúllépések

A végpontokra történő kézbesítések időtúllépése kísérletenként 30 s. Az örökölt útvonalon az élő hívási viselkedést vezérlő blokkoló kérések — a telephony.incoming / web.incoming konfigurációs adatcsere — 10 s után időtúllépnek, de a lassú válasz késlelteti a hívás fogadását, ezért törekedjen néhány másodpercen belüli válaszadásra. A webhook módú eszközhívás alapértelmezés szerint 20 s-ot engedélyez, és az eszközdeklarációk felső szintű timeout értéket is megadhatnak.

Forrás IP-címek

A kimenő webhookok a ThunderPhone felhőbeli IP-tartományából származnak. Ha a tűzfala engedélyezési listát igényel, lépjen kapcsolatba a támogatással, és megosztjuk az aktuális tartományokat.

Választás az örökölt és a végpont-alapú webhookok között

FunkcióÖrökölt (/v1/webhook)Végpontok (/v1/developer/webhook-endpoints)
URL-ek száma1 szervezetenkéntTöbb szervezetenként
EseménylefedettségCsak telephony.* / web.*Mind a 10 eseménytípus
EseményszűrőVégpontonként
ÚjrapróbálkozásokNincs8 kísérlet 24 óra alatt
Borítéktype + datatype + data + event_id
Titok rotációjaEgyetlen titkot cserélVégpontonkénti titok
Letiltás törlés nélkülstatus=disabled
Állapot láthatóságaactive / disabled / failing
Blokkoló konfigurációs adatcsereIgen (telephony.incoming / web.incoming)Soha — csak értesítések
Legjobb felhasználásDinamikus híváskonfigurációEsemények feldolgozása éles környezetben

Az új integrációknak végpont-alapú webhookokon keresztül kell feldolgozniuk az eseményeket. Csak akkor tartson meg (vagy adjon hozzá) örökölt URL-t, ha a hívásokat dinamikusan konfigurálja a fogadáskor, vagy webhook módú eszközhívást használ — ezek a kérés/válasz adatcserék csak az örökölt útvonalon futnak.


Kapcsolódó tartalom