Panduan Integrasi BCA Payment Gateway
Dokumentasi lengkap dan praktis untuk menghubungkan toko online atau aplikasi Anda dengan sistem pembayaran BCA QRIS Dinamis otomatis.
1. Pengenalan & Alur Kerja
Gateway ini bekerja secara self-hosted tanpa potongan biaya transaksi pihak ketiga. Setiap pembayaran pembeli otomatis dideteksi dari mutasi KlikBCA Merchant dan diteruskan ke server toko Anda dalam hitungan detik.
Toko memanggil POST /api/v1/charge. Sistem menambah kode unik Rp 1–199 agar nominal tiap pembeli berbeda.
Tampilkan qris_image. Dengan acquirer: "bca", pembayaran dari aplikasi apa pun wajib masuk ke KlikBCA.
Bot pemantau memeriksa mutasi KlikBCA tiap ±10 detik dan langsung mengirim HTTP POST ke webhook_url toko Anda.
2. Autentikasi (API Key)
Seluruh endpoint API publik (/api/v1/*) wajib menyertakan API Key Merchant pada header HTTP Authorization menggunakan format Bearer Token.
Authorization: Bearer BCA-GW-YOUR_API_KEY Content-Type: application/json
3. Charge API (Buat Invoice BCA QRIS)
Endpoint ini membuat transaksi QRIS Dinamis baru, menghitung kode unik otomatis (1–199) agar tidak bentrok dengan tagihan pending lain, dan mengembalikan gambar QR siap scan.
Parameter Request Body (JSON)
| Field | Tipe | Status | Deskripsi |
|---|---|---|---|
| external_id | String | Wajib | ID invoice unik dari sistem toko Anda (contoh: ORDER-100249). |
| amount | Number | Wajib | Nominal dasar transaksi dalam Rupiah (IDR), bernilai positif. Sistem otomatis menambahkan kode unik 1–199. |
| webhook_url | String | Opsional | URL endpoint server toko Anda untuk menerima notifikasi POST otomatis saat pembayaran sukses. |
| acquirer | String | Opsional |
Rute bank tujuan jika QRIS Anda memiliki multi-acquirer (misal DANA + BCA). Nilai: bca (default, wajib agar auto-verifikasi KlikBCA jalan), dana, atau multi. |
ID invoice unik dari sistem toko Anda (contoh: ORDER-100249).
Nominal dasar (IDR) bernilai positif. Sistem otomatis menambah kode unik 1–199.
URL callback server Anda untuk menerima notifikasi sukses otomatis.
Rute bank QRIS: bca (default, direkomendasikan), dana, atau multi.
Contoh Request Body (JSON)
{
"external_id": "ORDER-100249",
"amount": 10000,
"acquirer": "bca",
"webhook_url": "https://toko-anda.com/api/webhook-bca"
}
Respons Sukses (201 Created)
{
"status": "pending",
"transaction_id": 18,
"external_id": "ORDER-100249",
"amount": 10103,
"base_amount": 10000,
"fee": 103,
"payment_method": "qris",
"qris_acquirer": "bca",
"active_acquirers": ["BCA"],
"qris_string": "00020101021226650013ID.CO.BCA.WWW...",
"qris_image": "data:image/png;base64,iVBORw0KGgo...",
"created_at": "2026-11-11T05:50:00.000Z"
}
4. Status API (Cek Status Pembayaran)
Gunakan endpoint ini untuk memeriksa status transaksi secara manual atau polling berkala dari backend toko Anda menggunakan external_id yang Anda kirim saat pembuatan invoice.
Path Parameter
| Parameter | Tipe | Status | Deskripsi |
|---|---|---|---|
| :external_id | String | Wajib | ID invoice milik toko Anda (contoh: /api/v1/status/ORDER-100249). |
Path parameter ID invoice toko Anda (contoh: /api/v1/status/ORDER-100249).
Respons Sukses (200 OK)
{
"external_id": "ORDER-100249",
"status": "success",
"amount": 10103,
"payment_method": "qris",
"created_at": "2026-11-11T05:50:00.000Z",
"updated_at": "2026-11-11T05:51:12.000Z"
}
5. Webhook Callback (Notifikasi Otomatis)
Begitu mutasi dana masuk terdeteksi di KlikBCA Merchant, server gateway akan otomatis mengirim request HTTP POST (dengan maksimal 3 kali percobaan ulang bila gagal) ke webhook_url yang Anda daftarkan.
Payload JSON yang Dikirim Gateway ke Server Anda
{
"transaction_id": 18,
"external_id": "ORDER-100249",
"amount": 10103,
"status": "success",
"updated_at": "2026-11-11T05:51:12.000Z"
}
- Selalu kembalikan response HTTP 200 OK secepat mungkin setelah menerima payload agar tidak dianggap gagal oleh sistem retry.
- Terapkan pengecekan idempoten: cek apakah order external_id masih berstatus belum dibayar sebelum memproses pesanan agar tidak diproses dua kali.
- Untuk keamanan ekstra, pastikan nominal amount & status dikonfirmasi ulang melalui GET /api/v1/status/:external_id sebelum mengirim barang digital/fisik.
6. Contoh Integrasi Kode (Siap Pakai)
Pilih tab di bawah untuk menyalin contoh kode lengkap pembuatan invoice, cek status, dan penerima webhook. URL server di bawah ini sudah menyesuaikan otomatis dengan domain aktif Anda.
# 1. Membuat invoice BCA QRIS Dinamis
curl -X POST https://bca.5nod.com/api/v1/charge \
-H "Authorization: Bearer BCA-GW-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_id": "ORDER-100249",
"amount": 10000,
"acquirer": "bca",
"webhook_url": "https://toko-anda.com/api/webhook-bca"
}'
# 2. Memeriksa status transaksi
curl -X GET https://bca.5nod.com/api/v1/status/ORDER-100249 \
-H "Authorization: Bearer BCA-GW-YOUR_API_KEY"
<?php
// Membuat Invoice BCA QRIS Dinamis (PHP cURL)
$url = "https://bca.5nod.com/api/v1/charge";
$apiKey = "BCA-GW-YOUR_API_KEY";
$payload = [
"external_id" => "ORDER-" . time(),
"amount" => 10000,
"acquirer" => "bca",
"webhook_url" => "https://toko-anda.com/api/webhook-bca"
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . $apiKey,
"Content-Type: application/json"
],
CURLOPT_TIMEOUT => 20
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($httpCode === 201 && isset($data['qris_image'])) {
echo "<h3>Total Bayar: Rp " . number_format($data['amount'], 0, ',', '.') . "</h3>";
echo '<img src="' . htmlspecialchars($data['qris_image']) . '" alt="QRIS BCA" width="240" />';
} else {
echo "Gagal membuat invoice: " . ($data['message'] ?? 'Unknown error');
}
?>
// Membuat Invoice & Cek Status dengan Fetch bawaan Node.js 18+
const BASE_URL = 'https://bca.5nod.com';
const API_KEY = 'BCA-GW-YOUR_API_KEY';
async function createInvoice() {
const res = await fetch(`${BASE_URL}/api/v1/charge`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
external_id: 'ORDER-' + Date.now(),
amount: 10000,
acquirer: 'bca',
webhook_url: 'https://toko-anda.com/api/webhook-bca'
})
});
const data = await res.json();
if (!res.ok) throw new Error(data.message || 'Gagal membuat invoice');
console.log('Nominal Unik (IDR):', data.amount);
console.log('Routing Bank:', data.active_acquirers);
console.log('QR String:', data.qris_string);
return data;
}
createInvoice().catch(console.error);
<?php
// Contoh Endpoint Penerima Webhook di Server Toko (PHP)
// URL: https://toko-anda.com/api/webhook-bca
$rawBody = file_get_contents('php://input');
$payload = json_decode($rawBody, true);
if (!$payload || empty($payload['external_id']) || ($payload['status'] ?? '') !== 'success') {
http_response_code(400);
echo json_encode(['ok' => false, 'message' => 'Payload tidak valid']);
exit;
}
$externalId = $payload['external_id'];
$amountPaid = (float) ($payload['amount'] ?? 0);
// 1. Verifikasi silang ke Gateway API agar 100% aman dari request palsu
$ch = curl_init("https://bca.5nod.com/api/v1/status/" . urlencode($externalId));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer BCA-GW-YOUR_API_KEY"]
]);
$verifyJson = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($verifyJson['status'] ?? '') === 'success' && (float)$verifyJson['amount'] === $amountPaid) {
// 2. Tandai order sebagai LUNAS di database toko Anda (secara idempoten)
// updateOrderPaid($externalId);
http_response_code(200);
echo json_encode(['ok' => true]);
} else {
http_response_code(400);
echo json_encode(['ok' => false, 'message' => 'Verifikasi status gagal']);
}
?>
// Contoh Endpoint Penerima Webhook di Server Toko (Node.js Express)
const express = require('express');
const app = express();
app.use(express.json());
const GATEWAY_URL = 'https://bca.5nod.com';
const API_KEY = 'BCA-GW-YOUR_API_KEY';
app.post('/api/webhook-bca', async (req, res) => {
const { external_id, amount, status } = req.body || {};
if (!external_id || status !== 'success') {
return res.status(400).json({ ok: false, message: 'Payload tidak valid' });
}
try {
// Verifikasi ulang ke Gateway API untuk memastikan pembayaran asli
const verifyRes = await fetch(`${GATEWAY_URL}/api/v1/status/${encodeURIComponent(external_id)}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const tx = await verifyRes.json();
if (verifyRes.ok && tx.status === 'success' && Number(tx.amount) === Number(amount)) {
// TODO: Update status order di database toko Anda menjadi PAID (idempoten)
console.log(`Order ${external_id} lunas sebesar Rp ${amount}`);
return res.status(200).json({ ok: true });
}
return res.status(400).json({ ok: false, message: 'Status transaksi belum lunas' });
} catch (err) {
return res.status(500).json({ ok: false, message: err.message });
}
});
7. Kode Status HTTP & Troubleshooting
Referensi cepat arti kode respons HTTP yang dikembalikan oleh Gateway API beserta cara mengatasinya.
| Kode | Arti | Penyebab Umum & Solusi |
|---|---|---|
| 200 / 201 | Sukses | Request berhasil diproses (201 untuk pembuatan invoice baru, 200 untuk cek status). |
| 400 | Bad Request | Parameter wajib kosong (external_id/amount), nominal ≤ 0, atau String QRIS Statis belum diset pada merchant/file .env (jalankan Sync QRIS di Dashboard). |
| 401 | Unauthorized | Header Authorization: Bearer ... tidak ada, API Key salah, atau merchant sedang nonaktif. |
| 404 | Not Found | Transaksi dengan external_id tersebut tidak ditemukan untuk merchant terkait. |
| 500 | Server Error | Terjadi kesalahan internal saat membentuk QRIS. Periksa log aktivitas sistem pada Dashboard Admin. |
Request berhasil diproses (201 invoice baru, 200 cek status).
Field wajib kosong, nominal ≤ 0, atau QRIS Statis belum diset (klik Sync QRIS di Dashboard).
Header Authorization: Bearer ... hilang atau API Key salah.
ID transaksi external_id tidak ditemukan pada merchant Anda.
Kesalahan internal server saat generate QRIS; cek Live Logs di Dashboard Admin.