Integracja Webhooków
Webhooki pozwalają Twoim systemom otrzymywać powiadomienia w czasie rzeczywistym, gdy na Twoim koncie Wink zachodzą zdarzenia — nowe rezerwacje, anulacje, aktualizacje płatności i inne. Ten przewodnik przeprowadzi Cię przez konfigurację i najlepsze praktyki.
Odbiorcy
Dział zatytułowany „Odbiorcy”Ten przewodnik jest przeznaczony dla programistów integrujących Wink z systemami zewnętrznymi, takimi jak systemy zarządzania nieruchomościami (PMS), channel managerowie, CRM-y lub niestandardowe pulpity.
Jak działają webhooki
Dział zatytułowany „Jak działają webhooki”- Rejestrujesz URL webhooka w Wink.
- Gdy wystąpi zdarzenie (np. nowa rezerwacja), Wink wysyła HTTP POST na Twój URL.
- Twój serwer przetwarza payload i odpowiada
200 OK.
Konfiguracja webhooka
Dział zatytułowany „Konfiguracja webhooka”- Zaloguj się na swoje konto (Extranet, Studio lub TripPay — wszystkie obsługują webhooki).
- Przejdź do
Applications, a następnieWebhooks. Zobacz Webhooki. - Kliknij
Create webhook. - Wprowadź nazwę (np. “Synchronizacja rezerwacji PMS”).
- Wprowadź swój URL webhooka — punkt końcowy HTTPS na Twoim serwerze.
- Wybierz zdarzenia — Wybierz konkretne zdarzenia do subskrypcji lub pozostaw puste, aby otrzymywać wszystkie zdarzenia.
- Przełącz Enabled na włączone.
- Kliknij
Save— odpowiedź pokaże Twój sekret podpisu tylko raz; zapisz go teraz.
Typy zdarzeń
Dział zatytułowany „Typy zdarzeń”Wink publikuje obecnie 70 typów zdarzeń webhooków dotyczących rezerwacji, nieruchomości, kont (jednostek zarządzających) oraz inwentarza (typy pokoi, plany taryfowe, stawki główne, dodatki, udogodnienia, kanały sprzedaży, promocje). Najczęstsze:
| Kategoria | Przykłady |
|---|---|
| Rezerwacja | booking.create, booking.cancelled, booking.refund.partial, booking.refund.full, booking.review.created |
| Nieruchomość | property.created, property.status.updated, property.policy.updated |
| Inwentarz | room_type.updated, rate_plan.created, master_rate.updated, special_rate.created, sales_channel.created |
| Konto | managing_entity.created, managing_entity.status.updated, managing_entity.manager.added |
Pełna, generowana lista — z opisem, odbiorcą i linkiem do strony referencyjnej każdego zdarzenia — to Katalog Zdarzeń Webhook. Strona referencyjna dla każdego zdarzenia (ciało JSON, nagłówki, polityka ponawiania) znajduje się w Webhooks API.
Zobacz wszystkie typy zdarzeń
Co otrzymujesz
Dział zatytułowany „Co otrzymujesz”Każda dostawa to HTTP POST na Twój URL webhooka z Content-Type: application/json i następującą kopertą:
{ "id": "0198a4f2-6b0e-7c1d-9a3e-2f4b8c6d1e0a", "type": "booking.create", "occurredAt": "2026-08-15T09:30:00Z", "ownerIdentifier": "3c6b1a5d-8e2f-4a0b-9c7d-6e4f0a8b2c51", "recipientRole": "SUPPLIER", "schemaVersion": 2, "object": { "...": "event-specific payload, e.g. BookingWebhookPayload" }}id— identyfikator zdarzenia; taki sam dla każdego punktu końcowego Twojego konta, który otrzymuje to zdarzenie, oraz dla każdej próby ponownej wysyłki. Używaj go jako klucza idempotencji.type— klucz typu zdarzenia (wysyłany również jako nagłówekWink-Event-Type). Rozgałęziając potypeischemaVersionparsujobject.object— wyselekcjonowane podsumowanie zasobu, którego dotyczy zdarzenie (identyfikatory, status, pola, na których działasz) orazlinks.self, kanoniczny URL REST po stronie dostawcy pełnego zasobu. Pobierz go za pomocą własnych poświadczeń API, gdy potrzebujesz więcej niż podsumowanie; jeśli otrzymujesz zdarzenie jako reseller lub agent turystyczny, użyj odpowiedniego punktu końcowego swojego API dla tego samego identyfikatora.
Każdy schemat payload jest dokumentowany dla zdarzenia w referencji Webhooks API.
Nagłówki
Dział zatytułowany „Nagłówki”| Nagłówek | Znaczenie |
|---|---|
Wink-Version | Wersja kontraktu sieciowego, 2.0. |
Wink-Event-Id | To samo co id w ciele — Twój klucz idempotencji. |
Wink-Delivery-Id | Unikalny dla punktu końcowego i zdarzenia; zmienia się tylko przy ponownej wysyłce. |
Wink-Event-Type | To samo co type w ciele. |
Wink-Delivery-Attempt | Numer próby dostawy, zaczynając od 1. |
Wink-Signature | Podpis HMAC — patrz poniżej. |
Weryfikacja podpisów
Dział zatytułowany „Weryfikacja podpisów”Każdy webhook ma sekret podpisu (whsec_…), który Wink pokazuje raz, podczas tworzenia webhooka lub rotacji sekretu. Przechowuj go jak hasło. Każda dostawa zawiera
Wink-Signature: t=1755250200,v1=5d41402abc4b2a76b9719d911017c592…gdzie t to znacznik czasu Unix (sekundy), a v1 to małe litery hex HMAC-SHA256 ciągu
t + "." + rawBody, kluczowanego Twoim sekretem, a rawBody to dokładne bajty ciała żądania, jakie otrzymałeś — nie serializuj ponownie JSON przed weryfikacją. Przez 24 godziny po rotacji sekretu nagłówek zawiera drugi podpis v1= podpisany poprzednim sekretem; zaakceptuj dostawę, jeśli którykolwiek v1 pasuje.
Weryfikuj w czterech krokach: sparsuj t i każdy v1; przelicz HMAC dla t.rawBody z Twoim sekretem; porównaj w czasie stałym; odrzuć, jeśli |teraz − t| przekracza tolerancję (zalecane 5 minut).
// Node.js (Express-style; upewnij się, że masz surowe ciało, a nie sparsowany obiekt)import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWinkSignature(header, rawBody, secret, toleranceSeconds = 300) { const parts = Object.fromEntries(header.split(',').map((p) => p.split('=').map((s) => s.trim()))); const t = Number(parts.t); if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false; const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex'); return header .split(',') .filter((p) => p.trim().startsWith('v1=')) .map((p) => p.trim().slice(3)) .some((v1) => v1.length === expected.length && timingSafeEqual(Buffer.from(v1, 'utf8'), Buffer.from(expected, 'utf8')));}// Javastatic boolean verify(String header, String rawBody, String secret, long nowSeconds, long toleranceSeconds) throws Exception { long t = Long.MIN_VALUE; List<String> signatures = new ArrayList<>(); for (String part : header.split(",")) { String[] kv = part.trim().split("=", 2); if (kv[0].equals("t")) t = Long.parseLong(kv[1]); else if (kv[0].equals("v1")) signatures.add(kv[1]); } if (t == Long.MIN_VALUE || Math.abs(nowSeconds - t) > toleranceSeconds) return false; Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); byte[] expected = HexFormat.of().formatHex(mac.doFinal((t + "." + rawBody).getBytes(StandardCharsets.UTF_8))).getBytes(StandardCharsets.US_ASCII); return signatures.stream().anyMatch(v1 -> MessageDigest.isEqual(expected, v1.toLowerCase().getBytes(StandardCharsets.US_ASCII)));}Rotuj sekret z poziomu portalu lub za pomocą POST /api/managing-entity/{id}/webhook/{webhookId}/rotate-secret;
odpowiedź pokaże nowy sekret raz, a stary będzie ważny przez 24 godziny, abyś mógł go wdrożyć.
Ponawianie i ponowna dostawa
Dział zatytułowany „Ponawianie i ponowna dostawa”- Odpowiedz dowolnym
2xxw ciągu 10 sekund, aby potwierdzić odbiór. Ciężkie operacje wykonuj asynchronicznie. 5xx, timeout,408lub429są ponawiane z opóźnieniem: po 1 minucie, 5 minutach, 30 minutach, 2 godzinach, 6 godzinach, 12 godzinach, a potem codziennie — 10 prób przez około 3 dni — po czym dostawa jest oznaczana jako martwa.- Każdy inny
4xxtraktowany jest jako “odrzuciłeś tę dostawę” i nie jest ponawiany. - Każde zdarzenie, dostawa i próba (status, fragment odpowiedzi) jest widoczna w Applications > Webhooks
oraz przez API (
…/webhook/event/grid,…/webhook/delivery/grid). Możesz ponownie dostarczyć dowolną dostawę (POST …/webhook/delivery/{deliveryId}/redeliver, co rozpoczyna nową serię prób), ponownie dostarczyć wszystkie martwe dostawy webhooka naraz (POST …/webhook/{webhookId}/redeliver-dead), lub anulować jedną. - Dostawy są przechowywane przez 30 dni.
Testowe zdarzenia
Dział zatytułowany „Testowe zdarzenia”Wyślij sobie syntetyczne zdarzenie webhook.test z portalu lub za pomocą
POST /api/managing-entity/{id}/webhook/{webhookId}/test. Jest podpisane i dostarczane dokładnie jak prawdziwe
zdarzenie, więc możesz zweryfikować swój punkt końcowy, sprawdzenie podpisu i obsługę idempotencji przed subskrypcją
na zdarzenia na żywo.
Najlepsze praktyki
Dział zatytułowany „Najlepsze praktyki”- Używaj HTTPS — Wink wysyła payloady tylko do punktów końcowych HTTPS.
- Odpowiadaj szybko — Zwróć
200 OKzaraz po otrzymaniu payloadu. Ciężkie przetwarzanie wykonuj asynchronicznie. - Idempotencja — Twój handler powinien być idempotentny; deduplikuj po
Wink-Event-Id. Wink ponawia próby, gdy nie otrzyma2xx. - Weryfikuj źródło — Sprawdzaj nagłówek
Wink-Signature(patrz Weryfikacja podpisów) przed przetwarzaniem; odrzucaj wszystko, co nie przejdzie. - Logowanie — Loguj każdy otrzymany payload webhooka. Ułatwia to debugowanie problemów z integracją.
Wstrzymywanie i usuwanie
Dział zatytułowany „Wstrzymywanie i usuwanie”Możesz wyłączyć webhook bez usuwania go. To wstrzymuje dostarczanie, abyś mógł rozwiązać problemy bez utraty konfiguracji. Gdy będziesz gotowy, włącz go ponownie.
Usunięcie webhooka usuwa go na stałe. Każda integracja korzystająca z tego webhooka przestanie otrzymywać powiadomienia.
Dalsza lektura
Dział zatytułowany „Dalsza lektura”- Katalog Zdarzeń Webhook — Wszystkie typy zdarzeń, generowane z katalogu platformy.
- Referencja Webhooks API — Schematy payloadów, nagłówki i punkty końcowe zarządzania subskrypcjami/dostawami.
- Webhooki — Pełna referencja zarządzania webhookami.
- Applications — Zarządzaj swoimi poświadczeniami API.
- Developers > APIs — Pełna dokumentacja API.
