Panduan Integrasi

Hubungkan QRISGate ke website Andadalam 30 menit

Panduan langkah demi langkah untuk menerima QRIS dan transfer bank otomatis di toko online Anda. Tidak perlu kontrak payment gateway, tidak perlu tim IT khusus.

Dana langsung ke rekening Anda QRIS + Transfer Bank REST API sederhana

Bagaimana alurnya?

Enam langkah dari checkout pembeli sampai pesanan Anda lunas.

LANGKAH 1

Pembeli checkout

Di website Anda, pembeli klik "Bayar".

LANGKAH 2

Server Anda → API

Backend memanggil POST /api/v1/transactions.

LANGKAH 3

Halaman bayar

Pembeli melihat QRIS atau nomor rekening.

LANGKAH 4

Pembeli bayar

Scan QRIS atau transfer nominal tepat.

LANGKAH 5

Mutasi terdeteksi

Listener membaca notifikasi masuk di HP.

LANGKAH 6

Lunas otomatis

Status PAID + webhook dikirim ke server Anda.

Inti sistemnya: setiap transaksi diberi 3 digit kode unik, jadi nominalnya menjadi unik (mis. Rp 150.247). Saat mutasi masuk dengan nominal itu, sistem tahu persis pesanan mana yang harus dilunasi — tanpa perlu API bank.

Persiapan

Daftar & ambil API Key

sekali saja · ± 2 menit

Buat akun, verifikasi email, lalu buka Dashboard dan salin Live API Key. Kunci ini hanya ditampilkan sekali — simpan di server, jangan pernah di kode frontend.

Daftar sekarang

Tidak ingin menulis kode sendiri? Di Dashboard → Pasang di Website / Toko sudah tersedia prompt siap pakai untuk Cursor, Claude Code, Codex, atau ChatGPT. AI Anda yang akan menulis endpoint checkout, verifikasi webhook, dan halaman status pesanan.

Buka Dashboard

Langkah demi langkah

Empat langkah setelah persiapan. Total waktu ± 28 menit.

01

Pasang sumber pembayaran

± 3 menit

Untuk QRIS: unggah gambar Static QRIS toko Anda di Dashboard. Untuk transfer bank: tambahkan nomor rekening di menu Rekening. Bisa keduanya sekaligus.

Buka Dashboard
02

Aktifkan kanal deteksi mutasi

± 5 menit

Pasang aplikasi Android QRISGate Listener di HP yang menerima notifikasi mutasi, atau hubungkan Moota/Cekmutasi. Tanpa kanal ini, pembayaran tidak akan terdeteksi otomatis.

Unduh APK
03

Buat transaksi dari server

± 10 menit

Panggil POST /api/v1/transactions dari backend Anda saat pembeli checkout. Simpan checkout_url yang dikembalikan, lalu arahkan pembeli ke halaman itu.

Lihat contoh kode
04

Terima notifikasi pembayaran

± 10 menit

Set URL webhook di Dashboard. QRISGate mengirim POST bertanda tangan HMAC saat pembayaran lunas, jadi sistem Anda tidak perlu polling.

Cara verifikasi

Kode integrasi

Pilih bahasa yang Anda pakai. Semua contoh membuat satu transaksi lalu mengarahkan pembeli ke halaman pembayaran.

POST /api/v1/transactions — node
// Node.js 18+ (fetch sudah built-in)
const res = await fetch("https://qriskan.vercel.app/api/v1/transactions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.QRISGATE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    external_order_id: "INV-2026-001", // ID unik pesanan Anda
    amount: 150000,                    // nominal dasar (Rp)
    customer_name: "Budi Santoso",
    payment_method: "QRIS",            // atau "BANK_TRANSFER"
  }),
});

const json = await res.json();
if (!res.ok) throw new Error(json.error);

// Simpan checkout_url, lalu arahkan pembeli ke sana
console.log(json.data.checkout_url);

Parameter yang dikirim

FieldWajibKeterangan
external_order_idYaID pesanan unik dari sistem Anda (idempoten)
amountYaNominal dasar dalam Rupiah, minimal Rp 5.000
payment_methodTidak"QRIS" (default) atau "BANK_TRANSFER"
bank_codeTidakPilih rekening tertentu untuk BANK_TRANSFER (mis. "BCA"). Kosong = rekening aktif pertama
customer_nameTidakNama pembeli, tampil di halaman pembayaran
return_urlTidakHalaman tujuan setelah pembeli selesai membayar

Contoh respons sukses

201 Created
{
  "success": true,
  "data": {
    "transaction_id": "trx_9f2c1a...",
    "external_order_id": "INV-2026-001",
    "payment_method": "QRIS",
    "base_amount": 150000,
    "unique_code": 247,
    "total_amount": 150247,
    "status": "PENDING",
    "qr_string": "00020101021226...",
    "qr_image_base64": "data:image/png;base64,iVBOR...",
    "bank_transfer": null,
    "checkout_url": "https://qriskan.vercel.app/pay/trx_9f2c1a...",
    "expires_at": "2026-10-23T09:15:00.000Z"
  }
}

Arahkan pembeli ke checkout_url — halaman itu sudah menampilkan QRIS atau nomor rekening, countdown, dan berubah otomatis saat lunas. Anda juga bisa memakai qr_image_base64 langsung di halaman checkout Anda sendiri.

Dua metode pembayaran

Pilih per transaksi lewat field payment_method.

QRIS

DEFAULT

Pembeli scan satu QR dengan aplikasi apa pun — GoPay, OVO, DANA, ShopeePay, LinkAja, atau m-Banking.

  • Butuh Static QRIS toko di Dashboard
  • Dana masuk ke rekening QRIS Anda
  • Paling cepat untuk pembeli

Transfer Bank

Pembeli transfer ke rekening bank Anda dengan nominal tepat. Cocok untuk nominal besar atau pembeli yang tidak memakai e-wallet.

  • Butuh rekening terdaftar di menu Rekening
  • BCA, Mandiri, BRI, BNI, dan 12 bank lain
  • Nominal harus tepat, tidak boleh dibulatkan

GoPay hanya mendukung QRIS statis: nominal harus diketik manual oleh pembeli.

Aplikasi GoPay Merchant hanya mengirim notifikasi ke penjual untuk pembayaran QRIS statis. Jika QR memuat nominal (QRIS dinamis), GoPay menganggapnya sebagai transaksi yang belum diaktifkan untuk akun tersebut dan notifikasi tidak pernah muncul — pesanan akan tertahan di status Menunggu. Karena itu, untuk merchant GoPay QRISGate selalu menampilkan QRIS statis dan pembeli mengetik nominal sendiri. Nominal tersebut sudah termasuk kode unik, jadi pastikan pembeli mengetiknya persis. DANA dan kanal lain tetap memakai QRIS dinamis bernominal terkunci.

Contoh: transaksi transfer bank

{
  "external_order_id": "INV-2026-002",
  "amount": 500000,
  "payment_method": "BANK_TRANSFER",
  "bank_code": "BCA"
}

Notifikasi otomatis (webhook)

Supaya sistem Anda tahu pesanan sudah lunas tanpa polling, set URL webhook di Dashboard. Setiap kiriman ditandatangani HMAC-SHA256.

X-QRISGate-Event

payment.paid | payment.expired | payment.cancelled

X-QRISGate-Timestamp

Unix timestamp pengiriman (detik)

X-QRISGate-Signature

HMAC-SHA256 dari timestamp.payload

X-QRISGate-Delivery-Id

Sama untuk setiap retry event ini — kunci idempotensi

X-QRISGate-Attempt

Percobaan pengiriman ke-berapa

Content-Type

application/json

Bentuk body (FLAT — tidak ada wrapper `data`)
{
  "event": "payment.paid",
  "transaction_id": "trx_8f2c4b1a05c67e1f7294b3d0",
  "external_order_id": "INV-1042",
  "base_amount": 150000,
  "unique_code": 247,
  "total_amount": 150247,
  "customer_name": "Budi",
  "paid_at": "2026-10-24T09:15:22.000Z",
  "created_at": "2026-10-24T09:12:40.000Z"
}
Verifikasi signature (PHP)
<?php
// webhook.php — terima notifikasi pembayaran dari QRISGate
$raw = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_QRISGATE_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_QRISGATE_TIMESTAMP'] ?? '';

// 1. Tolak replay di luar 5 menit
if (abs(time() - (int) $timestamp) > 300) {
    http_response_code(400);
    exit('Stale timestamp');
}

// 2. Verifikasi HMAC-SHA256
$expected = hash_hmac('sha256', $timestamp . '.' . $raw, getenv('QRISGATE_WEBHOOK_SECRET'));
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

// 3. Proses event — payload-nya FLAT, tidak ada wrapper `data`.
$event = json_decode($raw, true);

if ($event['event'] === 'payment.paid') {
    $orderId = $event['external_order_id'];
    // TODO: update pesanan Anda menjadi LUNAS
    // Wajib idempoten — event yang sama bisa dikirim ulang.
    // Gunakan X-QRISGate-Delivery-Id untuk membedakan pengiriman ulang.
}

http_response_code(200);
echo 'OK';

Wajib idempoten. Event yang sama bisa dikirim lebih dari sekali (retry). Kunci idempotensi paling aman adalah external_order_id — jangan menambah stok atau saldo dua kali untuk ID yang sama.

Alternatif: cek status manual

Kalau belum siap menerima webhook, polling endpoint status juga bisa.

GET /api/v1/transactions/:id
// Cek status transaksi (polling, tanpa webhook)
const res = await fetch("https://qriskan.vercel.app/api/v1/transactions/trx_abc123");
const { data } = await res.json();

if (data.status === "PAID") {
  // pembayaran sudah lunas
}

Checklist sebelum go-live

Email sudah diverifikasi
Static QRIS sudah diunggah (jika pakai QRIS)
Minimal satu rekening aktif (jika pakai transfer bank)
Aplikasi Listener terpasang & punya akses notifikasi
Battery optimization sudah di-bypass
Sudah masuk dengan akun yang benar di aplikasi Listener
Saldo kredit cukup untuk biaya transaksi
URL webhook sudah diset & bisa diakses publik
Sudah tes 1 transaksi end-to-end
Sudah tes pembayaran nominal salah (harus tetap PENDING)

Pertanyaan umum

Biaya layanan sama dengan kode unik pesanan, antara Rp 100 sampai Rp 999. Kode itu sudah termasuk pada nominal yang dibayar pembeli, jadi uang yang masuk ke rekening Anda tetap sebesar harga jual. Besaran pastinya diacak di dalam rentang itu agar dua pesanan bernominal sama tidak bertabrakan. Tidak ada biaya bulanan dan tidak ada potongan persentase.

Tidak. Cukup unggah Static QRIS toko Anda sekali. QRISGate yang menyuntikkan nominal + kode unik ke payload EMVCo sehingga setiap transaksi punya QR sendiri.

Transaksi tidak akan terdeteksi otomatis karena pencocokan memakai nominal tepat termasuk 3 digit kode unik. Dana tetap masuk ke rekening Anda, dan Anda bisa menyelesaikannya manual lewat tombol konfirmasi di dashboard.

Tidak. Pembayaran QRIS maupun transfer bank masuk langsung ke rekening merchant. QRISGate hanya membaca mutasi untuk mencocokkan status pesanan.

Biasanya kanal mutasi belum aktif atau HP-nya di-freeze sistem (Samsung Freecess). Pastikan aplikasi Listener sudah punya akses notifikasi, sudah di-bypass battery optimization, dan Anda sudah masuk dengan akun yang benar di aplikasi.

Bisa. Tentukan per transaksi lewat field payment_method: "QRIS" atau "BANK_TRANSFER". Kalau tidak diisi, default-nya QRIS.

Siap menerima pembayaran?

Daftar gratis, dapat saldo awal Rp 5.000 untuk menutup biaya transaksi pertama Anda.