Używanie danych aplikacji w sekwencji głosowej
Użyj voice.webhook, gdy Twoja aplikacja przechowuje dane potrzebne w połączeniu, na przykład status zamówienia, zespół lub potwierdzenie wizyty. Krok zwraca te dane na success, a późniejszy krok Branch wybiera na ich podstawie ścieżkę.
Zdefiniuj odpowiedź
Ustaw w config.output_schema schemat obiektu dla zwracanych danych. Krok ma dwa wyjścia: success przekazuje dane zgodne z tym schematem, a failure obsługuje problemy techniczne. Jeśli pominiesz konfigurację, krok zwraca pusty obiekt.
Dane wejściowe zawierają statyczny HTTPS url i opcjonalny obiekt data. Pole danych obsługuje obiekt literalny, $literal lub $expr dla całego obiektu. Dynamiczne adresy URL, własne nagłówki i dane uwierzytelniające nie są obsługiwane.
Weryfikuj żądania
Bird podpisuje każde żądanie, także kontynuacje, sekretem wywołań zwrotnych Twojego obszaru roboczego przy użyciu nagłówków Standard Webhooks: webhook-id, webhook-timestamp i webhook-signature. Podpis obejmuje identyfikator, znacznik czasu i dokładną treść żądania. Przez 24 godziny po rotacji sekretu webhook-signature zawiera jeden wpis v1, na każdy aktywny sekret, więc weryfikacja działa z każdym z nich. Połączenia mogą zacząć używać nowego sekretu dopiero po około minucie, dlatego akceptuj poprzedni sekret do końca okresu nakładania się. Twoja odpowiedź nie jest podpisywana: Bird sprawdza certyfikat TLS odbiornika, a połączenie HTTPS uwierzytelnia zwracane dane.
Zanim przetworzysz treść, zweryfikuj nagłówki na surowej treści żądania za pomocą funkcji weryfikującej z biblioteki Standard Webhooks. Funkcja webhooks.unwrap w SDK przetwarza zdarzenia platformy i nie służy do tych żądań. Najpierw wykonaj rotację sekretu w Webhooks → Direct callbacks, ponieważ początkowy sekret nigdy nie jest wyświetlany. Podpis dowodzi, że żądanie podpisał ktoś, kto zna sekret Twojego obszaru roboczego. Twoje odbiorniki wywołań zwrotnych SMS mają ten sam sekret i również mogą podpisywać żądania, dlatego przechowuj go tylko w odbiornikach, którym ufasz. Każdy, kto może edytować sekwencje obszaru roboczego, wybiera adres URL i data. Sprawdź, czy target_url to Twój własny adres URL, aby odrzucić żądanie, które Bird podpisał dla innego odbiornika, i autoryzuj operacje biznesowe w swoim odbiorniku. Autoryzacja klienta nigdy nie jest przekazywana.
Żądania webhooków sekwencji nie przedstawiają certyfikatu klienta, nawet gdy Twój obszar roboczy wymusza mTLS. Skonfiguruj odbiornik tak, aby akceptował połączenie bez certyfikatu klienta, i zamiast tego uwierzytelniaj podpisane żądanie.
Porównaj podpisany webhook-timestamp, czyli uniksowy znacznik czasu w sekundach, z zsynchronizowanym zegarem serwera. Odrzucaj żądania przesunięte o więcej niż pięć minut w przeszłość lub przyszłość. Przed wykonaniem skutków ubocznych usuwaj duplikaty na podstawie webhook-id. W miarę możliwości zapisuj identyfikator i wynik atomowo razem z operacją, a na powtórzone żądanie zwracaj zapisany wynik. Każda kontynuacja ma własny identyfikator. Jeśli różne żądania nie mogą powtórzyć tej samej operacji, użyj osobnego biznesowego klucza idempotencji.
Zwróć dane
Odbiorca zwraca odpowiedź o tej zamkniętej strukturze:
{
"schema_version": 1,
"type": "outcome",
"output": { "status": "confirmed", "message": "Your appointment is confirmed." }
}output musi być zgodne ze skonfigurowanym schematem. Odpowiedź zwraca dane, a nie port, identyfikator węzła ani nowe polecenia. Kontynuacja to {"schema_version":1,"type":"continue","url":"https://example.com/voice/next"} na kanonicznym źródle (origin) pierwotnego adresu URL.
Aby kierować połączenie na podstawie danych, połącz success z krokiem logic.branch z przypadkami takimi jak steps.decision.output.status == 'confirmed'. Zadeklaruj pole w schemacie jako ciąg znaków enum, aby odbiornik mógł zwracać tylko te wartości.
Żądanie zawiera identyfikatory przebiegu, sesji i połączenia, identyfikatory dopuszczonej sekwencji i węzła, zmaterializowane data oraz results. Dane biznesowe przekazuj w data. Bezpośredni prywatny wynik kroku Gather może pojawić się jednorazowo w results, a zakończone nagrania zawierają identyfikator, jeśli jest dostępny. Te obserwacje nie stają się automatycznie polami wyrażeń.
Odczytaj żądanie odbiornika
Przebieg testowy wersji roboczej wysyła żądanie w takim kształcie. Poniższe identyfikatory i znaczniki czasu są fikcyjne. Rzeczywiste żądanie używa dopuszczonego przebiegu i bieżącego wystąpienia węzła:
{
"schema_version": 1,
"method": "POST",
"target_url": "https://example.com/decision",
"run_id": "vsr_01k5yb7p000000000000000000",
"sequence": {
"id": "vsq_01k5yb7p000000000000000000",
"version_id": null,
"draft_revision": 1,
"entry_node_id": "start",
"mode": "test"
},
"session_id": "vcs_01k5yb7p000000000000000000",
"call": { "id": "vcl_01k5yb7p000000000000000000", "orig": null, "dest": null },
"node": { "id": "decision", "occurrence_id": "00000000-0000-4000-8000-000000000001" },
"data": { "appointment_id": "appointment_123" },
"results": []
}W przebiegu opublikowanym version_id identyfikuje wybraną wersję, a draft_revision ma wartość null. W połączeniu, które wykonało definicję wbudowaną, pola id, version_id i draft_revision mają wartość null. mode może mieć wartość test lub production. Strona inicjująca i docelowa używają dopuszczających null obiektów stron połączenia. Zanim zaufasz tym polom identyfikacyjnym, zweryfikuj podpis.
Obserwacja Gather w results zawiera type: "gather", node_id, UUID command_id, digits i reason. Obserwacja nagrania zawiera type: "recording", UUID command_id, state oraz recording_id, jeśli jest dostępny. Używaj prywatnych cyfr tylko w żądaniu, dla którego są przeznaczone. Nie stają się one zachowywanymi wynikami wyrażeń. Żądania kontynuacji zachowują to samo wystąpienie węzła, a już dostarczone obserwacje są usuwane z results.
Obsługa błędów
Próbka techniczna używa portu failure z {"code":"webhook_unavailable"} lub {"code":"webhook_invalid_response"}. Podłączony błąd przechodzi do ścieżki odzyskiwania, a niepodłączony kończy przebieg niepowodzeniem. Niepodłączony success kończy przebieg w zwykły sposób. Żądania webhooków na żywo mają limit trzech sekund i nie są automatycznie ponawiane. Podgląd nie wysyła żądania.
Limit trzech sekund obejmuje odczytanie sekretu podpisującego. Połącz failure ze ścieżką odzyskiwania, aby połączenie mogło trwać dalej, gdy odbiornik jest niedostępny lub zwraca nieprawidłową odpowiedź. Żądanie przerwane po przekroczeniu limitu czasu mogło już wywołać skutek uboczny w odbiorniku.
Traktuj data, identyfikatory połączenia i cyfry z Gather jako prywatne. Ogranicz dostęp do odbiornika i sekretu, nie zapisuj w logach treści żądań ani sekretów i przechowuj dane od dzwoniącego tylko tak długo, jak potrzebuje ich Twoja aplikacja. Nie umieszczaj prywatnych danych ani poświadczeń w adresach URL, ponieważ ślad połączenia zachowuje pełny URL wraz z zapytaniem. Skonfigurowany URL i dane oraz zwalidowany wynik są zachowywane w historii przebiegów. Tymczasowe cyfry z Gather są wyłączone z przechwytywanych danych wejściowych kroku. Zwracaj tylko dane potrzebne sekwencji.
Zwrócone dane odczytuj z steps.decision.output, a błędy techniczne z steps.decision.error.code. Jeśli obie ścieżki się łączą, przed użyciem opakowania sprawdź je warunkiem has(steps.decision.output) lub has(steps.decision.error). Odpowiedź HTTP 200 z odbiornika nie oznacza prawidłowego wyniku, dopóki jej treść nie przejdzie walidacji kontraktu.
Powiązane zasoby
Przejdź do dokumentacji, przewodników i przykładów dotyczących tego tematu.