Skip to content

Integrasi Webhook

Webhook membolehkan sistem anda menerima pemberitahuan masa nyata apabila acara berlaku pada akaun Wink anda — tempahan baru, pembatalan, kemas kini pembayaran, dan banyak lagi. Panduan ini membimbing anda melalui penyediaan dan amalan terbaik.

Panduan ini untuk pembangun yang mengintegrasikan Wink dengan sistem luaran seperti sistem pengurusan hartanah (PMS), pengurus saluran, CRM, atau papan pemuka tersuai.

  1. Anda mendaftar URL webhook pada Wink.
  2. Apabila acara berlaku (contohnya, tempahan baru), Wink menghantar HTTP POST ke URL anda.
  3. Pelayan anda memproses muatan dan membalas dengan 200 OK.
  1. Log masuk ke akaun anda (Extranet, Studio, atau TripPay — semua menyokong webhook).
  2. Pergi ke Applications kemudian Webhooks. Lihat Webhooks.
  3. Klik Create webhook.
  4. Masukkan nama (contohnya, “PMS Booking Sync”).
  5. Masukkan URL webhook anda — titik akhir HTTPS pada pelayan anda.
  6. Pilih acara — Pilih acara tertentu untuk dilanggan, atau biarkan kosong untuk menerima semua acara.
  7. Togol Enabled ke hidup.
  8. Klik Save — respons menunjukkan rahsia tandatangan sekali sahaja; simpan sekarang.

Wink menerbitkan 70 jenis acara webhook hari ini merangkumi tempahan, hartanah, akaun (entiti pengurusan) dan inventori (jenis bilik, pelan kadar, kadar induk, tambahan, kemudahan, saluran jualan, promosi). Yang biasa:

KategoriContoh
Tempahanbooking.create, booking.cancelled, booking.refund.partial, booking.refund.full, booking.review.created
Hartanahproperty.created, property.status.updated, property.policy.updated
Inventoriroom_type.updated, rate_plan.created, master_rate.updated, special_rate.created, sales_channel.created
Akaunmanaging_entity.created, managing_entity.status.updated, managing_entity.manager.added

Senarai lengkap yang dijana — dengan penerangan, siapa penerima, dan pautan ke halaman rujukan setiap acara — adalah Katalog Acara Webhook. Halaman rujukan untuk setiap acara (badan JSON, pengepala, polisi cuba semula) boleh didapati di Webhooks API.

Lihat setiap jenis acara

Setiap penghantaran adalah HTTP POST ke URL webhook anda dengan Content-Type: application/json dan sampul surat ini:

{
"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 — pengecam acara; sama untuk setiap titik akhir akaun anda yang menerima acara ini dan untuk setiap cubaan semula. Gunakan sebagai kunci idempotensi anda.
  • type — kunci jenis acara (juga dihantar sebagai pengepala Wink-Event-Type). Cabang pada type dan schemaVersion untuk mengurai object.
  • object — ringkasan terpilih sumber acara tersebut (pengecam, status, medan yang anda bertindak ke atas) serta links.self, URL REST kanonik sisi pembekal bagi sumber penuh. Dapatkan dengan kelayakan API anda sendiri apabila anda memerlukan lebih daripada ringkasan; jika anda menerima acara sebagai penjual semula atau ejen pelancongan, gunakan titik akhir sumber yang sepadan pada permukaan API anda sendiri untuk pengecam yang sama.

Setiap skema muatan didokumentasikan mengikut acara dalam rujukan Webhooks API.

PengepalaMaksud
Wink-VersionVersi kontrak wayar, 2.0.
Wink-Event-IdSama seperti id dalam badan — kunci idempotensi anda.
Wink-Delivery-IdUnik bagi setiap titik akhir bagi setiap acara; berubah hanya jika anda menghantar semula.
Wink-Event-TypeSama seperti type dalam badan.
Wink-Delivery-AttemptNombor cubaan bermula dari 1 untuk penghantaran ini.
Wink-SignatureTandatangan HMAC — lihat di bawah.

Setiap webhook mempunyai rahsia tandatangan (whsec_…) yang Wink tunjukkan sekali sahaja, apabila anda mencipta webhook atau menggilirkan rahsia. Simpan seperti kata laluan. Setiap penghantaran membawa

Wink-Signature: t=1755250200,v1=5d41402abc4b2a76b9719d911017c592…

di mana t adalah cap masa Unix (saat) dan v1 adalah HMAC-SHA256 heks huruf kecil bagi rentetan t + "." + rawBody, dikunci dengan rahsia anda, dan rawBody adalah bait badan permintaan tepat seperti diterima — jangan serikan semula JSON sebelum mengesahkan. Untuk 24 jam selepas penggiliran rahsia, pengepala membawa nilai v1= kedua yang ditandatangani dengan rahsia sebelumnya; terima penghantaran jika mana-mana v1 sepadan.

Sahkan dalam empat langkah: uraikan t dan setiap v1; kira semula HMAC ke atas t.rawBody dengan rahsia anda; bandingkan dengan perbandingan masa tetap; tolak jika |now − t| melebihi toleransi anda (5 minit disyorkan).

// Node.js (gaya Express; pastikan anda ada badan RAW, bukan objek yang diurai)
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')));
}
// Java
static 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)));
}

Gilirkan rahsia dari portal atau dengan POST /api/managing-entity/{id}/webhook/{webhookId}/rotate-secret; respons menunjukkan rahsia baru sekali sahaja, dan yang lama terus disahkan selama 24 jam semasa anda melaksanakannya.

  • Balas dengan mana-mana 2xx dalam 10 saat untuk mengakui. Lakukan kerja berat secara tak segerak.
  • 5xx, tamat masa, 408 atau 429 dicuba semula dengan penangguhan: selepas 1 minit, 5 minit, 30 minit, 2 jam, 6 jam, 12 jam, kemudian harian — 10 cubaan dalam kira-kira 3 hari — selepas itu penghantaran ditandakan mati.
  • Mana-mana 4xx lain dianggap sebagai “anda menolak penghantaran ini” dan tidak dicuba semula.
  • Setiap acara, penghantaran dan cubaan (status, petikan respons) boleh dilihat di bawah Applications > Webhooks dan melalui API (…/webhook/event/grid, …/webhook/delivery/grid). Anda boleh menghantar semula mana-mana penghantaran (POST …/webhook/delivery/{deliveryId}/redeliver, yang memulakan siri cubaan semula baru), menghantar semula semua penghantaran mati webhook sekaligus (POST …/webhook/{webhookId}/redeliver-dead), atau membatalkannya.
  • Penghantaran disimpan selama 30 hari.

Hantar sendiri acara sintetik webhook.test dari portal atau dengan POST /api/managing-entity/{id}/webhook/{webhookId}/test. Ia ditandatangani dan dihantar sama seperti acara sebenar, jadi anda boleh mengesahkan titik akhir anda, pemeriksaan tandatangan dan pengendalian idempotensi sebelum melanggan acara langsung.

  • Gunakan HTTPS — Wink hanya menghantar muatan ke titik akhir HTTPS.
  • Balas dengan cepat — Kembalikan 200 OK sebaik sahaja anda menerima muatan. Lakukan pemprosesan berat secara tak segerak.
  • Idempotensi — Pengendali anda harus idempotent; hapus pendua berdasarkan Wink-Event-Id. Wink cuba semula apabila tidak menerima respons 2xx.
  • Sahkan sumber — Sahkan pengepala Wink-Signature (lihat Mengesahkan tandatangan) sebelum memproses; tolak apa-apa yang gagal.
  • Log — Log setiap muatan webhook yang anda terima. Ini memudahkan penyahpepijatan isu integrasi.

Anda boleh nyahaktifkan webhook tanpa memadamnya. Ini menjeda penghantaran supaya anda boleh menyelesaikan masalah tanpa kehilangan konfigurasi anda. Apabila anda bersedia, togol semula ke hidup.

Memadam webhook mengeluarkannya secara kekal. Sebarang integrasi yang bergantung pada webhook itu akan berhenti menerima pemberitahuan.