Open in
Przegląd webhooków
Jak ThunderPhone dostarcza zdarzenia w czasie rzeczywistym, jak weryfikować podpisy oraz jak wypada porównanie starszego modelu dostarczania z modelem opartym na punktach końcowych.
ThunderPhone wysyła żądania HTTP POST do Twojego serwera, gdy coś
dzieje się podczas połączenia — rozpoczyna się połączenie przychodzące, połączenie się kończy, uruchomienie oceny zostaje ukończone, zostaje wyzwolony alert itd. Dostępne są dwa modele dostarczania:
Wiele adresów URL, sekrety dla poszczególnych endpointów, filtry zdarzeń dla poszczególnych endpointów
oraz automatyczne ponawianie prób.
Zarządzaj za pomocą GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Jeden adres URL na organizację. Obejmuje zdarzenia cyklu życia połączenia, w tym
blokujące wymiany konfiguracji. Zarządzany przez GET/PUT /v1/webhook.
Wszystkie wymienione typy zdarzeń w katalogu zdarzeń są
dostarczane przez endpointy webhooków. Sześć zdarzeń cyklu życia połączenia
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) jest również wysyłanych do
starszego webhooka z jednym adresem URL — jeśli masz zarówno starszy adres URL, jak i
pasujący endpoint, otrzymasz zdarzenie na obu ścieżkach. Zachowanie blokujące
(wymiana konfiguracji telephony.incoming / web.incoming oraz
wywoływanie narzędzi w trybie webhooka)
jest dostępne wyłącznie na starszej ścieżce; każde dostarczenie do endpointu jest
powiadomieniem typu fire-and-forget.
Format ładunku
Dostarczenia do endpointów mają postać obiektu JSON z polami data, event_id i
type:
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}event_id jest unikalne dla każdego wyemitowanego zdarzenia. Jest identyczne przy ponownych próbach
oraz we wszystkich endpointach, które otrzymują zdarzenie — usuwaj duplikaty na jego podstawie.
Starszy webhook z jednym adresem URL wysyła te same pola type i data, ale
bez event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}W transmisji każde body jest serializowane kanonicznie — klucze są sortowane alfabetycznie, bez białych znaków, w UTF-8. Przykłady sformatowane dla czytelności w tej dokumentacji służą wyłącznie ułatwieniu lektury.
Zobacz Katalog zdarzeń, aby uzyskać pełną listę typów zdarzeń i pól ładunku.
Weryfikacja podpisu
Każde żądanie zawiera dwa podpisy, oba HMAC-SHA256 z kluczem secret
punktu końcowego (lub secret webhooka na poziomie organizacji w przypadku starszych
dostaw):
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>podpisuje znacznik czasu, metodę, ścieżkę i zapytanie oraz surową treść. Zweryfikuj ten podpis i odrzucaj żądania, którychtróżni się od czasu na Twoim zegarze o więcej niż 5 minut, aby przechwycone żądanie nie mogło zostać później ponownie odtworzone. Ponowienia są podpisywane ponownie w momencie wysłania.X-ThunderPhone-Signaturepodpisuje tylko surową treść. Nadal jest wysyłany bez zmian, aby istniejące mechanizmy weryfikujące nadal działały.
Kroki
- Odczytaj nagłówek, metodę, surową ścieżkę i zapytanie oraz surowe ciało przed jakimkolwiek parsowaniem.
- Oblicz szesnastkowy HMAC-SHA256 ciągu
<t>\n<METHOD>\n<path and query>\n<body>przy użyciu swojego sekretu. - Odrzuć żądanie, jeśli
tróżni się o więcej niż 300 sekund lub jeśli wynik nie odpowiadav1w porównaniu ze stałym czasem wykonania.
Ciała mają kanoniczną serializację JSON (posortowane klucze, zwięzłe separatory) i podpisujemy dokładnie te bajty, które przesyłamy. Przewodnik po weryfikacji zawiera dokładny podpisywany ciąg, przykład z objaśnieniem, kod bez SDK oraz starszy nagłówek.
from flask import Flask, abort, request
from thunderphone import verify_signature
app = Flask(__name__)
@app.post("/thunderphone-webhook")
def handle():
query = request.query_string.decode()
if not verify_signature(
request.headers.get("X-ThunderPhone-Signature-V2"),
secret=WEBHOOK_SECRET,
method=request.method,
path=request.path + (f"?{query}" if query else ""),
body=request.get_data(), # raw bytes
):
abort(401)
event = request.get_json()
# dispatch on event["type"] …
return "", 204import express from "express";
import { verifySignature } from "@thunderphone/sdk";
const app = express();
app.post(
"/thunderphone-webhook",
express.raw({ type: "application/json" }),
(req, res) => {
const ok = verifySignature({
header: req.header("X-ThunderPhone-Signature-V2"),
secret: process.env.WEBHOOK_SECRET,
method: req.method,
path: req.originalUrl,
body: req.body,
});
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body.toString("utf8"));
// dispatch on event.type …
res.sendStatus(204);
},
);Semantyka dostarczania
Te zasady dotyczą dostarczania do endpointów. Starszy webhook z jednym adresem URL wykonuje pojedynczą synchroniczną próbę bez ponowień, z wyjątkiem wymiany konfiguracji połączenia telefonicznego telephony.incoming, która jest ponawiana jednokrotnie.
Ponowienia
Każde zdarzenie jest natychmiast podejmowane raz. Każda odpowiedź 2xx
potwierdza dostarczenie. Przy każdym innym wyniku (innym niż 2xx,
błędzie połączenia, przekroczeniu limitu czasu) ponawiamy próbę po 1 min, 5 min, 30 min, 2 godz., 6 godz.,
12 godz. i 24 godz. od pierwszej próby — łącznie 8 prób w ciągu
24 godzin. Jeśli wszystkie próby zakończą się niepowodzeniem, dostarczanie zostanie zatrzymane, a endpoint
otrzyma wartość status="failing" w sekcji
endpointy webhooków; wyślemy wiadomość e-mail do
właścicieli i administratorów Twojej organizacji oraz wyświetlimy to w panelu. Zwróć 2xx, gdy tylko
ładunek zostanie trwale przyjęty; przetwarzaj go asynchronicznie.
Wysyłki testowe z interfejsu API testowania endpointów otrzymują jedno ponowienie około minuty po
pierwszej próbie i nigdy nie zmieniają statusu endpointu.
Kolejność
Kolejność dostarczania jest realizowana według najlepszych starań. W praktyce dostarczamy zdarzenia w
kolejności ich emisji, ale ponowienia mogą zmienić kolejność po niepowodzeniu.
Zawsze deduplikuj i uzgadniaj według call_id / identyfikatora obiektu.
Duplikaty
Dostarczanie odbywa się co najmniej raz: ponowienie po odpowiedzi, której nie
otrzymaliśmy, może zduplikować zdarzenie. Każde ponowienie zawiera ten sam
event_id, dlatego przechowuj przetworzone identyfikatory i pomijaj powtórzenia. event_id jest
także współdzielony między punktami końcowymi — dwa punkty końcowe subskrybujące to
samo zdarzenie otrzymują ten sam event_id.
Limity czasu
Dostarczanie do endpointów ma limit czasu 30 s na próbę. W starszej
ścieżce blokujące żądania sterujące zachowaniem aktywnego połączenia — wymiana
konfiguracji telephony.incoming / web.incoming
— są ograniczone do 10 s dla pierwszej próby połączenia
telefonicznego i 13 s dla całej wymiany, łącznie z jednym
ponowieniem, oraz do 10 s dla sesji widżetu. Powolna odpowiedź opóźnia
odebranie połączenia, dlatego staraj się odpowiadać w ciągu kilku sekund. Wysyłanie narzędzi w trybie webhooka domyślnie umożliwia 20 s,
a deklaracje narzędzi mogą ustawiać timeout na najwyższym poziomie.
Źródłowe adresy IP
Wychodzące webhooki pochodzą z zakresu adresów IP chmury ThunderPhone. Jeśli zapora wymaga listy dozwolonych adresów, skontaktuj się z pomocą techniczną, a udostępnimy aktualne zakresy.
Wybór między starszymi webhookami a webhookami opartymi na punktach końcowych
| Funkcja | Starsze (/v1/webhook) | Punkty końcowe (/v1/developer/webhook-endpoints) |
|---|---|---|
| Liczba adresów URL | 1 na organizację | Wiele na organizację |
| Obsługiwane zdarzenia | Tylko telephony.* / web.* | Wszystkie 10 typów zdarzeń |
| Filtr zdarzeń | — | Dla każdego punktu końcowego |
| Ponowne próby | Brak, z wyjątkiem jednej dla wymiany konfiguracji połączenia telefonicznego | 8 prób w ciągu 24 h |
| Koperta | type + data | type + data + event_id |
| Rotacja sekretu | Zastępuje pojedynczy sekret | Sekret dla każdego punktu końcowego |
| Wyłączenie bez usuwania | PUT /v1/webhook z {"url": ""} | status=disabled |
| Widoczność statusu | — | active / disabled / failing |
| Blokująca wymiana konfiguracji | Tak (telephony.incoming / web.incoming) | Nigdy — tylko powiadomienia |
| Najlepsze zastosowanie | Dynamiczna konfiguracja połączeń | Obsługa zdarzeń w środowisku produkcyjnym |
Nowe integracje powinny odbierać zdarzenia przez webhooki oparte na punktach końcowych. Zachowaj (lub dodaj) starszy adres URL tylko wtedy, gdy konfigurujesz połączenia dynamicznie w momencie odebrania lub używasz wywoływania narzędzi w trybie webhooków — te wymiany żądanie/odpowiedź działają tylko w starszej ścieżce.
Powiązane
Wszystkie typy zdarzeń i ich ładunki.
Zarządzaj wieloma punktami końcowymi, filtrami zdarzeń i sekretami.
Blokujące żądanie, na które serwer musi odpowiedzieć, aby skonfigurować połączenia.
Ładunek po połączeniu z transkrypcją, nagraniem i metrykami.