Tīmekļa āķu pārskats
Kā ThunderPhone piegādā reāllaika notikumus, kā verificēt parakstus un kā salīdzināmi mantotais un galapunktos balstītais piegādes modelis.
ThunderPhone nosūta HTTP POST pieprasījumus uz jūsu serveri, kad zvana
laikā notiek kāds notikums — sākas ienākošs zvans, zvans beidzas, tiek pabeigta
novērtēšanas izpilde, tiek aktivizēts brīdinājums utt. Ir divi piegādes
modeļi:
Vairāki URL, atsevišķi noslēpumi katram galapunktam, notikumu filtri katram galapunktam
un automātiski atkārtoti mēģinājumi.
Pārvaldiet ar GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Viens URL katrai organizācijai. Ietver zvana dzīves cikla notikumus, tostarp
bloķējošās konfigurācijas apmaiņas. Pārvalda ar GET/PUT /v1/webhook.
Visi desmit notikumu veidi notikumu katalogā tiek
piegādāti, izmantojot tīmekļa aizķeru galapunktus. Seši zvana dzīves cikla notikumi
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) tiek arī nosūtīti uz
mantoto tīmekļa aizķeri ar vienu URL — ja jums ir gan mantotais URL, gan
atbilstošs galapunkts, notikumu saņemat pa abiem ceļiem. Bloķējošā
darbība (telephony.incoming / web.incoming konfigurācijas
apmaiņa un tīmekļa aizķera režīma
rīku nosūtīšana) ir pieejama
tikai mantotajā ceļā; katra piegāde uz galapunktu ir paziņojums bez atbildes gaidīšanas.
Lietderīgās slodzes formāts
Galapunktu piegādes ir JSON objekts ar data, event_id un
type:
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}event_id ir unikāls katram izsūtītajam notikumam. Tas ir identisks atkārtotos
mēģinājumos un visos galapunktos, kas saņem notikumu — izmantojiet to dublikātu novēršanai.
Mantotais tīmekļa aizķeris ar vienu URL nosūta to pašu type un data, bet
bez event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}Pārsūtē katrs pamatteksts tiek serializēts kanoniski — atslēgas sakārtotas alfabētiski, bez atstarpēm, UTF-8. Šajā dokumentācijā glīti formatētie piemēri ir paredzēti tikai lasāmībai.
Skatiet Notikumu katalogu, lai iegūtu pilnu notikumu veidu un lietderīgās slodzes lauku sarakstu.
Paraksta verifikācija
Katram pieprasījumam galvenē X-ThunderPhone-Signature ir HMAC-SHA256 paraksts
pār neapstrādāto pieprasījuma pamattekstu. Parakstīšanas atslēga ir
galapunkta secret (vai jūsu organizācijas līmeņa tīmekļa aizķeres secret
mantotajām piegādēm).
Darbības
- Nolasiet neapstrādāto pieprasījuma pamattekstu pirms jebkādas parsēšanas.
- Aprēķiniet
hmac_sha256(secret, body).hexdigest(). - Salīdziniet to ar galveni
X-ThunderPhone-Signaturekonstantā laikā.
Mēs parakstām tieši baitus, ko nosūtām, un šie baiti ir kanoniskā JSON serializācija (sakārtotas atslēgas, kompakti atdalītāji). Tāpēc verifikācija pret neapstrādāto pamattekstu vienmēr darbojas — un, ja jūsu ietvars nodod tikai parsētu JSON, tā atkārtota serializēšana ar sakārtotām atslēgām un kompaktiem atdalītājiem rada identiskus baitus. Abas metodes ir aprakstītas verifikācijas ceļvedī.
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);
},
);Piegādes semantika
Šī semantika attiecas uz galapunktu piegādēm. Mantotais viena URL webhook ir viens sinhrons mēģinājums bez atkārtotiem mēģinājumiem.
Atkārtoti mēģinājumi
Katrs notikums tiek mēģināts piegādāt vienu reizi nekavējoties. Jebkura 2xx atbilde
apstiprina piegādi. Jebkura cita iznākuma gadījumā (ne-2xx,
savienojuma kļūda, taimauts) mēs atkārtoti mēģinām pēc 1 min, 5 min, 30 min, 2 h, 6 h,
12 h un 24 h pēc pirmā mēģinājuma — 8 mēģinājumi 24 stundu
laikā. Ja visi mēģinājumi neizdodas, piegāde tiek pārtraukta un galapunkts
webhook galapunktos tiek atzīmēts ar
status="failing". Atgrieziet 2xx, tiklīdz datu pakotne ir
droši saglabāta; apstrādājiet to asinhroni.
Secība
Piegādes secība tiek nodrošināta pēc iespējas. Praksē mēs piegādājam notikumus
to izraisīšanas secībā, taču neveiksmju gadījumā atkārtoti mēģinājumi var mainīt secību.
Vienmēr noņemiet dublikātus un saskaņojiet pēc call_id / objekta id.
Dublikāti
Piegāde ir vismaz vienreiz: atkārtots mēģinājums pēc atbildes, kuru mēs
nesaņēmām, var dublēt notikumu. Katrs atkārtotais mēģinājums ietver to pašu
event_id, tāpēc saglabājiet apstrādātos id un izlaidiet atkārtojumus. event_id tiek
koplietots arī starp galapunktiem — divi galapunkti, kas abonē
vienu un to pašu notikumu, saņem vienādu event_id.
Taimauti
Galapunktu piegādēm katram mēģinājumam ir 30 s taimauts. Mantotajā
ceļā bloķējošie pieprasījumi, kas nosaka aktīva zvana darbību —
telephony.incoming / web.incoming
konfigurācijas apmaiņa — sasniedz taimautu pēc 10 s, taču lēna
atbilde aizkavē zvana pieņemšanu, tāpēc centieties atbildēt dažu
sekunžu laikā. Webhook režīma rīku izsaukšana pēc noklusējuma
atļauj 20 s, un rīku deklarācijas var iestatīt augstākā līmeņa timeout.
Avota IP adreses
Izejošie webhooki tiek sūtīti no ThunderPhone mākoņa IP diapazona. Ja jūsu ugunsmūrim nepieciešams atļauju saraksts, sazinieties ar atbalsta dienestu, un mēs kopīgosim aktuālos diapazonus.
Izvēle starp mantotajiem un uz galapunktiem balstītajiem webhookiem
| Funkcija | Mantotais (/v1/webhook) | Galapunkti (/v1/developer/webhook-endpoints) |
|---|---|---|
| URL skaits | 1 katrai organizācijai | Vairāki katrai organizācijai |
| Notikumu pārklājums | Tikai telephony.* / web.* | Visi 10 notikumu tipi |
| Notikumu filtrs | — | Katram galapunktam |
| Atkārtoti mēģinājumi | Nav | 8 mēģinājumi 24 h laikā |
| Aploksne | type + data | type + data + event_id |
| Slepenās atslēgas rotācija | Aizstāj vienoto slepeno atslēgu | Slepenā atslēga katram galapunktam |
| Deaktivizēšana bez dzēšanas | — | status=disabled |
| Statusa redzamība | — | active / disabled / failing |
| Bloķējoša konfigurācijas apmaiņa | Jā (telephony.incoming / web.incoming) | Nekad — tikai paziņojumi |
| Vispiemērotākais | Dinamiska zvanu konfigurēšana | Notikumu apstrāde produkcijas vidē |
Jaunām integrācijām notikumi jāsaņem, izmantojot uz galapunktiem balstītus webhookus. Saglabājiet (vai pievienojiet) mantoto URL tikai tad, ja konfigurējat zvanus dinamiski zvana pieņemšanas laikā vai izmantojat webhook režīma rīku izsaukšanu — šīs pieprasījuma/atbildes apmaiņas darbojas tikai mantotajā ceļā.
Saistīts
Visi notikumu tipi un to datu pakotnes.
Pārvaldiet vairākus galapunktus, notikumu filtrus un slepenās atslēgas.
Bloķējošais pieprasījums, uz kuru jūsu serverim jāatbild, lai konfigurētu zvanus.
Pēc zvana nosūtāma datu pakotne ar atšifrējumu, ierakstu un metrikām.