Perbandingan · Terbit

Webhook melawan halaman kembali sebagai pemicu pemenuhan pesanan: satu kiriman bertanda tangan yang datang tanpa peramban, satu kepulangan yang bisa tidak pernah terjadi dan bisa dipalsukan siapa saja, dan pembagian kerja yang membuat keduanya tetap dipakai

Jawabannya tidak berimbang, dan memang tidak seharusnya berimbang: pemenuhan pesanan dipicu webhook yang tanda tangannya sudah diverifikasi, tidak pernah oleh kepulangan pembeli ke halaman toko. Kepulangan itu navigasi, bukan bukti.

Yang layak dibaca terus bukan aturannya, melainkan sebabnya, karena kedua peristiwa ini terlihat setara dari layar penjual: keduanya terjadi sesudah pembayaran dan keduanya membawa id yang sama. Perbedaannya tidak terlihat sampai satu pembeli menutup aplikasi banknya, atau satu orang menyalin alamat halaman terima kasih dan mengirimnya ke grup.

Yang benar-benar dijamin masing-masing

Halaman kembali adalah return_url yang dikirim saat tagihan dibuat. Setelah pembayaran, halaman pembayaran menampilkan konfirmasi dan sebuah tombol kembali ke alamat itu, dengan ?id=payreq_...&status=succeeded ditambahkan di belakangnya. Yang dijamin peristiwa itu hanya satu hal: sebuah peramban membuka sebuah alamat.

Webhook adalah kiriman POST dari server ke server, yang datang ke setiap endpoint aktif segera setelah pembayaran terkonfirmasi. Setiap kiriman membawa tanda tangan bertimestamp pada header Kasera-Signature-V1 berbentuk t=<unix>,v1=<hex>, yaitu HMAC-SHA256 atas t, titik, dan raw body, dengan pengiriman yang timestampnya melenceng lebih dari lima menit pantas ditolak sebagai upaya pengulangan rekaman lama. Bentuk lengkapnya ada di dokumentasi webhook.

PertanyaanHalaman kembaliWebhook payment.paid
Siapa yang mengirimnyaPeramban pembeliServer Kasera Pay
Bisa dipalsukan tanpa membayarBisa, cukup dengan mengetik alamatnyaTidak, tanpa signing secret tanda tangannya tidak cocok
Bisa tidak pernah terjadi meski sudah dibayarBisa, dan seringTidak, pengiriman diulang sampai tujuh kali selama sekitar 33 jam
Bisa terjadi lebih dari sekaliBisa, lewat tombol kembali atau muat ulangBisa, karena pengiriman bersifat at-least-once, dan setiap event membawa id yang sama untuk di-dedupe
Bergantung pada pembeli tetap membuka perambanYa, sepenuhnyaTidak sama sekali

Tiga kegagalan yang hanya muncul kalau pemicunya kepulangan pembeli

Ketiganya bukan kemungkinan teoretis. Ketiganya bentuk kejadian sehari-hari pada cara bayar yang paling umum di Indonesia, yaitu QRIS dan nomor Virtual Account, justru karena kedua metode itu memindahkan pembeli ke aplikasi lain.

Pekerjaan yang tetap menjadi milik halaman kembali

Menghapus halaman kembali bukan jawabannya. Pembeli yang selesai membayar butuh layar yang menyatakan apa yang baru saja terjadi dan apa langkah berikutnya, dan tanpa itu tingkat komplain naik tanpa satu pun pembayaran gagal. Yang berubah hanya kewenangannya.

Bentuk yang benar: ambil id dari parameter, abaikan status yang ikut menempel, lalu tanyakan keadaannya dari server sendiri lewat GET /v1/transactions/:id, yang bentuknya ada di dokumentasi mengambil permintaan pembayaran. Panggilan itu memakai kunci API yang tidak pernah ada di peramban, sehingga jawabannya tidak bisa dikarang pembeli. Kalau jawabannya masih pending, yang ditampilkan adalah keadaan sedang diperiksa, bukan gagal: urutan kedatangan webhook dan kepulangan pembeli tidak dijamin, dan keduanya berlomba tanpa pemenang tetap.

Susunan yang memakai keduanya sesuai porsinya

  1. Pesanan dibuat di sistem penjual lebih dulu, lalu tagihannya dibuat dengan Idempotency-Key yang tersimpan bersama pesanan itu.
  2. Pembeli diarahkan ke halaman pembayaran, dengan return_url yang menunjuk ke halaman hasil di toko.
  3. Pemenuhan dijalankan di handler webhook, setelah tanda tangan diverifikasi terhadap raw body dan setelah event id diperiksa sebagai pertahanan terhadap kiriman ganda. Verifikasi selalu mendahului perubahan apa pun pada pesanan, karena memverifikasi sesudah mengubah pesanan tidak menghasilkan apa-apa.
  4. Halaman hasil membaca statusnya sendiri dari server dan hanya menampilkannya. Tidak ada satu pun perubahan data yang dipicu dari sana.

Susunan ini punya sifat yang jarang disebut: keempat langkahnya tetap benar kalau pembeli tidak pernah kembali, kalau pembeli kembali dua kali, dan kalau kiriman webhook sampai tiga kali. Tidak ada satu pun kasus itu yang perlu ditangani sebagai pengecualian.

Kalau endpoint webhook belum bisa dipasang

Webhook membutuhkan URL https yang bisa dijangkau publik, dan itu belum selalu ada saat integrasi sedang dikerjakan di komputer sendiri. Penggantinya bukan kepulangan pembeli, melainkan pembacaan status berkala dari sisi server: sumbernya sama, kewenangannya sama, dan yang hilang hanya kecepatannya. Perbandingan lengkap kedua jalur itu, termasuk anggaran pembacaan berkala yang masuk akal, ada di perbandingan webhook dan pembacaan status berkala, dan cara mengujinya di komputer sendiri ada di tulisan tentang webhook di localhost dan mode tes.

Yang sudah memutuskan ini untuk toko yang tidak menulis kodenya

Penjual yang memakai plugin resmi tidak perlu mengambil keputusan ini sama sekali: pesanan ditandai lunas atas pemberitahuan yang sudah terbukti asli, bukan atas kepulangan pembeli ke halaman toko, dan kiriman yang nominalnya tidak cocok dengan total pesanan membuat pesanan ditahan alih-alih diselesaikan. Bentuk pemasangannya ada di dokumentasi plugin WooCommerce. Keputusan ini milik integrasi yang ditulis sendiri, dan pemilihan antara keduanya dibahas di perbandingan memakai plugin dan menulis integrasi sendiri.

Ringkasnya

Pertanyaan yang sering muncul

Kenapa parameter status=succeeded pada return_url tidak bisa dipercaya?

Karena yang membawanya adalah peramban pembeli, dan alamat di peramban bisa diketik siapa saja. Halaman kembali dijangkau dengan menyalin alamatnya, tanpa pembayaran apa pun, dan parameter di belakang tanda tanya tidak ditandatangani. Yang pantas diambil dari sana hanya id permintaan pembayarannya, untuk kemudian ditanyakan sendiri dari server ke GET /v1/transactions/:id.

Pembeli sudah membayar tetapi tidak pernah kembali ke toko. Apakah pesanannya hilang?

Tidak, selama pemenuhannya dipicu webhook. Kiriman payment.paid berjalan dari server ke server dan tidak membutuhkan peramban pembeli sama sekali, jadi pembeli yang menutup aplikasi banknya setelah membayar tetap menghasilkan pesanan yang terpenuhi. Pada integrasi yang memicu dari kepulangan pembeli, kasus ini justru bentuk kegagalan yang paling sering dan paling sunyi.

Apakah halaman kembali masih diperlukan kalau webhook sudah dipasang?

Diperlukan, tetapi tugasnya berbeda. Halaman kembali adalah layar yang dibaca pembeli setelah membayar, dan tanpa itu pembeli ditinggal di halaman pembayaran tanpa tahu harus ke mana. Yang berubah hanyalah kewenangannya: halaman itu menampilkan hasil, bukan memutuskan hasil.

Apa yang ditampilkan halaman kembali kalau webhooknya belum sampai saat pembeli tiba?

Keadaan sedang diperiksa, bukan gagal. Urutan kedatangan keduanya tidak dijamin, dan pembacaan status dari server sendiri lewat GET /v1/transactions/:id menjawab pertanyaan itu tanpa menunggu webhook. Menyatakan pembayaran gagal karena webhook belum tiba adalah sumber komplain yang tidak perlu.

Kalau endpoint webhook belum ada, apakah kepulangan pembeli boleh dipakai sementara?

Tidak sebagai pemicu. Penggantinya yang benar adalah pembacaan status dari sisi server, karena yang dibutuhkan bukan kiriman melainkan sumber yang tidak dipegang pembeli. Webhook membutuhkan URL https publik, dan selama itu belum ada, server yang bertanya sendiri sudah cukup untuk mulai berjalan.

Mulai sekarang

Terima pembayaran pertama minggu ini.

Daftar gratis, buat payment link atau pakai API, dan lihat statusnya berubah otomatis. Tanpa biaya bulanan, biaya transaksi hanya untuk pembayaran yang berhasil.

Dapatkan di Google PlayDownload di App Store