# Integrasi Pembayaran QRIS Dinamis di Node.js: Panduan Lengkap

> QRIS statis vs dinamis, membuat QR dinamis lewat PSP berlisensi, alur MPM, penanganan webhook, onboarding NMID, dan tarif MDR Oktober 2026 — panduan Node.js praktis.

URL: https://www.matthewswong.com/id/blog/qris-dynamic-payment-integration-nodejs/

- Author: Matthews Wong (https://www.matthewswong.com/id/about/)
- Published: 2026-07-14
- Updated: 2026-10-12
- Category: Backend

> **Key takeaway:** QRIS dinamis menanamkan nominal di QR baru untuk setiap transaksi, dibuat lewat API PSP berlisensi Indonesia dan dikonfirmasi lewat webhook bertanda tangan. Mulai 1 Oktober 2026, Bank Indonesia menetapkan MDR 0 persen sampai Rp100.000 untuk merchant reguler (0,7 persen di atasnya) dan sampai Rp500.000 untuk merchant mikro (0,3 persen di atasnya).

Pada sebuah proyek untuk klien di Indonesia, saya harus menambahkan QRIS ke alur checkout, dan hal pertama yang membingungkan tim adalah menganggap QRIS itu satu jenis saja. Padahal bukan. Ada versi statis yang Anda cetak jadi stiker, dan versi dinamis yang Anda buat langsung dari backend. Untuk apa pun yang menyerupai aplikasi atau toko online, Anda butuh QRIS dinamis, dan artikel ini membahas persis cara membangunnya di Node.js.

QRIS (Quick Response Code Indonesian Standard) adalah standar QR terpadu dari Bank Indonesia: satu QR yang bisa dipindai dan dibayar oleh e-wallet atau aplikasi mobile banking mana pun yang terdaftar (GoPay, OVO, DANA, ShopeePay, aplikasi bank). Sebagai developer, Anda hampir tidak pernah berbicara langsung dengan jaringan QRIS. Anda lewat PSP berlisensi, dan pekerjaan nyata Anda adalah membuat QR, menampilkannya, dan bereaksi terhadap webhook saat uang masuk.

## QRIS statis vs dinamis: mana yang Anda butuhkan?

Perbedaannya penting untuk UX sekaligus rekonsiliasi. Dengan QR statis, pelanggan memindai satu kode cetak Anda dan mengetik nominalnya sendiri — cukup untuk warung, tapi menyulitkan untuk software karena Anda tidak bisa mengaitkan pembayaran ke pesanan tertentu secara andal. QR dinamis dicetak per transaksi dengan nominal terkunci, dan membawa referensi pesanan yang bisa dicocokkan webhook Anda. Berikut perbandingannya.

| Aspek | QRIS statis | QRIS dinamis |
| --- | --- | --- |
| Nominal | Diketik pelanggan secara manual | Tertanam dan terkunci saat dibuat |
| Masa berlaku QR | Satu QR cetak dipakai selamanya | QR baru per transaksi, kedaluwarsa |
| Rekonsiliasi | Manual, sulit mencocokkan pesanan ke pembayaran | Otomatis via order_id di webhook |
| Paling cocok untuk | Warung, kotak tip, volume rendah | Aplikasi, e-commerce, checkout berpesanan |
| Upaya integrasi | Cetak stiker, tanpa kode | Panggilan API plus handler webhook |

## Membuat QRIS dinamis lewat PSP berlisensi

Anda tidak bisa secara legal membuat QRIS sah dari nol. Setiap QR harus memuat NMID asli dan ditandatangani ke jaringan switching nasional Bank Indonesia, yang hanya bisa dilakukan acquirer dan PJSP berlisensi. Jadi arsitekturnya selalu sama: backend Anda memanggil PSP, PSP mengembalikan QR, dan PSP menyelesaikan dana ke rekening Anda dikurangi MDR. Berikut PSP berlisensi yang biasa dipakai developer Indonesia.

- Midtrans (Core API dan Snap) — cakupan e-wallet paling luas, SDK Node.js yang kuat
- Xendit — API rapi, populer di kalangan startup dan fintech
- DOKU — sudah lama berdiri, kuat untuk kebutuhan enterprise dan biller
- API bank langsung (BRI, BCA, Mandiri) — jika Anda sudah menjadi nasabah dan ingin biaya lebih rendah di volume tinggi

## NMID dan onboarding merchant

Sebelum satu QR pun berfungsi, Anda harus di-onboarding sebagai merchant. PSP Anda mengumpulkan dokumen usaha (KTP dan NIK untuk perorangan, NPWP dan akta pendirian untuk perusahaan), memverifikasi legalitas, dan acquirer menerbitkan NMID — National Merchant ID yang tertanam di setiap QR yang Anda tampilkan dan menghubungkan tiap pembayaran ke bisnis Anda di repositori merchant nasional. Lama penerbitannya bergantung pada PSP dan acquirer Anda, jadi tanyakan perkiraan waktunya sebelum menetapkan tanggal peluncuran. Tidak ada yang bisa bertransaksi sampai ini selesai, jadi mulai onboarding lebih awal.

## Alur MPM: membuat QR dinamis di Node.js

QRIS dinamis memakai MPM — Merchant Presented Mode — artinya merchant menampilkan QR dan pelanggan yang memindai (kebalikannya CPM, di mana pelanggan menunjukkan QR aplikasinya ke alat pindai). Alur MPM dalam kode ada tiga langkah: charge, render, konfirmasi. Dengan Midtrans Core API dan SDK Node.js mereka, membuat QR cukup satu panggilan charge dengan payment_type qris.

> Respons charge mengembalikan array actions. Ambil URL action generate-qr-code lalu tampilkan gambarnya, atau tanam string QR di frontend Anda sendiri. Simpan juga transaction_id dan masa berlaku yang Anda tetapkan. QR dinamis akan kedaluwarsa dan setiap penyedia punya default sendiri: panduan GoPay QRIS Midtrans menyebut 15 menit, yang bisa diubah dengan custom_expiry, jadi tetapkan masa berlakunya secara eksplisit atau cek default gateway Anda, lalu tampilkan hitung mundur dan tombol regenerate daripada QR yang mati diam-diam.

## Menangani callback/webhook pembayaran

Di sinilah kebanyakan integrasi diam-diam rusak. Aplikasi pelanggan bilang lunas, tapi backend Anda baru benar-benar tahu ketika PSP mengirim webhook ke notification URL Anda. Atur URL itu di dashboard PSP, siapkan endpoint HTTPS publik, dan — yang paling penting — verifikasi signature sebelum mempercayai apa pun. Midtrans menandatangani tiap notifikasi sebagai hash SHA-512 dari order_id, status_code, gross_amount, dan server key Anda. Identitas QR yang dibayar datang sebagai merchant_cross_reference_id.

> Jangan pernah menandai pesanan lunas dari frontend atau redirect — keduanya bisa dipalsukan penyerang. Percayai hanya webhook yang signature key-nya cocok dengan hash yang Anda hitung ulang, dan buat handler-nya idempoten: PSP melakukan retry, jadi settlement yang sama bisa datang beberapa kali. Balas 200 dengan cepat dan kerjakan proses berat secara asinkron, kalau tidak PSP terus retry dan menggandakan efek samping Anda.

## Struktur biaya MDR

Terakhir, soal uang. MDR (Merchant Discount Rate) adalah biaya yang dipotong PSP dari tiap settlement — Anda menerima nominal kotor dikurangi MDR. Bank Indonesia menetapkan tarifnya, dan aturannya berubah lagi pada 1 Oktober 2026, saat MDR 0% diperluas ke merchant kecil, menengah, dan besar untuk transaksi sampai Rp 100.000. Tabel BI juga menetapkan tarif khusus 0,6% untuk pendidikan dan 0,4% untuk SPBU, yang tidak disebut terpisah dalam siaran pers BI Agustus 2026. Verifikasi angka terkini ke Bank Indonesia sebelum mengutipnya ke klien, karena ini didorong kebijakan dan bisa berubah. Sejak 1 Oktober 2026:

| Kategori merchant | MDR (sejak 1 Okt 2026) |
| --- | --- |
| Mikro (UMI), transaksi sampai Rp 500.000 | 0% (gratis) |
| Mikro (UMI), transaksi di atas Rp 500.000 | 0,3% |
| Kecil, menengah, besar (UKE, UME, UBE) | 0% sampai Rp 100.000; 0,7% di atasnya |
| Layanan publik, G2P, P2G, donasi | 0% |

> Dua catatan praktis: MDR secara hukum ditanggung merchant dan tidak boleh dibebankan sebagai surcharge ke pelanggan, jadi masukkan ke margin Anda, bukan total checkout. Dan bangun rekonsiliasi dengan asumsi settlement bersih — catat gross_amount dari webhook, kurangi tier MDR, dan cocokkan dengan yang benar-benar masuk ke rekening agar selisih 0,7 persen tidak terlihat seperti pembayaran hilang.

## Sources

- Bank Indonesia — Merchant Discount Rate (MDR) QRIS
- Midtrans Docs — QRIS Core API charge reference
- Midtrans Docs — HTTP(S) Notification / Webhooks
- Bank Indonesia (BICARA 131) — Identifying a QRIS issuer via the NSS code / NMID
- Midtrans Docs — Integrasi GoPay QRIS POS (masa berlaku default dan custom_expiry)

## Source links

- https://www.bi.go.id/id/publikasi/ruang-media/cerita-bi/Pages/mdr-qris.aspx
- https://docs.midtrans.com/reference/qris
- https://docs.midtrans.com/docs/https-notification-webhooks
- https://bicara131.bi.go.id/knowledgebase/article/KA-01154/en-us
- https://docs.midtrans.com/docs/gopay-qris-pos-integration

## FAQ

### Apa perbedaan QRIS statis dan dinamis?

QRIS statis adalah satu QR cetak yang dipindai semua pelanggan lalu nominalnya diketik manual. QRIS dinamis dibuat per transaksi dengan nominal yang sudah tertanam, jadi pelanggan tinggal konfirmasi dan bayar. QRIS dinamis juga memungkinkan backend Anda merekonsiliasi setiap pembayaran otomatis berdasarkan order ID.

### Bisakah saya membuat QRIS dinamis sendiri tanpa payment provider?

Praktis tidak bisa. QR QRIS harus memuat NMID sah yang diterbitkan acquirer atau PJSP berlisensi Bank Indonesia, dan QR-nya harus ditandatangani ke jaringan switching nasional. Anda membuat QRIS dinamis dengan memanggil API PSP berlisensi seperti Midtrans, Xendit, atau DOKU, yang mengurus NMID dan settlement untuk Anda.

### Berapa tarif MDR QRIS di 2026?

Mulai 1 Oktober 2026, Bank Indonesia menetapkan MDR QRIS 0 persen untuk transaksi sampai Rp 100.000 di merchant kecil, menengah, dan besar, dan 0,7 persen di atasnya. Merchant mikro dikenai 0 persen sampai Rp 500.000 dan 0,3 persen di atasnya. Pendidikan 0,6 persen dan SPBU 0,4 persen, sedangkan kategori layanan publik, pemerintah, dan donasi 0 persen. Biaya ini ditanggung merchant dan tidak boleh dibebankan ke pelanggan.

### Bagaimana cara memastikan pembayaran QRIS benar-benar berhasil?

Anda memastikannya lewat webhook (HTTP notification) yang dikirim PSP ke server Anda saat status berubah menjadi settlement. Selalu verifikasi signature key sebelum mempercayainya, dan jangan mengandalkan layar pelanggan atau frontend saja. Jadikan webhook sebagai satu-satunya sumber kebenaran dan buat handler-nya idempoten.

### Apa itu NMID dalam QRIS?

NMID (National Merchant ID) adalah identitas merchant unik yang diterbitkan acquirer dan tertanam di setiap QRIS yang Anda tampilkan. NMID menghubungkan tiap transaksi ke bisnis Anda yang terdaftar di repositori merchant nasional Bank Indonesia. Saat integrasi lewat PSP, NMID disediakan pada proses onboarding merchant, dan lamanya bergantung pada PSP dan acquirer Anda, jadi tanyakan sebelum menetapkan tanggal peluncuran.

---

- HTML version: https://www.matthewswong.com/id/blog/qris-dynamic-payment-integration-nodejs/
- English: https://www.matthewswong.com/en/blog/qris-dynamic-payment-integration-nodejs/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
