Open in
Webhook apžvalga
Kaip ThunderPhone pateikia įvykius realiuoju laiku, kaip patikrinti parašus ir kuo skiriasi senasis bei galinio taško pagrindu veikiantys pateikimo modeliai.
ThunderPhone siunčia HTTP POST užklausas į jūsų serverį, kai skambučio
metu įvyksta tam tikri veiksmai — prasideda įeinantis skambutis, baigiasi skambutis, užbaigiamas vertinimo
vykdymas, suveikia įspėjimas ir pan. Yra du pristatymo
modeliai:
Kelios URL, kiekvienam galiniam taškui skirti slapti raktai, kiekvienam galiniam taškui skirti įvykių filtrai
ir automatiniai pakartotiniai bandymai.
Valdykite naudodami GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Viena URL vienai organizacijai. Perduoda skambučio ciklo įvykius, įskaitant
blokuojančius konfigūracijos mainus. Valdoma per GET/PUT /v1/webhook.
Visi dešimt įvykių tipų, pateiktų įvykių kataloge,
pristatomi per žiniatinklio kabliuko galinius taškus. Šeši skambučio ciklo įvykiai
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) taip pat siunčiami į
senąjį vienos URL žiniatinklio kabliuką — jei turite ir senąją URL, ir
atitinkamą galinį tašką, įvykį gaunate abiejais keliais. Blokavimo
veikimas ( telephony.incoming / web.incoming konfigūracijos
mainai ir žiniatinklio kabliuko režimo
įrankių iškvietimas) galimas
tik senuoju keliu; kiekvienas pristatymas į galinį tašką yra
pranešimas, kuriam atsakymo nelaukiama.
Naudingosios apkrovos formatas
Į galinius taškus pristatoma JSON objektas su data, event_id ir
type:
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}event_id yra unikalus kiekvienam sugeneruotam įvykiui. Jis yra toks pats per pakartotinius bandymus
ir visuose galiniuose taškuose, kurie gauna įvykį — naudokite jį dublikatams pašalinti.
Senasis vienos URL žiniatinklio kabliukas siunčia tuos pačius type ir data, tačiau
be event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}Perduodant tinklu, kiekvienas užklausos turinys serializuojamas kanoniškai — raktai surūšiuojami abėcėlės tvarka, nėra tarpų, naudojamas UTF-8. Šiuose dokumentuose pateikti skaitymui suformatuoti pavyzdžiai skirti tik aiškumui.
Visą įvykių tipų ir naudingosios apkrovos laukų sąrašą rasite įvykių kataloge.
Parašo patvirtinimas
Kiekvienoje užklausoje antraštėje X-ThunderPhone-Signature pateikiamas HMAC-SHA256 parašas, apskaičiuotas pagal neapdorotą užklausos
turinį. Pasirašymo raktas yra galinio taško secret (arba organizacijos lygio webhook secret, skirtas senesniems
pristatymams).
Veiksmai
- Perskaitykite neapdorotą užklausos turinį prieš bet kokį analizavimą.
- Apskaičiuokite
hmac_sha256(secret, body).hexdigest(). - Pastoviuoju laiku palyginkite su antrašte
X-ThunderPhone-Signature.
Pasirašome tiksliai tuos baitus, kuriuos perduodame, o tie baitai yra kanoninis JSON serializavimas (surikiuoti raktai, kompaktiški skirtukai). Todėl patvirtinimas pagal neapdorotą turinį visada veikia — o jei jūsų sistema pateikia tik išanalizuotą JSON, pakartotinis jo serializavimas su surikiuotais raktais ir kompaktiškais skirtukais sukuria identiškus baitus. Abu būdai aprašyti patvirtinimo vadove.
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 "", 204import 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);
},
);Pristatymo semantika
Ši semantika taikoma galinio punkto pristatymams. Senasis vieno URL žiniatinklio kabliukas yra vienas sinchroninis bandymas be pakartotinių bandymų.
Pakartotiniai bandymai
Kiekvienas įvykis iškart bandomas pristatyti vieną kartą. Bet koks 2xx atsakymas
patvirtina pristatymą. Esant bet kokiai kitai baigčiai (ne 2xx,
ryšio klaidai, laiko limitui), bandome dar kartą po 1 min., 5 min., 30 min., 2 val., 6 val.,
12 val. ir 24 val. nuo pirmojo bandymo — iš viso 8 bandymai per
24 valandas. Jei nepavyksta visiems bandymams, pristatymas sustabdomas, o galinis punktas
žiniatinklio kabliukų galiniuose punktuose pažymimas būsena
status="failing". Grąžinkite 2xx iškart, kai naudingasis krovinys
patikimai priimamas; apdorokite jį asinchroniškai.
Eiliškumas
Pristatymo eiliškumas užtikrinamas dedant visas pastangas. Praktikoje pristatome tokia
tvarka, kuria įvykiai sugeneruojami, tačiau nepavykus bandymams pakartotiniai bandymai gali pakeisti eilę.
Visada šalinkite dublikatus ir sutaikykite pagal call_id / objekto ID.
Dublikatai
Pristatymas yra bent kartą: pakartotinis bandymas po atsakymo, kurio negavome,
gali dubliuoti įvykį. Kiekvienas pakartotinis bandymas turi tą patį
event_id, todėl saugokite apdorotus ID ir praleiskite pasikartojimus. event_id taip pat
bendrinamas tarp galinių punktų — du galiniai punktai, užsiprenumeravę tą
patį įvykį, gauna tą patį event_id.
Laiko limitai
Galinių punktų pristatymams taikomas 30 s laiko limitas kiekvienam bandymui. Senajame
kelyje blokuojančios užklausos, lemiančios tiesioginio skambučio veikimą —
telephony.incoming / web.incoming
konfigūracijos apsikeitimas — baigia galioti po 10 s, tačiau lėtas
atsakymas vėlina skambučio priėmimą, todėl siekite atsakyti per kelias
sekundes. Žiniatinklio kabliuko režimo įrankių iškvietimas pagal numatytuosius nustatymus leidžia 20 s,
o įrankių deklaracijose galima nustatyti aukščiausio lygio timeout.
Šaltinio IP adresai
Siunčiami žiniatinklio kabliukai gaunami iš ThunderPhone debesijos IP adresų diapazono. Jei jūsų užkarda reikalauja leidžiamųjų sąrašo, susisiekite su palaikymo komanda ir pateiksime aktualius diapazonus.
Pasirinkimas tarp senųjų ir galinių punktų pagrindu veikiančių žiniatinklio kabliukų
| Funkcija | Senasis (/v1/webhook) | Galiniai punktai (/v1/developer/webhook-endpoints) |
|---|---|---|
| URL skaičius | 1 vienai organizacijai | Keli vienai organizacijai |
| Įvykių aprėptis | Tik telephony.* / web.* | Visi 10 įvykių tipų |
| Įvykių filtras | — | Kiekvienam galiniam punktui |
| Pakartotiniai bandymai | Nėra | 8 bandymai per 24 val. |
| Vokas | type + data | type + data + event_id |
| Slaptojo rakto keitimas | Pakeičia vieną slaptąjį raktą | Slaptasis raktas kiekvienam galiniam punktui |
| Išjungimas neištrinant | PUT /v1/webhook su {"url": ""} | status=disabled |
| Būsenos matomumas | — | active / disabled / failing |
| Blokuojantis konfigūracijos apsikeitimas | Taip (telephony.incoming / web.incoming) | Niekada — tik pranešimai |
| Geriausia naudoti | Dinaminei skambučių konfigūracijai | Įvykių vartojimui produkcinėje aplinkoje |
Naujose integracijose įvykius reikėtų vartoti per galinių punktų pagrindu veikiančius žiniatinklio kabliukus. Senąjį URL palikite (arba pridėkite) tik jei dinamiškai konfigūruojate skambučius jų priėmimo metu arba naudojate žiniatinklio kabliuko režimo įrankių iškvietimą — šie užklausos ir atsakymo apsikeitimai vykdomi tik senuoju keliu.
Susiję
Visi įvykių tipai ir jų naudingi kroviniai.
Tvarkykite kelis galinius punktus, įvykių filtrus ir slaptuosius raktus.
Blokuojanti užklausa, į kurią jūsų serveris turi atsakyti, kad sukonfigūruotų skambučius.
Po skambučio pateikiamas naudingasis krovinys su transkriptu, įrašu ir metrika.