Ringkasan Utama
Standar SNAP dari Bank Indonesia, yang ditetapkan lewat PADG 23/15/PADG/2021 pada 16 Agustus 2021, mewajibkan skema request, alur autentikasi dan kode error yang seragam di seluruh bank dan payment processor Indonesia. Bagi developer hal itu menggantikan tebak-tebakan integrasi per bank dengan satu kontrak yang dipublikasikan di Developer Site SNAP milik ASPI, termasuk layanan MPM untuk membuat dan membayar QRIS dinamis.
Standar SNAP (Standar Nasional Open API Pembayaran) Bank Indonesia telah mengubah secara fundamental cara developer fintech mengintegrasikan diri dengan bank dan pemroses pembayaran Indonesia. Diatur dalam PADG 23/15/PADG/2021 yang ditetapkan pada 16 Agustus 2021, SNAP mewajibkan skema request yang seragam, alur autentikasi, dan kode error di semua Penyelenggara Jasa Pembayaran (PJP) berlisensi, menggantikan puluhan API bank proprietary dengan satu standar tunggal. Dikombinasikan dengan QRIS Antarnegara, yang menurut Bank Indonesia sudah dipakai di Thailand, Malaysia, Singapura, Jepang, Korea Selatan, dan Tiongkok, ekosistem open banking Indonesia kini menjadi salah satu yang paling komprehensif di Asia Tenggara.
Memahami SNAP: Cakupan dan Kategori API
PADG 23/15/PADG/2021 menetapkan ruang lingkup SNAP pada aspek interkoneksi dan interoperabilitas, standar keamanan sistem informasi, tata kelola, serta manajemen risiko Open API Pembayaran, dan menerapkan spesifikasi teknisnya pada lima kategori API: registrasi, informasi saldo, informasi riwayat transaksi, transfer kredit, dan transfer debit, ditambah kategori lain yang ditetapkan Bank Indonesia. Dalam spesifikasi yang dipublikasikan ASPI, transfer kredit mencakup transfer intrabank dan antarbank, virtual account, serta pembayaran QRIS Merchant Presented Mode (MPM), sedangkan transfer debit mencakup direct debit dan pembayaran QR Customer Presented Mode (CPM). Sejak 1 September 2023, pengelolaan standar ini beserta Developer Site-nya dipegang ASPI.
Detail API Pembayaran SNAP
Endpoint SNAP yang paling umum diintegrasikan, sesuai penamaan di spesifikasi ASPI, adalah: `/v1.0/access-token/b2b` (access token B2B), `/v1.0/transfer-interbank` (transfer kredit antarbank), `/v1.0/transfer-va/create-va` (pembuatan virtual account), `/v1.0/transfer-va/inquiry-va` (inquiry VA), dan `/v1.0/debit/payment-host-to-host` (debit langsung). Setiap bank yang mengimplementasikan SNAP mengekspos layanan ini dengan skema request/response yang sama, hanya berbeda pada base URL, prefix path di depan versi, dan kredensial partner yang diperlukan.
Integrasi QRIS Antarnegara
QRIS Antarnegara, di situs berbahasa Inggris BI disebut QRIS Cross-Border, adalah nama yang dipakai Bank Indonesia untuk pembayaran QRIS lintas negara. Wisatawan Indonesia memindai kode QR negara mitra di merchant yang bekerja sama di luar negeri, dan bila interkoneksinya berlaku dua arah, wisatawan asing membayar merchant QRIS Indonesia dari aplikasi negaranya. Bank Indonesia mencatat layanan ini sudah dipakai di Thailand (PromptPay), Malaysia (DuitNow QR), Singapura (NETS QR), Jepang (JPQR Global), Korea Selatan, dan Tiongkok (UnionPay), dengan batas Rp10.000.000 per transaksi, sama dengan QRIS domestik. Konversi kurs terjadi di dalam aplikasi pembayaran peserta: dana pembayar didebet dalam mata uangnya sendiri dan merchant Indonesia menerima notifikasi dalam rupiah, jadi integrasi merchant tidak perlu langkah konversi kurs sendiri.
Buat `X-EXTERNAL-ID` numerik yang baru untuk setiap panggilan SNAP. Spesifikasi ASPI mewajibkannya unik dalam hari yang sama dan menjawab nilai yang dipakai ulang dengan HTTP 409 Conflict (case code 00), jadi header ini adalah pengaman replay, bukan kunci retry. Idempotensi transfernya sendiri bertumpu pada `partnerReferenceNo`: provider yang sudah memproses referensi itu menjawab dengan case code 01, Duplicate partnerReferenceNo, alih-alih membuat transfer kedua.
Autentikasi: OAuth 2.0 dengan Penandatanganan Kunci Asimetris
Autentikasi SNAP menggunakan model keamanan dua lapis: alur OAuth 2.0 client credential untuk akuisisi access token, dan penandatanganan request HMAC-SHA512 untuk setiap panggilan API berikutnya. Request access token membawa tanda tangan asimetris SHA256withRSA atas client ID dan nilai X-TIMESTAMP, dibuat dengan private key Anda, untuk membuktikan identitas; token yang dikembalikan kadaluarsa setelah 900 detik. Tanda tangan HMAC-SHA512 per-request kemudian menggunakan access token dan hash body request untuk memastikan integritas pesan.
Implementasi Penandatanganan Request HMAC-SHA512 di Node.js
Algoritma tanda tangan SNAP memerlukan konstruksi `StringToSign` dari method HTTP, path relatif endpoint, access token, hash SHA-256 dari body request yang di-minify (di-encode hex dan huruf kecil), dan nilai header X-TIMESTAMP — digabung dengan titik dua. String ini kemudian ditandatangani dengan HMAC-SHA512 menggunakan client secret sebagai kunci. Tanda tangan berenkoding base64 yang dihasilkan dikirim dalam header `X-SIGNATURE`, dan X-TIMESTAMP wajib mengikuti format yyyy-MM-ddTHH:mm:ssTZD dari spesifikasi, misalnya 2026-10-12T14:30:00+07:00. Blok kode di bawah menampilkan implementasi lengkapnya.
// snap-api-client.js — Bank Indonesia SNAP API request with HMAC-SHA512
const crypto = require('crypto');
const axios = require('axios');
const CLIENT_ID = process.env.SNAP_CLIENT_ID;
const CLIENT_SECRET = process.env.SNAP_CLIENT_SECRET;
const PRIVATE_KEY = process.env.SNAP_PRIVATE_KEY; // PEM; the bank verifies with your public key
const BASE_URL = process.env.SNAP_BASE_URL; // each bank publishes its own sandbox host
const PREFIX = process.env.SNAP_PATH_PREFIX || ''; // bank-specific prefix in front of /v1.0
/**
* X-TIMESTAMP in the spec's yyyy-MM-ddTHH:mm:ssTZD form, here in WIB (+07:00)
*/
function snapTimestamp(date = new Date()) {
const wib = new Date(date.getTime() + 7 * 60 * 60 * 1000);
return wib.toISOString().slice(0, 19) + '+07:00';
}
/**
* X-EXTERNAL-ID: a numeric string of at most 36 characters, unique within the day
*/
function externalId() {
return Date.now().toString() + crypto.randomInt(0, 1e9).toString().padStart(9, '0');
}
/**
* Get a B2B access token (OAuth 2.0 client credentials, valid for 900 seconds)
*/
async function getAccessToken() {
const timestamp = snapTimestamp();
const signature = crypto
.createSign('RSA-SHA256') // SHA256withRSA over client_ID|X-TIMESTAMP
.update(`${CLIENT_ID}|${timestamp}`)
.sign(PRIVATE_KEY, 'base64');
const resp = await axios.post(`${BASE_URL}${PREFIX}/v1.0/access-token/b2b`, {
grantType: 'client_credentials'
}, {
headers: {
'X-CLIENT-KEY': CLIENT_ID,
'X-TIMESTAMP': timestamp,
'X-SIGNATURE': signature,
'Content-Type': 'application/json'
}
});
return resp.data.accessToken;
}
/**
* Interbank credit transfer (SNAP service code 18)
*/
async function transferCredit(token, payload) {
const path = `${PREFIX}/v1.0/transfer-interbank`;
const timestamp = snapTimestamp();
const body = JSON.stringify(payload); // minified; sign exactly the bytes you send
const bodyHash = crypto.createHash('sha256').update(body).digest('hex').toLowerCase();
const stringToSign = `POST:${path}:${token}:${bodyHash}:${timestamp}`;
const signature = crypto.createHmac('sha512', CLIENT_SECRET).update(stringToSign).digest('base64');
return axios.post(`${BASE_URL}${path}`, body, {
headers: {
Authorization: `Bearer ${token}`,
'X-TIMESTAMP': timestamp,
'X-SIGNATURE': signature,
'X-PARTNER-ID': CLIENT_ID,
'X-EXTERNAL-ID': externalId(),
'CHANNEL-ID': '95221',
'Content-Type': 'application/json'
}
});
}
// Usage
(async () => {
const token = await getAccessToken();
const result = await transferCredit(token, {
partnerReferenceNo: 'TXN-2026-001',
amount: { value: '100000.00', currency: 'IDR' },
beneficiaryAccountName: 'Budi Santoso',
beneficiaryBankCode: '014', // BCA
beneficiaryAccountNo: '1234567890',
sourceAccountNo: '9876543210',
transactionDate: snapTimestamp()
});
console.log('Transfer status:', result.data.responseCode); // 2001800 = success
})();Manajemen Private Key dan Rotasi Kunci
Tanda tangan asimetris SNAP memakai pasangan kunci RSA: Anda menandatangani dengan private key, dan setiap bank yang diintegrasikan memverifikasinya dengan public key Anda. Simpan private key dan client secret di secrets manager Anda (AWS Secrets Manager, HashiCorp Vault, atau Azure Key Vault) — jangan pernah commit ke source code. Bila kunci atau sertifikat punya tanggal kadaluarsa, implementasikan monitoring kadaluarsa otomatis dengan alerting 60 dan 30 hari sebelum expiry. Saat merotasi kunci, uji kunci baru di environment sandbox bank minimal 2 minggu sebelum kunci lama dipensiunkan.
Integrasi Merchant QRIS dan Pembuatan QR Dinamis
Untuk aplikasi yang memerlukan pembuatan QRIS dinamis (jumlah sudah terisi dalam kode QR), gunakan layanan SNAP Generate QR MPM, `/v1.0/qr/qr-mpm-generate`. Response-nya mengembalikan string QR di `qrContent` (atau `qrUrl` maupun `qrImage`), dan field opsional `validityPeriod` di request menentukan kapan kode berhenti berlaku; berapa lama sebuah kode boleh berlaku ditentukan masing-masing provider. Selalu tampilkan nama merchant, jumlah, dan referensi transaksi unik di samping kode QR agar pengguna dapat memverifikasi transaksi sebelum melakukan scan.
Menangani Kode Error SNAP dan Retry Logic
Setiap response code SNAP terdiri dari tujuh digit: HTTP status, service code dua digit, dan case code dua digit. Transfer antarbank memakai service code 18, sehingga `2001800` berarti sukses, `4001801` format field tidak valid (jangan retry), `4091800` X-EXTERNAL-ID yang sudah dipakai pada hari yang sama, `4091801` partnerReferenceNo yang sudah pernah diproses (ambil hasil aslinya), `5001801` internal server error (retry dengan exponential backoff), dan `5041800` timeout dari issuer (query status transaksi sebelum retry). Selalu implementasikan panggilan inquiry status transaksi sebelum memulai retry untuk menghindari transfer duplikat, yang sangat sulit dibalik dalam sistem antarbank Indonesia.
Environment sandbox dan produksi SNAP bukan sekadar base URL yang berbeda — keduanya juga memberlakukan aturan IP whitelisting yang berbeda. IP egress server produksi Anda harus didaftarkan ke tim API gateway setiap bank sebelum go-live. Sandbox sering menggunakan allowlist bersama, tetapi produksi secara ketat menolak IP yang tidak disetujui dengan respons 403. Kegagalan mendaftarkan IP adalah penyebab paling umum keterlambatan peluncuran produksi untuk integrasi SNAP.
Proses Testing dan Sertifikasi
Sebelum terhubung ke environment produksi SNAP sebuah bank, partner menyelesaikan proses pengujian di sandbox bank tersebut, membuktikan implementasi yang benar untuk endpoint yang dipakai, penanganan error yang tepat, perilaku idempotency, dan kontrol keamanan. Lamanya berbeda di tiap bank. Untuk menguji kesesuaian implementasi dengan spesifikasinya sendiri, Developer Site SNAP yang dikelola ASPI sejak 1 September 2023 menyediakan aplikasi pengujian daring bagi pengguna terdaftar.
Penanganan Notifikasi Webhook (Integrasi H2H)
Sebagian besar bank SNAP mendukung notifikasi webhook Host-to-Host (H2H) untuk event penyelesaian transaksi asinkron. Konfigurasi endpoint webhook Anda agar idempoten — notifikasi yang sama mungkin dikirimkan beberapa kali. Akui setiap notifikasi secepatnya dengan HTTP 200 dan response body sesuai spesifikasi bank; batas waktu acknowledgment dan jadwal retry berbeda di tiap bank, jadi ambil dari dokumentasi masing-masing bank alih-alih mengasumsikan satu angka.
Rate Limiting dan Circuit Breaker
Tabel response code SNAP mendefinisikan HTTP 429 Too Many Requests (case code 00) untuk partner yang melampaui batas maksimum transaksi, tetapi batasnya sendiri ditentukan masing-masing provider, jadi tanyakan batas Anda saat onboarding. Implementasikan token bucket rate limiter di layer integrasi Anda untuk memperhalus lonjakan traffic, dan bangun circuit breaker untuk secara otomatis fallback ke channel pembayaran alternatif saat provider SNAP mengalami degradasi.
Integrasikan metrik API SNAP — termasuk kegagalan verifikasi tanda tangan, tingkat timeout, dan distribusi kode error — ke platform observabilitas Anda. Lonjakan tiba-tiba kode berawalan 401 (error otorisasi seperti Invalid Token) sering menandakan masalah refresh token atau rotasi kunci, sementara meningkatnya kode berawalan 504 (timeout dari issuer) dari bank tertentu adalah peringatan dini masalah infrastruktur mereka sebelum pengumuman maintenance resmi.
Checklist Go-Live Produksi
Sebelum go-live dengan integrasi SNAP, verifikasi: alamat IP produksi sudah di-whitelist di semua bank yang diintegrasikan, private key dan client secret disimpan di secrets manager dengan monitoring expiry, endpoint webhook sudah di-deploy dengan logika idempotency dan membalas dalam batas waktu tiap bank, rate limiter dan circuit breaker dikonfigurasi dan diuji, logika fallback inquiry status transaksi diimplementasikan untuk semua endpoint transfer, dan dashboard monitoring Anda sudah live dengan alert untuk ambang batas error rate dan latensi.
Membangun Test Suite Integrasi SNAP
Test suite SNAP yang robust harus mencakup: (1) alur happy-path yang berhasil untuk setiap endpoint; (2) perlindungan replay (X-EXTERNAL-ID yang dipakai ulang pada hari yang sama harus ditolak dengan 409 Conflict, dan partnerReferenceNo yang diulang tidak boleh membuat transaksi kedua); (3) penanganan access token yang kadaluarsa; (4) format X-TIMESTAMP dan toleransi clock skew yang diberlakukan bank Anda; (5) penolakan tanda tangan tidak valid; dan (6) semua kode error SNAP yang ditentukan untuk endpoint yang diintegrasikan. Mock endpoint bank SNAP secara lokal menggunakan tools seperti WireMock atau Mockoon untuk mengaktifkan eksekusi pipeline CI yang cepat tanpa rate limit sandbox.
Istilah kunci dalam artikel ini meliputi SNAP, QRIS, HMAC-SHA512, and PJP.
Artikel Terkait
- DevSecOps: Membangun Pipeline CI/CD yang Aman
- Microservices vs. Monolith: Memilih Arsitektur yang Tepat
Sumber
- Bank Indonesia — PADG 23/15/PADG/2021 tentang Standar Nasional Open API Pembayaran
- Bank Indonesia — Mulai 1 September 2023 Pengelolaan SNAP Dilakukan oleh ASPI
- ASPI SNAP Developer Site — Security standard: access token and signatures
- ASPI SNAP Developer Site — Virtual Account specification and response codes
- ASPI SNAP Developer Site — Interbank transfer specification
- ASPI SNAP Developer Site — QRIS MPM (Generate QR) specification
- Bank Indonesia — QRIS Antarnegara (QRIS Cross-Border)

