Open in
Επισκόπηση Webhooks
Πώς το ThunderPhone παραδίδει συμβάντα σε πραγματικό χρόνο, πώς να επαληθεύετε υπογραφές και πώς συγκρίνονται τα παλαιού τύπου και τα βασισμένα σε endpoint μοντέλα παράδοσης.
Το ThunderPhone στέλνει αιτήματα HTTP POST στον διακομιστή σας όταν συμβαίνουν
ενέργειες κατά τη διάρκεια μιας κλήσης — ξεκινά μια εισερχόμενη κλήση, ολοκληρώνεται μια κλήση, ολοκληρώνεται
μια εκτέλεση αξιολόγησης, ενεργοποιείται μια ειδοποίηση και ούτω καθεξής. Υπάρχουν δύο μοντέλα
παράδοσης:
Πολλαπλά URL, μυστικά ανά τελικό σημείο, φίλτρα συμβάντων ανά τελικό σημείο
και αυτόματες επαναλήψεις.
Διαχείριση μέσω GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Ένα URL ανά οργανισμό. Μεταφέρει τα συμβάντα κύκλου ζωής κλήσης, συμπεριλαμβανομένων των
δεσμευτικών ανταλλαγών διαμόρφωσης. Διαχείριση στο GET/PUT /v1/webhook.
Όλοι οι τύποι συμβάντων που αναφέρονται στον κατάλογο συμβάντων
παραδίδονται μέσω τελικών σημείων webhook. Τα έξι συμβάντα κύκλου ζωής κλήσης
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) αποστέλλονται επίσης στο
webhook παλαιού τύπου με ένα URL — αν έχετε και URL παλαιού τύπου και αντίστοιχο
τελικό σημείο, λαμβάνετε το συμβάν και από τις δύο διαδρομές. Η δεσμευτική
συμπεριφορά (η ανταλλαγή διαμόρφωσης telephony.incoming / web.incoming
και η δρομολόγηση εργαλείων σε λειτουργία webhook)
υπάρχει αποκλειστικά στη διαδρομή παλαιού τύπου· κάθε παράδοση σε τελικό σημείο είναι
ειδοποίηση αποστολής χωρίς αναμονή.
Μορφή payload
Οι παραδόσεις σε τελικά σημεία είναι ένα αντικείμενο 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. Τα παραδείγματα με μορφοποίηση σε πολλές γραμμές σε αυτή την τεκμηρίωση προορίζονται μόνο για αναγνωσιμότητα.
Δείτε τον Κατάλογο συμβάντων για την πλήρη λίστα τύπων συμβάντων και πεδίων payload.
Επαλήθευση υπογραφής
Κάθε αίτημα φέρει δύο υπογραφές, και οι δύο HMAC-SHA256 με κλειδί το
secret του endpoint (ή το secret του webhook σε επίπεδο οργανισμού για παλαιές
παραδόσεις):
- Το
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>υπογράφει τη χρονική σήμανση, τη μέθοδο, τη διαδρομή και το ερώτημα, καθώς και το ακατέργαστο σώμα. Επαληθεύστε αυτήν και απορρίψτε αιτήματα των οποίων τοtαπέχει περισσότερο από 5 λεπτά από το ρολόι σας, ώστε ένα υποκλαπέν αίτημα να μην μπορεί να επαναληφθεί αργότερα. Οι επαναλήψεις υπογράφονται ξανά όταν αποστέλλονται. - Το
X-ThunderPhone-Signatureυπογράφει μόνο το ακατέργαστο σώμα. Εξακολουθεί να αποστέλλεται, χωρίς αλλαγές, ώστε οι υπάρχοντες επαληθευτές να συνεχίσουν να λειτουργούν.
Βήματα
- Διαβάστε την κεφαλίδα, τη μέθοδο, την ακατέργαστη διαδρομή και το ερώτημα, και το ακατέργαστο σώμα πριν από οποιαδήποτε ανάλυση.
- Υπολογίστε το δεκαεξαδικό HMAC-SHA256 του
<t>\n<METHOD>\n<path and query>\n<body>με το μυστικό σας. - Απορρίψτε το αίτημα αν το
tαπέχει περισσότερο από 300 δευτερόλεπτα ή αν το αποτέλεσμα δεν αντιστοιχεί στοv1σε σύγκριση σταθερού χρόνου.
Τα σώματα είναι η κανονική σειριοποίηση JSON (ταξινομημένα κλειδιά, συμπαγείς διαχωριστές) και υπογράφουμε ακριβώς τις οκτάδες που μεταδίδουμε. Ο οδηγός επαλήθευσης περιλαμβάνει την ακριβή υπογεγραμμένη συμβολοσειρά, ένα αναλυτικό παράδειγμα, κώδικα χωρίς το SDK και την παλαιότερη κεφαλίδα.
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);
},
);Σημασιολογία παράδοσης
Αυτές οι σημασιολογικές αρχές ισχύουν για παραδόσεις σε τελικά σημεία. Η παλαιού τύπου διαδικτυακή ειδοποίηση μίας διεύθυνσης URL
είναι μία σύγχρονη προσπάθεια χωρίς επαναλήψεις, εκτός από την
ανταλλαγή ρυθμίσεων για τηλεφωνικές κλήσεις
telephony.incoming,
η οποία επαναλαμβάνεται μία φορά.
Επαναλήψεις
Κάθε συμβάν επιχειρείται αμέσως μία φορά. Κάθε απόκριση 2xx
επιβεβαιώνει την παράδοση. Σε κάθε άλλη έκβαση (όχι 2xx,
σφάλμα σύνδεσης, χρονικό όριο), επαναλαμβάνουμε την προσπάθεια 1 λεπτό, 5 λεπτά, 30 λεπτά, 2 ώρες, 6 ώρες,
12 ώρες και 24 ώρες μετά την πρώτη προσπάθεια — 8 προσπάθειες σε διάστημα
24 ωρών. Αν αποτύχει κάθε προσπάθεια, η παράδοση σταματά και το τελικό σημείο
επισημαίνεται με status="failing" στα
τελικά σημεία διαδικτυακών ειδοποιήσεων· στέλνουμε μήνυμα ηλεκτρονικού ταχυδρομείου στους
κατόχους και τους διαχειριστές του οργανισμού σας και το εμφανίζουμε στον πίνακα ελέγχου. Επιστρέψτε 2xx μόλις
το ωφέλιμο φορτίο γίνει δεκτό με ανθεκτικό τρόπο· επεξεργαστείτε το ασύγχρονα.
Οι δοκιμαστικές αποστολές από το API δοκιμών του τελικού σημείου λαμβάνουν μία επανάληψη περίπου ένα λεπτό μετά
την πρώτη προσπάθεια και δεν αλλάζουν ποτέ την κατάσταση του τελικού σημείου.
Σειρά
Η σειρά παράδοσης είναι κατά το δυνατόν εγγυημένη. Στην πράξη παραδίδουμε με τη
σειρά που εκπέμπονται τα συμβάντα, αλλά οι επαναλήψεις μπορεί να αλλάξουν τη σειρά σε περίπτωση αποτυχίας.
Πάντα να εξαλείφετε διπλότυπα και να συμφωνείτε δεδομένα βάσει call_id / αναγνωριστικού αντικειμένου.
Διπλότυπα
Η παράδοση είναι τουλάχιστον μία φορά: μια επανάληψη μετά από απόκριση που δεν
λάβαμε ποτέ μπορεί να δημιουργήσει διπλότυπο συμβάν. Κάθε επανάληψη φέρει το ίδιο
event_id, επομένως αποθηκεύστε τα αναγνωριστικά που επεξεργαστήκατε και παραλείψτε τις επαναλήψεις. Το event_id
κοινοποιείται επίσης μεταξύ τελικών σημείων — δύο τελικά σημεία που έχουν εγγραφεί στο
ίδιο συμβάν λαμβάνουν το ίδιο event_id.
Χρονικά όρια
Οι παραδόσεις σε τελικά σημεία έχουν χρονικό όριο 30 δευτερολέπτων ανά προσπάθεια. Στην
παλαιού τύπου διαδρομή, τα αιτήματα αποκλεισμού που καθορίζουν τη συμπεριφορά ζωντανών κλήσεων — η
ανταλλαγή ρυθμίσεων
telephony.incoming / web.incoming
— περιορίζονται σε 10 δευτερόλεπτα για την πρώτη προσπάθεια μιας τηλεφωνικής κλήσης
και σε 13 δευτερόλεπτα για ολόκληρη την ανταλλαγή, συμπεριλαμβανομένης της μίας
επανάληψής της, και σε 10 δευτερόλεπτα για μια συνεδρία γραφικού στοιχείου. Μια αργή απόκριση καθυστερεί
την απάντηση της κλήσης, επομένως επιδιώξτε να απαντάτε εντός λίγων δευτερολέπτων. Η αποστολή εργαλείων σε λειτουργία διαδικτυακής ειδοποίησης επιτρέπει 20 δευτερόλεπτα
από προεπιλογή και οι δηλώσεις εργαλείων μπορούν να ορίσουν ένα timeout ανώτατου επιπέδου.
IP προέλευσης
Τα εξερχόμενα webhook προέρχονται από το εύρος IP cloud του ThunderPhone. Αν το τείχος προστασίας σας απαιτεί λίστα επιτρεπόμενων διευθύνσεων, επικοινωνήστε με την υποστήριξη και θα μοιραστούμε τα τρέχοντα εύρη.
Επιλογή μεταξύ webhook παλαιού τύπου και webhook βάσει τελικών σημείων
| Χαρακτηριστικό | Παλαιού τύπου (/v1/webhook) | Τελικά σημεία (/v1/developer/webhook-endpoints) |
|---|---|---|
| Αριθμός URL | 1 ανά οργανισμό | Πολλά ανά οργανισμό |
| Κάλυψη συμβάντων | Μόνο telephony.* / web.* | Και οι 10 τύποι συμβάντων |
| Φίλτρο συμβάντων | — | Ανά τελικό σημείο |
| Επαναλήψεις | Καμία, εκτός από μία για την ανταλλαγή ρυθμίσεων της τηλεφωνικής κλήσης | 8 προσπάθειες σε διάστημα 24 ωρών |
| Φάκελος | type + data | type + data + event_id |
| Εναλλαγή μυστικού | Αντικαθιστά ένα μόνο μυστικό | Μυστικό ανά τελικό σημείο |
| Απενεργοποίηση χωρίς διαγραφή | PUT /v1/webhook with {"url": ""} | status=disabled |
| Ορατότητα κατάστασης | — | active / disabled / failing |
| Ανταλλαγή ρυθμίσεων με αποκλεισμό | Ναι (telephony.incoming / web.incoming) | Ποτέ — μόνο ειδοποιήσεις |
| Κατάλληλο για | Δυναμική ρύθμιση κλήσεων | Κατανάλωση συμβάντων στην παραγωγή |
Οι νέες ενσωματώσεις θα πρέπει να καταναλώνουν συμβάντα μέσω webhook βάσει τελικών σημείων. Διατηρήστε (ή προσθέστε) μια διεύθυνση URL παλαιού τύπου μόνο αν ρυθμίζετε κλήσεις δυναμικά τη στιγμή της απάντησης ή χρησιμοποιείτε εκτέλεση εργαλείων σε λειτουργία webhook — αυτές οι ανταλλαγές αιτήματος/απόκρισης εκτελούνται μόνο στη διαδρομή παλαιού τύπου.
Σχετικά
Όλοι οι τύποι συμβάντων και τα ωφέλιμα φορτία τους.
Διαχειριστείτε πολλαπλά τελικά σημεία, φίλτρα συμβάντων και μυστικά.
Το αποκλειστικό αίτημα στο οποίο πρέπει να απαντήσει ο διακομιστής σας για τη διαμόρφωση κλήσεων.
Ωφέλιμο φορτίο μετά την κλήση με απομαγνητοφώνηση, εγγραφή και μετρήσεις.