Lifecycle & settlement
Bedakan status database dari DTO client, lalu pahami kapan dana ditahan, dibebankan, dilepas, dan kapan sebuah order benar-benar selesai.
Unduh OpenAPI 3.1Di halaman ini
Database dan API memakai status berbeda
mapOrder di lib/ping/mappers.ts menyederhanakan status domain menjadi status untuk UI. Jangan membandingkan Order.status dengan ACTIVE atau CODE_RECEIVED: nilai itu hanya ada di domain/database.
| Status domain | Order.status | Sinyal yang dipakai client |
|---|---|---|
| CREATED / PURCHASING | waiting | isPreparing = true; phone masih berupa teks status. |
| ACTIVE | waiting | Nomor terbit; canCancel mengikuti cooldown server. |
| CODE_RECEIVED | waiting | code tersedia, canComplete = true, canCancel = false. |
| COMPLETED | completed | Pembebanan selesai; berhenti polling. |
| CANCELLED | cancelled | Pembatalan telah dikonfirmasi; berhenti polling. |
| EXPIRED | expired | Kedaluwarsa terkonfirmasi; berhenti polling. |
| FAILED_UPSTREAM | failed | Pembelian gagal definitif; dana hold dilepas. |
CODE_RECEIVED masih menjadi waiting pada DTO. Tawarkan penyelesaian jika canComplete true, dan tampilkan code bila tersedia. Jangan menunggu status completed untuk menampilkan SMS.
Jalur uang
Hold saat order dibuat
Saldo tersedia berkurang karena sebagian saldo ditahan. Ini belum pembebanan final. Ledger dan order dibuat secara terkoordinasi.
Capture setelah penyelesaian
Saat order diselesaikan, dana yang ditahan ditangkap menjadi pembayaran. Settlement menggunakan kunci tetap per order untuk mencegah pembebanan ganda.
Release setelah gagal atau batal terkonfirmasi
Kegagalan pembelian yang definitif, pembatalan, atau kedaluwarsa terkonfirmasi melepas dana. Respons ambigu tidak membenarkan release.
Revalidasi, jangan menebak saldo
Sesudah mutasi, baca ulang akun, detail order, daftar order, dan ledger. Jangan mengurangi/menambah saldo sendiri di komponen.
Cooldown dan pembatalan
Pembatalan paling awal tersedia 2 menit setelah respons pembelian selesai, dengan fallback timestamp dari server. Hanya ACTIVE sebelum SMS yang memenuhi syarat. Gunakan canCancel dan cancelAvailableAt untuk UI; server tetap memeriksa ulang saat aksi dilakukan.
Saat timer kedaluwarsa, server harus mengamati provider lalu membatalkan jika masih menunggu. Browser tidak boleh menetapkan EXPIRED, menghapus order, atau melepas saldo berdasarkan jam lokal. Jika SMS datang bersamaan dengan pembatalan, baca respons terkini dan ikuti status yang diputuskan server.
Polling tanpa request bertumpuk
- GET detail order berjalan tiap 5 detik selama DTO berstatus waiting. Hook useOrder berhenti saat tab tersembunyi/offline dan pada status terminal.
- Jangan gunakan loop setInterval yang membuat request tumpang tindih. Gunakan SWR/useOrder dengan interval dan aturan retry yang sudah ada.
- GET daftar order tidak memeriksa provider. Membaca daftar saja tidak cukup untuk menerima status/SMS terbaru.
- Provider budget, per-order lease, dan backoff ada di server. Satu request browser tidak menjamin satu panggilan upstream atau data upstream yang langsung baru.
Lifecycle top-up berbeda
| Status Payment | Perilaku client |
|---|---|
| CREATING | Hasil pembuatan masih dikonfirmasi. Materi QR bisa null. Jangan membuat pembayaran baru. |
| PENDING | Tampilkan materi pembayaran yang tersedia; pengguna membayar totalAmount. |
| PAID | Server telah memverifikasi dan mengkreditkan requestedAmount sekali. Revalidasi dompet. |
| EXPIRED / FAILED | Berhenti polling. Materi QR tidak ditampilkan lagi; baca message bila ada. |
Provider dapat mengirim timestamp tanpa zona waktu. Simpan/tampilkan dengan benar, jangan menambahkan Z atau menyimpulkan status PAID/EXPIRED dari jam browser. Hanya konfirmasi provider mengubah status pembayaran.