ThunderPhone 2.0 вече е тук.Започнете самостоятелно — от 2 цента/мин.Прочетете съобщението

Webhooks

Общ преглед на уебкуките

Как ThunderPhone доставя събития в реално време, как да проверявате подписи и как се сравняват наследеният и базираният на крайни точки модели за доставка.

ThunderPhone изпраща HTTP POST заявки до вашия сървър, когато по време на разговор се случат определени неща — започва входящ разговор, разговорът приключва, изпълнение на оценяване завършва, задейства се предупреждение и т.н. Има два модела за доставка:

Всички изброени типове събития в каталога на събитията се доставят чрез webhook крайни точки. Шестте събития от жизнения цикъл на разговорите (telephony.incoming, telephony.complete, telephony.tool, web.incoming, web.complete, web.tool) се изпращат също до остарелия webhook с един URL адрес — ако имате както остарял URL адрес, така и съвпадаща крайна точка, получавате събитието и по двата пътя. Блокиращото поведение (обменът на конфигурация telephony.incoming / web.incoming и изпращането на инструменти в режим webhook) съществува единствено по остарелия път; всяка доставка до крайна точка е уведомление без изчакване.

Формат на полезния товар

Доставките до крайни точки са JSON обект с data, event_id и type:

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

event_id е уникален за всяко генерирано събитие. Той е идентичен при повторни опити и за всяка крайна точка, която получава събитието — използвайте го за дедупликация.

Остарелият webhook с един URL адрес изпраща същите type и data, но без event_id:

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

При предаване всеки body се сериализира канонично — ключовете са подредени по азбучен ред, без празни интервали, в UTF-8. Примерите с форматиране в тази документация са само за по-лесно четене.

Вижте Каталога на събитията за пълния списък с типове събития и полета на полезния товар.

Проверка на подписа

Всяка заявка съдържа два подписа, и двата HMAC-SHA256 с ключ secret на крайната точка (или secret на webhook на ниво организация за наследени доставки):

  • X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex> подписва времевото клеймо, метода, пътя и заявката, както и необработеното тяло. Проверявайте този подпис и отхвърляйте заявки, чийто t се различава с повече от 5 минути от вашия часовник, така че прихваната заявка да не може да бъде повторно изпълнена по-късно. Повторните опити се подписват отново при изпращането им.
  • X-ThunderPhone-Signature подписва само необработеното тяло. Той все още се изпраща без промяна, за да продължат да работят съществуващите механизми за проверка.

Стъпки

  1. Прочетете заглавката, метода, суровия път и низа на заявката, както и суровото тяло преди всякакъв анализ.
  2. Изчислете шестнадесетичния HMAC-SHA256 на <t>\n<METHOD>\n<path and query>\n<body> с вашата тайна.
  3. Отхвърлете заявката, ако t се отклонява с повече от 300 секунди или ако резултатът не съвпада с v1 при сравнение в константно време.

Телата са в канонична JSON сериализация (сортирани ключове, компактни разделители) и подписваме точно байтовете, които предаваме. Ръководството за проверка съдържа точния подписван низ, пример с изчисления, код без SDK и наследената заглавка.

Python (Flask)
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 "", 204
Node.js (Express)
import 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);
  },
);

Семантика на доставянето

Тази семантика се прилага за доставки към крайни точки. Наследеният webhook с един URL е един синхронен опит без повторни опити, с изключение на обмена на конфигурация за телефонни обаждания telephony.incoming, който се повтаря веднъж.

Повторни опити

За всяко събитие се прави един незабавен опит. Всеки отговор 2xx потвърждава доставката. При всеки друг резултат (не-2xx, грешка във връзката, изчакване) правим повторен опит 1 m, 5 m, 30 m, 2 h, 6 h, 12 h и 24 h след първия опит — 8 опита в рамките на 24 часа. Ако всички опити са неуспешни, доставката спира и крайната точка се маркира с status="failing" в крайните точки за webhook; изпращаме имейл до собствениците и администраторите на вашата организация и показваме това в таблото. Върнете 2xx веднага щом полезният товар бъде надеждно приет; обработвайте асинхронно. Тестовите изпращания от API за тестване на крайната точка получават един повторен опит приблизително минута след първия опит и никога не променят статуса на крайната точка.

Подреждане

Подреждането на доставянията е с най-добро усилие. На практика доставяме в реда, в който се генерират събитията, но повторните опити могат да променят реда при неуспех. Винаги премахвайте дубликати и съгласувайте по call_id / id на обекта.

Дубликати

Доставянето е поне веднъж: повторен опит след отговор, който не сме получили, може да дублира събитие. Всеки повторен опит съдържа същия event_id, затова съхранявайте обработените id и пропускайте повторенията. event_id се споделя и между крайни точки — две крайни точки, абонирани за едно и също събитие, получават един и същ event_id.

Изчаквания

Доставките към крайни точки имат изчакване от 30 s за всеки опит. По наследения път блокиращите заявки, които управляват поведението на активно обаждане — обменът на конфигурация telephony.incoming / web.incoming — са ограничени до 10 s за първия опит на телефонно обаждане и 13 s за целия обмен, включително неговия единствен повторен опит, и до 10 s за сесия на widget. Бавният отговор забавя приемането на обаждането, затова се стремете да отговаряте в рамките на няколко секунди. Изпращането на инструменти в режим webhook позволява 20 s по подразбиране, а декларациите на инструменти могат да задават timeout от най-горно ниво.

IP адреси на източника

Изходящите уебкуки произхождат от диапазона облачни IP адреси на ThunderPhone. Ако защитната ви стена изисква списък с разрешени адреси, свържете се с поддръжката и ще споделим актуалните диапазони.

Избор между наследени уебкуки и уебкуки, базирани на крайни точки

ФункцияНаследени (/v1/webhook)Крайни точки (/v1/developer/webhook-endpoints)
Брой URL адреси1 на организацияМного на организация
Обхват на събитиятаСамо telephony.* / web.*Всички 10 типа събития
Филтър за събития—За всяка крайна точка
Повторни опитиНяма, с изключение на един за обмена на конфигурация при телефонно обаждане8 опита за 24 ч.
Обвивкаtype + datatype + data + event_id
Смяна на секретЗаменя единствения секретСекрет за всяка крайна точка
Деактивиране без изтриванеPUT /v1/webhook с {"url": ""}status=disabled
Видимост на състоянието—active / disabled / failing
Блокиращ обмен на конфигурацияДа (telephony.incoming / web.incoming)Никога — само известия
Подходящо заДинамична конфигурация на обажданияПолучаване на събития в продукционна среда

Новите интеграции трябва да получават събития чрез уебкуки, базирани на крайни точки. Запазете (или добавете) наследен URL само ако конфигурирате повиквания динамично при приемането им или използвате извикване на инструменти в режим на уебкуки — тези обмени заявка/отговор се изпълняват само по наследения път.


Свързани