BorderPay← Blog

Blog

Idempotency di API Pembayaran: Kenapa Penting dan Cara Menerapkannya

Oleh Admin7 mnt baca
Idempotency di API Pembayaran: Kenapa Penting dan Cara Menerapkannya
Foto: Godfrey Atima / Pexels

Bayangkan pelanggan menekan tombol "Bayar", koneksi internetnya tersendat, lalu ia menekan tombol itu sekali lagi. Tanpa perlindungan yang tepat, sistem bisa membuat dua tagihan atau memproses satu pembayaran dua kali. Di sinilah idempotency pembayaran menjadi krusial: ia memastikan bahwa permintaan yang sama, meski dikirim berkali-kali, hanya menghasilkan satu efek. Bagi merchant dan developer yang membangun alur pembayaran, memahami konsep ini bukan pilihan tambahan, melainkan fondasi agar transaksi tidak berujung double-charge, saldo ganda, atau notifikasi yang diproses berulang.

Artikel ini mengupas apa itu idempotency key, mengapa ia penting, dan pola implementasi praktis di dua sisi yang paling rawan: saat merchant memanggil API pembayaran dan saat merchant menerima webhook.

Apa Itu Idempotency dan Idempotency Key

Dalam istilah teknis, sebuah operasi disebut idempoten jika menjalankannya satu kali menghasilkan efek yang sama dengan menjalankannya berkali-kali. Membaca data (GET) secara alami idempoten — memuat halaman sepuluh kali tidak mengubah apa pun. Masalah muncul pada operasi yang mengubah keadaan, seperti membuat tagihan atau melakukan penarikan dana. Menjalankannya dua kali bisa berarti dua transaksi.

Idempotency key adalah penanda unik (biasanya string acak seperti UUID) yang Anda lampirkan pada sebuah permintaan. Server menggunakan penanda ini untuk mengenali: "Apakah saya sudah pernah memproses permintaan dengan kunci ini?" Jika sudah, server tidak memproses ulang; ia cukup mengembalikan hasil yang sama seperti permintaan pertama. Dengan begitu, retry akibat timeout, klik ganda, atau koneksi putus tidak lagi berbahaya.

Kuncinya harus dibuat oleh pihak pengirim (client/merchant), bukan server, dan harus tetap sama selama Anda me-retry permintaan yang secara logika identik. Jika Anda membuat kunci baru setiap retry, perlindungannya hilang.

Kenapa Idempotency Penting di API Pembayaran

Jaringan tidak pernah sepenuhnya andal. Skenario yang sering terjadi dan berpotensi merusak:

  • Timeout ambigu. Anda mengirim permintaan buat tagihan, server memprosesnya, tetapi jawabannya tak sampai karena koneksi putus. Anda tidak tahu apakah tagihan sudah dibuat, jadi Anda me-retry. Tanpa idempotency, ini menghasilkan dua tagihan.
  • Klik ganda pengguna. Pelanggan menekan tombol bayar dua kali karena halaman terasa lambat.
  • Retry otomatis. Banyak HTTP client atau job queue otomatis mengulang permintaan yang gagal. Tanpa kunci, setiap ulangan adalah transaksi baru.
  • Pemrosesan webhook berulang. Sistem notifikasi yang andal justru dirancang untuk mengirim ulang jika belum menerima konfirmasi. Artinya Anda pasti akan menerima event yang sama lebih dari sekali pada suatu waktu.

Dampak kegagalan bukan sekadar bug teknis: pelanggan bisa tertagih dua kali, stok ikut terpotong ganda, atau saldo merchant tercatat keliru. Untuk operasi keluar seperti penarikan dana, risikonya bahkan lebih serius. Karena itu idempotency adalah bagian penting dari keandalan integrasi API pembayaran secara keseluruhan — sepenting menjaga alur pembayaran tetap aman dan bisa diprediksi.

Cara Kerja di Sisi Server (Ringkas)

Meski Anda sebagai merchant tak perlu menulis logika ini di sisi penyedia, memahaminya membantu Anda memakainya dengan benar. Ketika server menerima permintaan dengan idempotency key, alur umumnya:

  1. Cek apakah kunci sudah pernah tercatat.
  2. Jika belum: proses permintaan, simpan hasilnya bersama kunci, lalu kembalikan hasil.
  3. Jika sudah ada dan selesai: kembalikan hasil yang tersimpan tanpa memproses ulang.
  4. Jika sudah ada tapi masih diproses: tolak dengan aman (misalnya minta client menunggu), agar tidak terjadi pemrosesan paralel ganda.

Server biasanya menyimpan kunci untuk jangka waktu tertentu (misalnya beberapa jam hingga sehari), sehingga retry dalam rentang wajar tetap terlindungi.

Pola Implementasi di Sisi Merchant (Saat Memanggil API)

Berikut praktik yang bisa Anda terapkan ketika membuat tagihan lewat REST API:

1. Buat kunci unik per niat transaksi

Buat satu idempotency key untuk setiap "niat bayar" yang unik — misalnya per pesanan (order_id). Gunakan UUID acak atau turunan deterministik dari ID pesanan Anda. Yang penting: kunci ini konsisten selama Anda me-retry pesanan yang sama.

POST /v1/charges
Idempotency-Key: order-2026-07-29-A1B9F3
Content-Type: application/json

{ "amount": 150000, "method": "qris", "reference": "INV-00123" }

2. Pertahankan kunci selama retry

Simpan kunci itu (misalnya di baris pesanan pada database Anda) sebelum mengirim permintaan. Jika permintaan gagal atau timeout, kirim ulang dengan kunci yang sama, bukan kunci baru. Inilah inti perlindungannya.

3. Perlakukan timeout sebagai "tidak tahu", bukan "gagal"

Saat timeout, jangan langsung menganggap transaksi gagal. Retry dengan kunci sama; jika tagihan sudah terbuat, Anda akan menerima hasil yang sama, bukan tagihan kedua. Untuk kepastian penuh, Anda juga bisa mengecek status via GET.

4. Jangan ubah payload untuk kunci yang sama

Idempotency key mewakili satu isi permintaan tertentu. Jika Anda mengirim kunci yang sama tetapi dengan jumlah atau metode berbeda, server yang baik akan menolaknya karena dianggap konflik. Satu kunci = satu maksud transaksi.

Pola Idempotency di Sisi Webhook Pembayaran

Webhook adalah tempat kedua yang paling butuh idempotency. Sistem notifikasi yang tangguh sengaja mengirim ulang event bila belum menerima balasan sukses, sehingga endpoint Anda pasti akan menemui event ganda.

Di BorderPay, notifikasi dikirim sebagai webhook yang ditandatangani HMAC, dengan event seperti payment.paid, payment.expired, dan payment.failed. Tersedia juga log dan fitur kirim ulang. Karena itu, sisi merchant sebaiknya menerapkan dua lapis pertahanan:

1. Verifikasi tanda tangan HMAC dulu

Sebelum memproses apa pun, pastikan payload benar-benar berasal dari sumber tepercaya dengan memvalidasi tanda tangan HMAC. Ini mencegah pihak lain mengirim notifikasi palsu.

2. Buat penanganan idempoten dengan ID event

Setiap event memiliki identitas unik (ID event atau ID pembayaran). Sebelum memproses, catat apakah ID itu sudah pernah Anda tangani:

onWebhook(event):
  verifikasi HMAC signature
  jika sudah ada di tabel processed_events dengan event.id:
      balas 200 OK dan berhenti   // sudah diproses, abaikan duplikat
  proses efek bisnis (tandai lunas, kirim barang, dll)
  simpan event.id ke processed_events
  balas 200 OK

Simpan ID event di tabel khusus (dengan constraint unik) atau tandai status pesanan sedemikian rupa sehingga transisi "belum bayar → lunas" hanya bisa terjadi satu kali. Pola "hanya transisi sekali" ini sering lebih kuat daripada sekadar mencatat ID, karena langsung mengunci efek bisnis.

3. Selalu balas cepat dan idempoten

Balas 200 OK begitu Anda yakin event tercatat, lalu jalankan pekerjaan berat secara asinkron bila perlu. Jika Anda gagal membalas, event akan dikirim ulang — dan berkat idempotency, pengiriman ulang itu aman.

Idempotency Melengkapi Alur Pembayaran, Bukan Berdiri Sendiri

Perlu diingat bahwa BorderPay adalah lapisan teknologi (software) di atas mitra Payment Gateway yang berlisensi Bank Indonesia; pemrosesan dan penyimpanan dana dilakukan mitra berlisensi. BorderPay sendiri bukan payment gateway atau PJP. Dari sisi Anda sebagai merchant, yang penting adalah alur teknisnya jelas dan aman.

Beberapa karakter alur yang relevan dengan idempotency:

  • Tagihan QRIS berlaku 60 menit dan Virtual Account berlaku 24 jam; lewat itu otomatis kedaluwarsa. Karena tak ada bayar-telat, status akhir sebuah tagihan bersifat pasti, sehingga penanganan event payment.expired yang idempoten menjaga catatan Anda tetap konsisten. Perbedaan karakter kedua metode ini dibahas lebih jauh di artikel QRIS vs Virtual Account.
  • Cara integrasi beragam: buat link manual dari dashboard, payment link, Embed Checkout (tempel satu snippet), hingga REST API penuh — plus GET /payment-methods untuk discovery. Idempotency paling relevan pada jalur REST API dan penanganan webhook.
  • Mode test/sandbox bisa Anda pakai sejak hari pertama untuk menguji perilaku retry dan duplikasi webhook tanpa risiko. Perlu dicatat, untuk menerima uang sungguhan Anda tetap wajib menyelesaikan KYC lebih dulu.

Checklist Praktis

Sebelum go-live, pastikan hal-hal berikut sudah beres:

AreaYang perlu dipastikan
Panggilan APIKirim idempotency key unik per pesanan; pertahankan saat retry
TimeoutPerlakukan sebagai "tidak tahu", retry dengan kunci sama atau cek status
WebhookVerifikasi tanda tangan HMAC sebelum memproses
WebhookTangani event ganda via ID event / transisi status sekali-jalan
ResponsBalas cepat; pekerjaan berat dijalankan asinkron
UjiSimulasikan retry & duplikat di mode sandbox

Penutup

Idempotency adalah jaring pengaman yang membuat sistem pembayaran tetap benar meski jaringan tidak sempurna. Di sisi merchant, kuncinya sederhana: kirim idempotency key yang konsisten saat memanggil API, dan buat penanganan webhook Anda tahan terhadap event ganda dengan verifikasi tanda tangan plus pengecekan ID event. Dengan dua kebiasaan ini, risiko double-charge dan double-proses bisa ditekan drastis.

Ingin mulai mencoba? Anda bisa menguji alur retry dan webhook di mode sandbox sejak awal. Pelajari detail teknisnya di dokumentasi, cek struktur biaya transaksi di halaman pricing, atau daftar untuk mulai bereksperimen. Untuk pertanyaan umum, tersedia juga halaman FAQ.

Siap menerima pembayaran?

Coba integrasi & mode test gratis sejak hari pertama.

Daftar gratis →