Ketika webhook tidak pernah sampai

Telusuri secara berurutan - log pengiriman, nama event, firewall, signature. Tab Deliveries memberi tahu apakah Didit sudah mengirimnya, yang langsung membagi masalah menjadi dua.

Short answer

Mulai dari tab Deliveries pada destinasinya. Jika Didit tidak pernah mencoba mengirimkannya, itu masalah subscription atau destinasi. Jika sudah dicoba dan gagal, kode responsnya memberi tahu penyebabnya: 404 berarti route Anda tidak terjangkau di URL itu, ketidakcocokan signature berarti Anda meng-hash byte yang salah.

#Langkah 1: apakah Didit sudah mencoba mengirimkannya?

Buka destinasi di API & Webhooks dan lihat tab Deliveries. Setiap percobaan dicatat satu per satu, lengkap dengan responsnya.

The webhooks page in the Didit console showing delivery status per destination
  1. Last sent memberi tahu apakah Didit sudah mencoba mengirim sama sekali.
  2. View stats menampilkan jumlah percobaan dan kegagalan untuk destinasi tersebut.
  3. Pengiriman uji coba memisahkan endpoint Anda dari event itu sendiri.
  4. Destinasi yang terus gagal bisa dinonaktifkan sementara Anda memperbaikinya.
Everything needed to tell a missing event from a failing endpoint is on this page.

Satu pemeriksaan itu saja langsung membagi masalah menjadi dua:

  • Tidak ada percobaan yang tercatat -> event tersebut tidak pernah dibuat untuk destinasi itu. Lanjut ke langkah 2.
  • Percobaan tercatat, gagal -> Didit sudah mengirimnya dan sisi Anda menolak atau tidak menerimanya. Lanjut ke langkah 3.
  • Percobaan tercatat, 2xx -> berhasil dikirim. Masalahnya ada di dalam handler Anda, bukan pada pengirimannya.

#Langkah 2: tidak ada percobaan yang tercatat

Berurutan dari yang paling mungkin:

  1. Event tersebut tidak di-subscribe. Tidak ada wildcard - setiap keluarga event harus didaftarkan secara eksplisit. Dan nama yang tidak ada (session.status.updated, kyc.completed) secara diam-diam tidak menerima apa pun. Periksa dengan daftar event.
  2. Aplikasi yang salah. Destinasi terikat pada sebuah aplikasi. Jika sesi Anda berjalan di bawah aplikasi yang berbeda dari destinasinya, tidak akan ada event yang pernah sampai ke sana. Ini penyebab paling umum ketika semuanya terlihat sudah dikonfigurasi dengan benar.
  3. Tidak ada yang benar-benar berubah. Webhook terpicu saat ada perubahan. Sesi yang belum bergerak, atau re-screening pemantauan AML yang tidak menemukan apa pun di atas ambang batas, secara wajar tidak menghasilkan event.
  4. Status yang Anda tunggu belum terjadi. Sesi yang berstatus In Progress belum selesai. Lihat ketika sesi tidak pernah selesai.

#Langkah 3: pengiriman sudah dicoba dan gagal

404 berarti permintaan sampai ke sesuatu yang tidak memiliki route Anda. Periksa:

  • Path yang persis, termasuk garis miring di akhir. Framework yang meredirect /hook ke /hook/ bisa mengubah endpoint yang tadinya bekerja menjadi 404 atau kehilangan body-nya.
  • Apakah URL-nya publik. Host lokal atau staging yang tidak terjangkau dari internet akan gagal dengan cara ini.
  • Apakah ada proxy, load balancer, atau router berbasis path di depan aplikasi Anda yang mengarahkan path tersebut ke tempat lain.

5xx berarti handler Anda melempar error. Catat body mentahnya sebelum di-parse supaya Anda bisa melihat apa yang sebenarnya diterima.

Timeout berarti Anda tidak merespons cukup cepat. Kembalikan 2xx terlebih dahulu, lalu proses setelahnya.

Tidak ada respons sama sekali / connection refused berarti edge Anda memblokirnya. Didit mengirim dari IP statis 18.203.201.92 dengan user agent DiditWebhook/2.0. Jika Anda berada di belakang Cloudflare atau WAF dengan kebijakan default-deny, izinkan IP tersebut untuk hostname penerima.

#Kasus klasik: pengiriman otomatis 404 tapi Resend berhasil

Kasus ini cukup sering muncul sampai layak diberi nama. Pengiriman otomatis gagal dengan 404, lalu mengklik Resend pada event yang sama justru berhasil.

Kombinasi itu berarti payload dan endpoint Anda sama-sama baik-baik saja - jadi perbedaannya ada di waktu atau path, bukan isi. Periksa:

  • Deploy atau restart pada momen pengiriman awal. Resend berhasil belakangan karena aplikasinya sudah aktif kembali.
  • Cold start yang melampaui batas timeout platform Anda - umum terjadi pada serverless dengan invocation pertama yang lambat.
  • Path-based routing yang berubah di antara dua percobaan, atau aturan yang hanya cocok untuk sebagian permintaan.
  • Rate limiting atau proteksi bot di edge Anda yang meloloskan resend manual karena datang sendirian, bukan dalam ledakan trafik.

Tab Deliveries menyimpan kedua percobaan beserta stempel waktunya - bandingkan dengan log deploy dan error Anda sendiri pada menit itu.

#Verifikasi signature gagal

Hampir selalu salah satu dari tiga hal berikut:

  1. Anda meng-hash JSON yang sudah di-serialize ulang. Lakukan HMAC pada byte body permintaan mentah persis seperti yang diterima. Melakukan parsing lalu menyusunnya kembali menjadi string mengubah spasi dan urutan key, sehingga signature-nya tidak akan cocok. Sebagian besar framework butuh konfigurasi eksplisit agar bisa memberi Anda body mentah.
  2. Secret yang salah. Signing secret bersifat per destinasi, dan itu bukan API key Anda. Dua destinasi punya dua secret yang berbeda.
  3. Asumsi encoding yang salah. Jika Anda tidak yakin apakah secret-nya digunakan sebagai string literal atau di-decode terlebih dahulu, jangan menebak - ikuti referensi verifikasi signature dengan persis, dan catat body mentahnya selama debugging supaya Anda bisa membandingkannya.
Important

Jangan pernah "memperbaiki" ketidakcocokan signature dengan melewati proses verifikasinya. Endpoint webhook yang tidak diverifikasi akan menerima persetujuan palsu dari siapa pun yang menemukan URL-nya, yang mengubah jalan pintas debugging menjadi celah pengambilalihan akun.

#Dua kali percobaan ulang bukan sebuah antrean

Pada 5xx, 404, timeout, atau kegagalan koneksi, Didit mencoba ulang dua kali - kira-kira 1 menit kemudian lalu 4 menit setelah itu - lalu pengirimannya dihentikan. Jika endpoint Anda mati lebih lama dari itu, event-event tersebut hilang untuk selamanya.

Bangun jalur rekonsiliasi: saat startup, poll endpoint keputusan untuk setiap sesi yang belum Anda miliki status terminalnya. Perlakukan webhook sebagai jalur cepat dan polling sebagai cadangannya.

#Menguji tanpa menjalankan verifikasi sungguhan

Try Webhook pada halaman destinasi mengirimkan event yang terbentuk lengkap dari jenis apa pun yang Anda pilih - approved, declined, in review, KYB, entity, transaction. Gunakan untuk membuktikan endpoint, pemeriksaan signature, dan handler Anda bekerja sebelum sebuah sesi sungguhan bergantung padanya.

Sandbox adalah bagian lain dari ini: sesi sandbox mengirimkan webhook sungguhan dengan "environment": "sandbox", sehingga Anda bisa menguji seluruh jalurnya secara end-to-end tanpa biaya. Lihat menguji di sandbox.