PAYWISE
id
← Semua artikel

Developer

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

Tersedia juga dalam: English, 简体中文

Cegah pembayaran ganda: cara idempotensi menjaga satu pesanan tetap satu pembayaran

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.

Request timeout, request yang sama dikirim lagi, dan PAYWISE mengembalikan pembayaran asli tanpa membuat duplikat

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_BUSY berarti 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:

  1. Verifikasi tanda tangannya (caranya).
  2. Cari pesanan berdasarkan merchant_reference.
  3. Kalau pesanan sudah dibayar, jawab 200 dan berhenti. Jangan kirim barang dua kali atau mengirim email kedua.
  4. 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-Key setiap 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.

Artikel lainnya

Mulai dengan key sandbox hari ini.

Daftar, buat key sandbox, dan kirim transaksi pertama dari playground dalam beberapa menit.