Charges

Membuat charge — POST /v1/charges

{
  "invoice_id": "INV-20261105-0001",
  "method": "qris",
  "amount": 15000,
  "gateway": "gdc",
  "callback_url": "https://api.vogsystem.com/payroute/callback",
  "metadata": { "kiosk": "K-12" }
}
Field Wajib Aturan
invoice_id ya 1–64 karakter A-Z a-z 0-9 . _ : -, unik per client, case-sensitive
method ya qris (metode lain menyusul)
amount ya rupiah, bilangan bulat ≥ 1
gateway tidak tripay / gdc / midtrans (fake di staging). Kosong = default
callback_url ya https, host harus terdaftar untuk client Anda
metadata tidak objek JSON ≤ 4 KB, dikembalikan apa adanya

Respons 201 berisi charge dengan qris.qr_string (render sebagai QR), expires_at, dan gateway yang dipakai.

Idempotensi per invoice

Status

Status Arti
pending QR aktif, menunggu bayar
paid dibayar — final, tidak pernah berubah lagi
expired QR lewat waktu tanpa pembayaran
failed gateway menolak / gagal

Pembayaran yang datang terlambat (setelah expired) tetap membuat charge menjadi paid dan Anda menerima charge.paid. Jangan anggap expired sebagai final untuk pembukuan.

Satu invoice bisa dibayar dua kali

Urutan ini mungkin terjadi: charge A expired → Anda membuat charge B untuk invoice yang sama (QR baru) → pelanggan ternyata sudah membayar QR A terlambat dan membayar QR B. Payroute mencatat keduanya paid (uang sudah diambil gateway) dan mengirim charge.paid untuk masing-masing — dua kali untuk satu invoice_id, dengan charge.id berbeda.

Project wajib menangani ini: kunci pembayaran per charge.id (bukan hanya invoice_id), deteksi invoice yang menerima lebih dari satu charge.paid, dan proses refund / rekonsiliasi lewat tim finance. Payroute belum mendukung refund otomatis.

Mengecek status — GET /v1/charges/{id}

Polling tiap beberapa detik (mis. 5 detik di kiosk) aman: Payroute menjawab dari database-nya dan hanya bertanya ke gateway paling sering sekali per 30 detik per charge (dihitung sejak dibuat). Webhook tetap jalur utama; polling adalah cadangan.

Daftar charge invoice — GET /v1/charges?invoice_id=…

Semua charge Anda untuk invoice itu, terbaru dulu: {"data": [ … ]}.

Kode error

HTTP error.code Kapan
400 invalid_request JSON rusak, field tak dikenal, query wajib kosong, body > 64 KB (413)
400 unknown_gateway gateway bukan kode yang dikenal
401 invalid_signature autentikasi gagal
404 not_found charge tidak ada / milik client lain
409 invoice_conflict / invoice_paid lihat idempotensi
422 invalid_request validasi per field, detail di error.fields
422 callback_not_allowed callback_url bukan https / host tidak terdaftar
502 gateway_unavailable semua gateway gagal, coba lagi

Setiap error membawa request_id; sertakan saat melapor masalah.