ThunderPhone 2.0 је стигао.Почните самостално, већ од 2 ¢/мин.Прочитајте објаву

Webhooks

Преглед вебхукова

Како ThunderPhone испоручује догађаје у реалном времену, како да верификујете потписе и како се пореде застарели модели испоруке и модели засновани на крајњим тачкама.

ThunderPhone шаље HTTP POST захтеве вашем серверу када се догађаји дешавају током позива — започне се долазни позив, позив се заврши, покретање оцењивања се доврши, активира се упозорење и тако даље. Постоје два модела испоруке:

Сви наведени типови догађаја у каталогу догађаја испоручују се путем крајњих тачака веб-хукова. Шест догађаја животног циклуса позива (telephony.incoming, telephony.complete, telephony.tool, web.incoming, web.complete, web.tool) такође се шаљу на застарели веб-хук са једним URL-ом — ако имате и застарели URL и одговарајућу крајњу тачку, примате догађај на обе путање. Блокирајуће понашање (размена конфигурације telephony.incoming / web.incoming и слање алата у режиму веб-хука слање алата) постоји искључиво на застарелој путањи; свака испорука крајњој тачки је обавештење без чекања одговора.

Формат садржаја

Испоруке крајњим тачкама су 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 је јединствен за сваки емитовани догађај. Идентичан је при поновним покушајима и на свакој крајњој тачки која прими догађај — користите га за уклањање дупликата.

Застарели веб-хук са једним URL-ом шаље исти type и data, али без event_id:

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

При преносу, сваки садржај се серијализује канонски — кључеви су сортирани по абецеди, без размака, у UTF-8 формату. Примери са форматираним увлачењем у овој документацији служе само ради читљивости.

Погледајте Каталог догађаја за комплетну листу типова догађаја и поља садржаја.

Верификација потписа

Сваки захтев садржи два потписа, оба HMAC-SHA256 са кључем secret крајње тачке (или secret веб-хука на нивоу ваше организације за застареле испоруке):

  • 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 чим је payload трајно прихваћен; обрађујте га асинхроно. Пробна слања из API-ја за тестирање крајње тачке имају један поновни покушај приближно минут након првог покушаја и никада не мењају статус крајње тачке.

Редослед

Редослед испоруке се обезбеђује у најбољој мери. У пракси испоручујемо редоследом којим се догађаји емитују, али поновни покушаји могу променити редослед при неуспеху. Увек уклањајте дупликате и усклађујте податке према call_id / ИД-у објекта.

Дупликати

Испорука је најмање једном: поновни покушај након одговора који никада нисмо примили може дуплирати догађај. Сваки поновни покушај носи исти event_id, зато чувајте обрађене ИД-ове и прескачите понављања. event_id се такође дели између крајњих тачака — две крајње тачке претплаћене на исти догађај примају исти event_id.

Истек времена

Испоруке крајњим тачкама имају истек времена од 30 s по покушају. На застарелој путањи, блокирајући захтеви који управљају понашањем позива уживо — размена конфигурације telephony.incoming / web.incoming — ограничени су на 10 s за први покушај телефонског позива и 13 s за целу размену, укључујући њен један поновни покушај, као и на 10 s за сесију виџета. Спор одговор одлаже прихватање позива, зато настојте да одговорите у року од неколико секунди. Отпремање алатки у webhook режиму подразумевано дозвољава 20 s, а декларације алатки могу поставити timeout на највишем нивоу.

Изворне IP адресе

Одлазни вебхукови потичу из ThunderPhone опсега IP адреса у облаку. Ако ваш заштитни зид захтева листу дозвољених адреса, обратите се подршци и ми ћемо поделити тренутне опсеге.

Избор између застарелих вебхукова и вебхукова заснованих на крајњим тачкама

ФункцијаЗастарели (/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 само ако конфигуришете позиве динамички у тренутку прихватања или користите покретање алатки у режиму вебхука — те размене захтева и одговора извршавају се само на застарелој путањи.


Повезано