2026-06-10 · 7 min
QRIS Payment di SaaS Jakarta: Snap vs Direct Integration
Klien SaaS subscription Jakarta saya (B2B, ~600 paying tenant, MRR Rp 180jt) request QRIS sebagai alternative bank transfer 5 bulan lalu. Saya pilihan: Midtrans Snap (jalur cepat, MDR sedikit lebih mahal) atau direct integration ke acquirer (lebih murah, effort lebih). Saya try Snap dulu, lalu evaluate. Hasil real.
Setup awal: Midtrans Snap
Decision driver: ship dulu, optimize belakangan. Klien butuh QRIS live dalam 3 minggu.
Implementation:
- Backend: webhook receiver di Bun + Hono (related: Bun 1.3 di payment gateway warung)
- Frontend: Snap.js embed di Next.js
- Reconciliation: cronjob nightly compare Midtrans report vs internal ledger
Effort: 4 hari. Saya billed Rp 16jt ke klien.
Yang Snap kasih:
- QRIS dynamic (per-transaksi)
- E-wallet (GoPay, ShopeePay, DANA, OVO)
- Bank transfer virtual account
- Card payment
Semua dalam satu integration. Klien tidak ribet daftar acquirer terpisah.
Cost: Midtrans Snap 5 bulan pertama
Volume transaksi: ~2,400 transaksi/bulan, average Rp 480k/transaksi (subscription monthly + annual).
Total volume bulanan: Rp 1,15 miliar.
Midtrans Snap MDR untuk QRIS: 0,77% (per 2026 rate card) Per transaksi avg fee: ~Rp 3,700 Monthly fee total: ~Rp 8,9jt
Plus Midtrans monthly minimum (saat itu Rp 0 untuk volume ini, tapi ada flat fee untuk Snap dashboard akses): Rp 200k/mo.
Total Midtrans cost: ~Rp 9,1jt/bulan
Latency Snap
Customer flow: click “bayar QRIS” → Snap popup → scan QR → payment app process → webhook ke server saya.
- Snap popup load: P50 1,2 detik, P95 2,8 detik (depend on Indihome/Telkomsel client side)
- QR generation: P50 1,8 detik (Snap call ke acquirer)
- Webhook notification: P50 12 detik setelah user bayar (acquirer → Midtrans → my server)
Total time-to-confirmation user: median ~25 detik. Acceptable. Kompetitor saya yang langsung ke acquirer claim ~15 detik, tapi belum saya verify.
Decision: try direct integration
Setelah 4 bulan Snap, klien tanya: “bisa lebih murah?”. Volume sudah lumayan. Saya assess:
Direct integration ke acquirer (saya coba: BCA QRIS Merchant API):
- MDR: 0,3% (cap BI untuk UMKM) — tapi klien bukan UMKM, jadi 0,7%
- Setup fee BCA: Rp 5jt one-time
- Monthly fee: Rp 350k untuk corporate account
- Settlement: T+1 ke rekening BCA
Saya prototype 2 minggu (parallel project). Effort lebih besar:
- BCA punya proprietary API yang dokumentasi-nya bisa diakses setelah onboarding
- Webhook signing pakai HMAC, bukan setarakan Snap
- Reconciliation file daily harus parse fixed-width format (lama-lama era)
- Tidak ada SDK official untuk Node/Bun; saya nulis client dari scratch
Total effort prototype + production-ready: 14 hari. Billed Rp 56jt ke klien.
Cost: direct integration 1 bulan running
Bulan ke-5 saya cutover 50% traffic ke direct BCA. Result:
- Volume direct: Rp 575jt
- MDR direct: 0,7% = Rp 4jt
- Plus BCA monthly: Rp 350k
- Cost: Rp 4,35jt untuk 50% volume
Proyeksi full direct: Rp 8,7jt/bulan untuk 100% volume.
Saving vs Midtrans: Rp 9,1jt - 8,7jt = Rp 400k/bulan saving.
Hmm. Tidak signifikan. Break-even setup cost (Rp 56jt) di 140 bulan. Tidak masuk akal.
Reality check
Saya kasih klien data ini. Klien marah sebentar (sudah bayar Rp 56jt prototype), tapi paham. Keputusan: keep Midtrans Snap untuk most flow, BCA direct untuk B2B annual subscription (high-ticket, Rp 5jt+) where MDR saving lebih material.
Hybrid pattern:
- Snap untuk transaksi < Rp 1jt: kemudahan + UX > saving
- BCA direct untuk transaksi > Rp 5jt: 0,7% dari Rp 5jt = Rp 35k saving per transaksi, worth-it
Yang break (Snap)
-
Webhook delivery delay: 2x dalam 5 bulan Midtrans webhook delay > 1 jam. User udah bayar, status di app pending. Customer support kena. Fix: tambah polling /v2/{order-id}/status setiap 30 detik sebagai backup.
-
Snap popup blocked: 4 customer report popup di-block browser. Sebelum bayar mereka harus allow popup. Fix: kasih instruksi UI sebelum click “bayar”.
-
Currency precision: Snap kirim amount as integer (cents-style). Saya pernah salah convert dan amount Rp 478,500 jadi Rp 47,850. Test case yang gak ketangkap. Customer marah, saya refund + apology.
Yang break (BCA direct)
-
Settlement format: file rekonsiliasi harian dari BCA pakai EBCDIC-encoded fixed-width. Saya butuh parse khusus. Bug pertama: tanggal misalign 1 kolom. Manual reconcile 3 hari sampai fix.
-
HMAC signature: saya salah pakai SHA-256 hex lowercase vs uppercase. Webhook saya validate gagal 100% selama 2 hari. Beruntung BCA retry webhook sampai 3x.
-
Maintenance window: BCA punya maintenance Minggu 02:00-04:00 WIB. User yang bayar saat itu, QR expired silent. Saya tambah fallback ke Snap untuk window itu.
Verdict
Untuk SaaS Indonesia dengan volume < Rp 2 milyar/bulan: pakai aggregator (Midtrans, Xendit, Doku). Engineering cost saving > MDR saving.
Direct integration ke acquirer make sense kalau:
- Volume > Rp 5 milyar/bulan
- Punya tim engineering dedicated untuk maintain integration
- Klien dengan transaksi high-ticket (B2B enterprise)
Bukan magic — saya buang effort Rp 56jt untuk discover ini. Kasih ke developer Indonesia lain supaya ga ulang mistake. Data dulu, bukan asumsi vendor selalu paling mahal.
Ditulis oleh Reza Pradipta