Cegah pembayaran ganda: cara idempotensi menjaga satu pesanan tetap satu pembayaran
Timeout, klik dua kali dan percobaan ulang bisa membuat dua pembayaran untuk satu pesanan. Begini cara merchant_reference dan header Idempotency-Key membuat setiap request PAYWISE aman diulang.
Terbit 07 Oktober 2026 4 menit baca
Jaringan tidak pernah sempurna. Server Anda mengirim request untuk membuat pembayaran, koneksinya putus, dan Anda tidak pernah menerima jawabannya. Pembayarannya sudah dibuat atau belum? Kalau Anda langsung mencoba lagi, bisa jadi ada dua pembayaran untuk satu pesanan, bahkan pelanggan bisa membayar dua kali.
Solusinya punya nama yang panjang tapi idenya sederhana: idempotensi. Sebuah request disebut idempoten kalau mengirimnya dua kali hasilnya sama dengan mengirimnya sekali.

Dari mana duplikat muncul
- Timeout. Request sampai ke PAYWISE, tapi jawabannya tidak sampai ke Anda.
- Percobaan ulang otomatis. Library HTTP atau antrean job Anda mencoba lagi setelah error.
- Klik dua kali. Pelanggan menekan "Bayar" dua kali, atau me-refresh halaman checkout.
- Dua server. Dua worker memproses pesanan yang sama di waktu yang sama.
Pembayaran: ID pesanan Anda adalah kuncinya
Saat membuat transaksi, Anda mengirim merchant_reference: ID pesanan milik Anda sendiri. PAYWISE memakainya untuk mengenali request yang diulang:
| Yang Anda kirim | Jawaban PAYWISE |
|---|---|
merchant_reference baru |
201 Created, transaksi baru |
merchant_reference yang sama dengan detail yang sama |
200 OK berisi transaksi asli, tidak ada yang dibuat baru |
merchant_reference yang sama dengan detail berbeda (misalnya nominal lain) |
409 DUPLICATE_REFERENCE |
Jadi setelah timeout, Anda bisa mengirim ulang request yang persis sama dengan aman:
curl -X POST https://paywise.asia/api/v1/transactions \
-H "Authorization: Bearer pw_test_..." \
-H "Content-Type: application/json" \
-d '{"merchant_reference":"ORDER-1042","customer_id":"user-42","amount":150000,"payment_method":"QRIS"}'
Setiap environment (sandbox dan live) punya daftar referensinya sendiri, jadi pengujian tidak akan memblokir ID pesanan live.
Kapan memakai referensi baru
Ada satu pengecualian. Kalau PAYWISE menjawab 502 PROVIDER_ERROR atau 504 PROVIDER_TIMEOUT, transaksi itu sudah ditandai gagal, dan pesan errornya menyebutkan hal itu. Coba lagi dengan merchant_reference baru, misalnya ORDER-1042-2, dan simpan hubungannya ke pesanan di database Anda sendiri. Begitu juga untuk pembayaran yang kedaluwarsa: buat pembayaran baru, jangan memakai ulang referensi lama.
Penarikan dana: header Idempotency-Key
Mengeluarkan uang butuh perlindungan yang sama. POST /api/v1/withdrawals wajib memakai header Idempotency-Key: 8 sampai 64 karakter (huruf, angka dan . _ : -), unik untuk setiap penarikan.
curl -X POST https://paywise.asia/api/v1/withdrawals \
-H "Authorization: Bearer pw_live_..." \
-H "Idempotency-Key: payout-2026-10-07-0001" \
-H "Content-Type: application/json" \
-d '{"payment_method":"USDT","amount":250,"wallet_address":"0x...","network":"BEP20"}'
- Key yang sama dengan detail yang sama mengembalikan penarikan asli (
200). - Key yang sama dengan detail berbeda mengembalikan
409 DUPLICATE_REQUEST. 409 WITHDRAWAL_BUSYberarti ada penarikan lain yang sedang dibuat di saat yang sama: tunggu sebentar lalu coba lagi dengan key yang sama.
Buat key-nya sebelum percobaan pertama dan simpan bersama data penarikan di database Anda. Key yang dibuat baru di setiap percobaan ulang tidak melindungi apa-apa.
Webhook: buat sisi Anda idempoten juga
Idempotensi berlaku dua arah. Kalau server Anda tidak menjawab webhook, PAYWISE mengirimnya lagi, jadi event payment.paid yang sama bisa datang lebih dari sekali. Buat handler Anda aman diulang:
- Verifikasi tanda tangannya (caranya).
- Cari pesanan berdasarkan
merchant_reference. - Kalau pesanan sudah dibayar, jawab
200dan berhenti. Jangan kirim barang dua kali atau mengirim email kedua. - Kalau belum, tandai terbayar dalam satu transaksi database, lalu jawab
200.
Daftar periksa
- Pakai ID pesanan asli sebagai
merchant_reference, jangan nilai acak di setiap request. - Ulangi request yang timeout atau error jaringan dengan request yang sama.
- Pakai referensi baru hanya setelah pembayaran gagal atau kedaluwarsa.
- Simpan
Idempotency-Keysetiap penarikan sebelum mengirimnya. - Buat handler webhook mengabaikan event yang sudah pernah diproses.
Ingin melihatnya sendiri? Kirim request yang sama dua kali di sandbox dan bandingkan jawabannya di log API. Semua kode error ada di dokumentasi API.

