ThunderPhone 2.0 เปิดให้ใช้งานแล้วเริ่มใช้งานได้ด้วยตัวเอง ราคาเริ่มต้น 2 เซนต์ต่อนาที.อ่านประกาศเปิดตัว

Webhooks

ภาพรวม Webhook

วิธีที่ 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" }
}

ในการส่งจริง เนื้อหาทุกรายการจะถูกซีเรียลไลซ์แบบมาตรฐาน — คีย์เรียงตาม ตัวอักษร ไม่มีช่องว่าง ใช้ UTF-8 ตัวอย่างที่จัดรูปแบบให้อ่านง่ายใน เอกสารนี้มีไว้เพื่อให้อ่านง่ายเท่านั้น

ดูแค็ตตาล็อกเหตุการณ์สำหรับรายการประเภทเหตุการณ์ และฟิลด์เพย์โหลดทั้งหมด

การตรวจสอบลายเซ็น

ทุกคำขอมีลายเซ็นสองรายการ โดยทั้งสองรายการใช้ HMAC-SHA256 ที่คีย์ด้วย secret ของ ปลายทาง (หรือ webhook 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);
  },
);

ความหมายของการส่ง

ความหมายเหล่านี้ใช้กับการส่งไปยัง ปลายทาง เว็บฮุก URL เดียวแบบเดิมเป็นการพยายามแบบซิงโครนัสเพียงครั้งเดียวโดยไม่มีการลองใหม่ ยกเว้นการแลกเปลี่ยนการกำหนดค่าระหว่างการโทร telephony.incoming ซึ่งจะลองใหม่หนึ่งครั้ง

การลองใหม่

แต่ละอีเวนต์จะถูกพยายามส่งทันทีหนึ่งครั้ง การตอบกลับ 2xx ใดๆ จะยืนยันการส่ง สำหรับผลลัพธ์อื่นๆ ทั้งหมด (ไม่ใช่ 2xx ข้อผิดพลาดการเชื่อมต่อ หมดเวลา) เราจะลองใหม่ที่ 1 m, 5 m, 30 m, 2 h, 6 h, 12 h, and 24 h after the first attempt — รวม 8 ครั้งภายใน 24 ชั่วโมง หากทุกความพยายามล้มเหลว การส่งจะหยุดลงและปลายทางจะถูกทำเครื่องหมายเป็น status="failing" ในหน้า ปลายทางเว็บฮุก เราจะส่งอีเมลถึงเจ้าของและผู้ดูแลระบบขององค์กรคุณ และแสดงสถานะในแดชบอร์ด ส่งคืน 2xx ทันทีที่ยอมรับและจัดเก็บเพย์โหลดอย่างคงทน แล้วประมวลผลแบบอะซิงโครนัส การส่งทดสอบจาก API ทดสอบปลายทางจะลองใหม่หนึ่งครั้งหลังจากความพยายามแรกประมาณหนึ่งนาที และจะไม่เปลี่ยนสถานะของปลายทาง

ลำดับ

ลำดับการส่งเป็นแบบพยายามอย่างดีที่สุด ในทางปฏิบัติ เราส่งตาม ลำดับที่อีเวนต์ถูกปล่อยออกมา แต่การลองใหม่อาจทำให้ลำดับเปลี่ยนเมื่อเกิดความล้มเหลว ให้ขจัดข้อมูลซ้ำและกระทบยอดโดยใช้ call_id / รหัสออบเจ็กต์เสมอ

รายการซ้ำ

การส่งเป็นแบบ อย่างน้อยหนึ่งครั้ง: การลองใหม่หลังจากการตอบกลับที่เราไม่เคย เห็นอาจทำให้อีเวนต์ซ้ำได้ การลองใหม่ทุกครั้งมี event_id เดียวกัน ดังนั้นให้จัดเก็บรหัสที่ประมวลผลแล้วและข้ามรายการซ้ำ event_id จะ ใช้ร่วมกันระหว่างเอ็นด์พอยต์ด้วย — เอ็นด์พอยต์สองรายการที่สมัครรับ อีเวนต์เดียวกันจะได้รับ event_id เดียวกัน

การหมดเวลา

การส่งไปยังปลายทางมีเวลาหมดเวลา 30 s ต่อความพยายามหนึ่งครั้ง ในเส้นทางแบบเดิม คำขอแบบบล็อกที่ขับเคลื่อนพฤติกรรมการโทรสด — การแลกเปลี่ยนการกำหนดค่า telephony.incoming / web.incoming — ถูกจำกัดไว้ที่ 10 s สำหรับความพยายามแรกของการโทร และ 13 s สำหรับการแลกเปลี่ยนทั้งหมดรวมการลองใหม่หนึ่งครั้ง และ 10 s สำหรับเซสชันวิดเจ็ต การตอบกลับที่ช้าจะทำให้การรับสายล่าช้า ดังนั้นควรตอบกลับภายในไม่กี่วินาที การเรียกใช้เครื่องมือในโหมดเว็บฮุกอนุญาตให้ใช้เวลา 20 s ตามค่าเริ่มต้น และการประกาศเครื่องมืออาจกำหนด timeout ระดับบนสุดได้

IP ต้นทาง

เว็บฮุกขาออกมาจากช่วง IP บนคลาวด์ของ ThunderPhone หากไฟร์วอลล์ของคุณต้องใช้รายการที่อนุญาต โปรดติดต่อฝ่ายสนับสนุน แล้วเราจะแชร์ ช่วงปัจจุบันให้

การเลือกระหว่างเว็บฮุกแบบเดิมและแบบอิงเอ็นด์พอยต์

ฟีเจอร์แบบเดิม (/v1/webhook)ปลายทาง (/v1/developer/webhook-endpoints)
จำนวน URL1 ต่อองค์กรหลายรายการต่อองค์กร
ขอบเขตเหตุการณ์เฉพาะ telephony.* / web.*เหตุการณ์ทั้ง 10 ประเภท
ตัวกรองเหตุการณ์—แยกตามแต่ละปลายทาง
การลองใหม่ไม่มี ยกเว้น 1 ครั้งสำหรับการแลกเปลี่ยนการกำหนดค่าการโทร8 ครั้งภายใน 24 ชม.
เอนเวโลปtype + datatype + data + event_id
การหมุนเวียนซีเคร็ตแทนที่ซีเคร็ตเดียวซีเคร็ตแยกตามปลายทาง
ปิดใช้งานโดยไม่ลบPUT /v1/webhook พร้อม {"url": ""}status=disabled
การแสดงสถานะ—active / disabled / failing
การแลกเปลี่ยนการกำหนดค่าแบบบล็อกมี (telephony.incoming / web.incoming)ไม่มี — มีเฉพาะการแจ้งเตือน
เหมาะสำหรับการกำหนดค่าการโทรแบบไดนามิกการรับเหตุการณ์ในระบบใช้งานจริง

การเชื่อมต่อใหม่ควรรับอีเวนต์ผ่าน เว็บฮุกแบบอิงเอ็นด์พอยต์ เก็บ (หรือเพิ่ม) URL แบบเดิมไว้เฉพาะเมื่อคุณกำหนดค่าสายสนทนา แบบไดนามิกในเวลารับสาย หรือใช้การเรียกใช้เครื่องมือในโหมดเว็บฮุก — การแลกเปลี่ยน คำขอ/การตอบกลับเหล่านั้นทำงานบนเส้นทางเดิมเท่านั้น


ที่เกี่ยวข้อง