ThunderPhone 2.0 je tu.Začnite sami, že od 2 ¢/min.Preberite obvestilo

Webhooks

Pregled spletnih kljuk

Kako ThunderPhone dostavlja dogodke v realnem času, kako preveriti podpise ter kako se primerjata zastareli model dostave in model dostave, ki temelji na končnih točkah.

ThunderPhone pošlje zahteve HTTP POST vašemu strežniku, ko se med klicem nekaj zgodi — začne se dohodni klic, klic se konča, ocenjevanje se zaključi, sproži se opozorilo in podobno. Obstajata dva modela dostave:

Vseh deset vrst dogodkov v katalogu dogodkov je dostavljenih prek končnih točk webhookov. Šest dogodkov življenjskega cikla klica (telephony.incoming, telephony.complete, telephony.tool, web.incoming, web.complete, web.tool) je prav tako poslanih v zastareli webhook z enim URL-jem — če imate zastareli URL in ujemajočo se končno točko, dogodek prejmete po obeh poteh. Blokirajoče vedenje ( izmenjava konfiguracije telephony.incoming / web.incoming in odpošiljanje orodij v načinu webhook) je na voljo izključno na zastareli poti; vsaka dostava v končno točko je obvestilo brez čakanja na odgovor.

Oblika koristnega tovora

Dostave v končne točke so objekt JSON s polji data, event_id in type:

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

event_id je edinstven za vsak poslan dogodek. Med ponovnimi poskusi je enak in enak je za vsako končno točko, ki prejme dogodek — uporabite ga za odstranjevanje dvojnikov.

Zastareli webhook z enim URL-jem pošlje enaka type in data, vendar brez event_id:

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

Pri prenosu je vsako telo serijsko zapisano kanonično — ključi so razvrščeni po abecedi, brez presledkov, v UTF-8. Lepo oblikovani primeri v tej dokumentaciji so namenjeni zgolj berljivosti.

Za celoten seznam vrst dogodkov in polj koristnega tovora glejte katalog dogodkov.

Preverjanje podpisa

Vsaka zahteva vsebuje podpis HMAC-SHA256 nad surovim telesom zahteve v glavi X-ThunderPhone-Signature. Podpisni ključ je secret končne točke (ali secret spletnega kavlja na ravni vaše organizacije za podedovane dostave).

Koraki

  1. Preberite surovo telo zahteve pred kakršnim koli razčlenjevanjem.
  2. Izračunajte hmac_sha256(secret, body).hexdigest().
  3. V konstantnem času primerjajte z glavo X-ThunderPhone-Signature.

Podpišemo natanko bajte, ki jih pošljemo, ti bajti pa so kanonična serializacija JSON (razvrščeni ključi, strnjena ločila). Zato preverjanje surovega telesa vedno deluje — in če vam vaše ogrodje posreduje samo razčlenjeni JSON, ponovna serializacija z razvrščenimi ključi in strnjenimi ločili ustvari enake bajte. Oba postopka sta opisana v vodniku za preverjanje.

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);
  },
);

Semantika dostave

Ta semantika velja za dostave v končno točko. Zastareli webhook z enim URL-jem je en sam sinhroni poskus brez ponovnih poskusov.

Ponovni poskusi

Vsak dogodek se takoj poskusi dostaviti enkrat. Vsak odgovor 2xx potrdi dostavo. Pri katerem koli drugem izidu (ki ni 2xx, napaka povezave, časovna omejitev) ponovno poskusimo 1 min, 5 min, 30 min, 2 h, 6 h, 12 h in 24 h po prvem poskusu — 8 poskusov v 24 urah. Če vsi poskusi ne uspejo, se dostava ustavi, končna točka pa je v končnih točkah webhookov označena s status="failing". Vrnite 2xx, takoj ko je koristni tovor trajno sprejet; obdelajte ga asinhrono.

Vrstni red

Vrstni red dostave temelji na najboljšem možnem prizadevanju. V praksi dostavljamo v vrstnem redu, v katerem so dogodki poslani, vendar lahko ponovni poskusi ob napaki spremenijo vrstni red. Vedno odstranite podvojitve in uskladite podatke po call_id / ID-ju objekta.

Podvojitve

Dostava je vsaj enkratna: ponovni poskus po odgovoru, ki ga nismo prejeli, lahko podvoji dogodek. Vsak ponovni poskus vsebuje isti event_id, zato shranite obdelane ID-je in preskočite ponovitve. event_id se deli tudi med končnimi točkami — dve končni točki, naročeni na isti dogodek, prejmeta isti event_id.

Časovne omejitve

Dostave v končne točke imajo časovno omejitev 30 s za posamezen poskus. Na zastareli poti se blokirajoče zahteve, ki usmerjajo vedenje klica v živo — izmenjava konfiguracije telephony.incoming / web.incoming — časovno omejijo po 10 s, vendar počasen odgovor zamakne prevzem klica, zato si prizadevajte odgovoriti v nekaj sekundah. Odprema orodij v načinu webhook privzeto omogoča 20 s, deklaracije orodij pa lahko nastavijo timeout na najvišji ravni.

Izvorni IP-naslovi

Odhodni webhooki izvirajo iz obsega IP-naslovov v oblaku ThunderPhone. Če vaš požarni zid zahteva seznam dovoljenih naslovov, se obrnite na podporo in posredovali vam bomo trenutne obsege.

Izbira med zastarelimi webhooki in webhooki na podlagi končnih točk

ZnačilnostZastareli (/v1/webhook)Končne točke (/v1/developer/webhook-endpoints)
Število URL-jev1 na organizacijoVeč na organizacijo
Pokritost dogodkovSamo telephony.* / web.*Vseh 10 vrst dogodkov
Filter dogodkovPo končni točki
Ponovni poskusiBrez8 poskusov v 24 h
Ovojnicatype + datatype + data + event_id
Menjava skrivnostiZamenja eno skrivnostSkrivnost za posamezno končno točko
Onemogočanje brez brisanjaPUT /v1/webhook z {"url": ""}status=disabled
Vidnost stanjaactive / disabled / failing
Blokirajoča izmenjava konfiguracijeDa (telephony.incoming / web.incoming)Nikoli — samo obvestila
Najprimernejše zaDinamično konfiguracijo klicevPrejemanje dogodkov v produkciji

Nove integracije naj prejemajo dogodke prek webhookov na podlagi končnih točk. Zastareli URL obdržite (ali ga dodajte) samo, če klice dinamično konfigurirate ob prevzemu ali uporabljate odpošiljanje orodij v načinu webhook — te izmenjave zahtev in odgovorov se izvajajo samo na zastareli poti.


Povezano