Pembayaran QRIS
Buat dan pulihkan satu top-up aktif tanpa menggandakan pembayaran atau mengkreditkan saldo sebelum konfirmasi provider.
Unduh OpenAPI 3.1Di halaman ini
Sebelum mengirim request
Nominal top-up saat ini Rp 10.000–Rp 1.000.000. UI polling setiap 5 detik selama CREATING/PENDING. Hanya status PAID terkonfirmasi yang menambah saldo; totalAmount adalah nominal bayar, requestedAmount adalah nominal kredit.
Endpoint, field, dan status HTTP mengikuti implementasi. Nilai ID, nomor, OTP, waktu, saldo, serta quote di contoh adalah ilustrasi, bukan data akun atau pilihan yang bisa langsung dibeli. Ganti dengan data dari instalasimu. Halaman ini tidak mengirim request atau menjalankan transaksi.
JavaScript dijalankan pada origin aplikasi setelah login. Contoh cURL memakai PING_ORIGIN dan cookie jar PING_COOKIE_JAR dari panduan autentikasi. Sukses memakai { ok: true, data }; create juga HTTP 200, bukan 201. Semua endpoint di halaman ini memerlukan sesi aktif dan dapat mengembalikan 401, 403, atau 500.
Baca pembayaran aktif
/api/payments/klikqrisSession cookieSource : app/api/payments/klikqris/route.ts
Membaca pembayaran CREATING/PENDING terakhir dari database. Bentuk data adalah { payment: Payment | null }, bukan Payment langsung. Gunakan endpoint detail untuk pemeriksaan provider.
const response = await fetch("/api/payments/klikqris", {
credentials: "same-origin",
cache: "no-store",
});
const body = await response.json();
if (!response.ok || !body.ok) {
throw Object.assign(
new Error(body.error?.message ?? "Request gagal"),
{ code: body.error?.code, status: response.status },
);
}
const data = body.data;Buat top-up QRIS
/api/payments/klikqrisSession cookieSource : app/api/payments/klikqris/route.ts
Membuat top-up idempotent. Satu pembayaran belum selesai per akun. Respons Payment bisa masih CREATING dengan materi QR null. Pembayaran aktif dengan nominal sama dapat dikembalikan alih-alih membuat transaksi kedua.
Menjalankan request ini membuat transaksi pembayaran nyata pada instalasi yang terhubung provider. Respons hilang tidak boleh memicu pembuatan transaksi baru; pulihkan melalui GET pembayaran aktif/detail.
| Body JSON | Tipe | Wajib | Keterangan |
|---|---|---|---|
| amount | integer | Ya | Rupiah utuh, antara 10000 dan 1000000. |
| clientRequestId | string · uuid | Ya | UUID untuk satu top-up. Jangan ganti UUID karena respons jaringan hilang. |
const response = await fetch("/api/payments/klikqris", {
method: "POST",
credentials: "same-origin",
cache: "no-store",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"amount": 10000,
"clientRequestId": "f41c29d8-967d-469d-ae4f-0114c38bf715"
}),
});
const body = await response.json();
if (!response.ok || !body.ok) {
throw Object.assign(
new Error(body.error?.message ?? "Request gagal"),
{ code: body.error?.code, status: response.status },
);
}
const data = body.data;| Kode error | HTTP | Tindakan |
|---|---|---|
| VALIDATION_ERROR | 400 | Periksa tipe, field wajib, format UUID, dan field tambahan. |
| IDEMPOTENCY_CONFLICT | 409 | Pulihkan pembayaran awal. UUID baru hanya untuk niat transaksi baru. |
| CONFLICT | 409 | Baca pembayaran aktif, jangan terus membuat top-up baru. |
| PAYMENT_NOT_CONFIGURED | 503 | Pemilik instalasi harus menyiapkan KlikQRIS; bukan mengganti data dengan demo. |
| PAYMENT_PROVIDER_ERROR | 502 | Baca pembayaran aktif atau detail dengan ID yang sama. |
Periksa pembayaran
/api/payments/klikqris/{id}Session cookieSource : app/api/payments/klikqris/[id]/route.ts
Membaca pembayaran milik sesi dan melakukan poll-through terbatas untuk pembayaran aktif. UI polling 5 detik, sedangkan klaim pemeriksaan provider dibatasi sekitar 10 detik. Respons langsung Payment, bukan { payment }.
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
| id (path) | string · uuid | Ya | UUID pembayaran milik pengguna bersesi. |
const response = await fetch("/api/payments/klikqris/5d81627b-4c2b-4cab-bd07-2a5ed675fe5f", {
credentials: "same-origin",
cache: "no-store",
});
const body = await response.json();
if (!response.ok || !body.ok) {
throw Object.assign(
new Error(body.error?.message ?? "Request gagal"),
{ code: body.error?.code, status: response.status },
);
}
const data = body.data;| Kode error | HTTP | Tindakan |
|---|---|---|
| VALIDATION_ERROR | 400 | Periksa tipe, field wajib, format UUID, dan field tambahan. |
| NOT_FOUND | 404 | Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna. |
| PAYMENT_PROVIDER_ERROR | 502 | Baca pembayaran aktif atau detail dengan ID yang sama. |
| CONFLICT | 409 | Baca pembayaran aktif, jangan terus membuat top-up baru. |
Schema · Payment
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
| id | string · uuid | Ya | Sesuai tipe yang ditampilkan. |
| requestedAmount | integer | Ya | Jumlah top-up yang dikreditkan jika PAID terkonfirmasi. |
| totalAmount | integer | null | Ya | Total yang harus dibayar ke provider; bisa berbeda dari requestedAmount. |
| status | CREATING | PENDING | PAID | EXPIRED | FAILED | Ya | Sesuai tipe yang ditampilkan. |
| qrisUrl | string | null | Ya | Materi QR dari provider; tersedia hanya untuk pembayaran aktif. |
| qrisImage | string | null | Ya | Sesuai tipe yang ditampilkan. |
| paymentUrl | string | null | Ya | Sesuai tipe yang ditampilkan. |
| expiresAt | string | null | Ya | Timestamp provider tanpa zona waktu, disimpan apa adanya. Bukan waktu ISO UTC. |
| createdAt | string · date-time | Ya | ISO 8601 dengan zona waktu. |
| paidAt | string | null · date-time | Ya | ISO 8601 dengan zona waktu. |
| message | string | null | Ya | Sesuai tipe yang ditampilkan. |
Schema · ActivePayment
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
| payment | Payment | null | Ya | Pembayaran aktif, atau null jika tidak ada. |