Mulai Alur Integrasi Autentikasi Endpoints Status Transaksi Webhook Error Handling Contoh PHP Polling JS
Masuk Dashboard
QRIS Payment Gateway  ·  REST API

Terima Pembayaran
QRIS Lebih Cepat

Integrasikan pembayaran QRIS dinamis ke website kamu dalam hitungan menit. API sederhana, webhook realtime, saldo langsung masuk.

Mulai Sekarang Lihat Dokumentasi
5 mnt
Waktu Integrasi
REST
Standar API
Real-time
Notif Webhook
QRIS
Standar Nasional
Mulai

VitzXPay adalah payment gateway berbasis QRIS yang memungkinkan kamu menerima pembayaran dari semua e-wallet dan mobile banking di Indonesia.

Setup Cepat
Daftar, buat proyek, dapat API Key — siap dalam 5 menit.
QRIS Dinamis
Setiap transaksi punya QR unik dengan nominal tertanam.
Webhook Realtime
Notif instan saat bayar berhasil langsung ke server kamu.
Saldo Otomatis
Saldo merchant langsung masuk begitu pembayaran terverifikasi.
Alur Integrasi

Ikuti 4 langkah berikut untuk mulai menerima pembayaran di website kamu.

01
Daftar & Login
Buat akun di VitzXPay, lalu buat proyek baru di dashboard. Kamu akan mendapatkan API Key unik untuk proyekmu.
02
Buat Transaksi
Dari backend website kamu, kirim POST ke /merchant_api/create.php beserta API Key di header.
03
Tampilkan QR Code
Tampilkan QR kepada pembeli. Polling status tiap beberapa detik atau terima webhook otomatis saat pembayaran masuk.
04
Saldo Masuk Otomatis
Saldo otomatis masuk ke akun VitzXPay begitu pembayaran terverifikasi. Withdraw kapan saja via DANA.
Autentikasi

Semua request ke API harus menyertakan API Key proyekmu di header HTTP.

HTTP Header
X-Api-Key: vitzpay_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API Key bisa dilihat dari halaman Dashboard → Proyek. Jangan pernah expose API Key di sisi client (JavaScript frontend).
Jika API Key bocor, segera hapus proyek dan buat yang baru. Semua request dengan API Key lama langsung ditolak.
Endpoints

VitzXPay menyediakan dua endpoint utama — membuat transaksi dan mengecek statusnya.

POST /merchant_api/create.php Buat transaksi baru

Buat transaksi QRIS baru dan dapatkan QR code dinamis siap tampil ke pembeli.

Request Headers
HeaderValueKeterangan
Content-Type application/json Wajib disertakan
X-Api-Key vitzpay_xxx… API Key proyekmu
Request Body (JSON)
FieldTipeWajibKeterangan
amount integer Wajib Nominal dalam Rupiah, minimum Rp 100
note string Opsional Catatan transaksi, misal nomor order
JSON
{
  "amount": 50000,
  "note": "Order #1023"
}
Response Sukses (200)
JSON
{
  "success": true,
  "trx_id": "TRX172093412345",
  "amount": 50000,
  "note": "Order #1023",
  "qr_url": "https://api.qrserver.com/v1/create-qr-code/?data=...",
  "qris_data": "00020101021226...",
  "expired_at": "2026-01-01T12:15:00",
  "check_url": "https://yourdomain.com/merchant_api/status.php?trx=TRX..."
}
GET /merchant_api/status.php?trx=TRX_ID Cek status transaksi

Cek status pembayaran berdasarkan trx_id yang didapat saat membuat transaksi.

Query Parameter
ParameterTipeKeterangan
trx string TRX ID yang diterima saat create transaksi
Response
JSON
{
  "success": true,
  "trx_id": "TRX172093412345",
  "amount": 50000,
  "status": "paid",
  "note": "Order #1023",
  "paid_at": "2026-01-01 12:08:45",
  "expired_at": "2026-01-01 12:15:00"
}
Status Transaksi

Setiap transaksi memiliki salah satu dari tiga status berikut.

pending
Menunggu pembayaran
paid
Pembayaran berhasil
expired
Transaksi kadaluwarsa
Transaksi yang belum dibayar akan otomatis menjadi expired setelah 15 menit.
Webhook

Atur Webhook URL di dashboard proyekmu. VitzXPay akan otomatis mengirim POST ke URL itu setiap kali pembayaran berhasil — tanpa perlu polling.

Payload yang Dikirim
JSON
{
  "event": "payment.success",
  "trx_id": "TRX172093412345",
  "amount": 50000,
  "note": "Order #1023",
  "paid_at": "2026-01-01 12:08:45"
}
Header yang Disertakan
X-QRPay-Event: payment.success Content-Type: application/json
Pastikan endpoint webhook kamu merespons dengan HTTP 200. Jika tidak, VitzXPay akan retry hingga 3 kali dengan jeda 5 detik.
Error Handling

Semua error dikembalikan dalam format JSON dengan success: false dan pesan error.

HTTP CodePesanPenyebab
401 Invalid API Key API Key salah atau tidak ada di header
400 amount required Field amount tidak dikirim
400 amount minimum Rp 100 Nominal di bawah minimum
404 Transaction not found TRX ID tidak ditemukan
500 Internal Server Error Error di sisi server VitzXPay
Response Error
{
  "success": false,
  "message": "Invalid API Key"
}
Contoh Integrasi PHP

Contoh lengkap dari membuat transaksi, menampilkan QR, hingga menangani webhook di server.

PHP
// ─── 1. Buat Transaksi ────────────────────────────────
$ch = curl_init('https://yourdomain.com/merchant_api/create.php');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'X-Api-Key: vitzpay_xxxxxxxxxxxx'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'amount' => 50000,
        'note'   => 'Order #' . $order_id
    ])
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

// ─── 2. Simpan TRX ID ke database ────────────────────
$trx_id = $result['trx_id'];
$qr_url = $result['qr_url'];

// ─── 3. Tampilkan QR ke customer ─────────────────────
echo '<img src="' . $qr_url . '" alt="QR QRIS" width="250">';

// ─── 4. Terima Webhook (webhook_handler.php) ──────────
$payload = json_decode(file_get_contents('php://input'), true);

if ($payload['event'] === 'payment.success') {
    $trx_id = $payload['trx_id'];
    $amount  = $payload['amount'];

    // UPDATE orders SET status='paid' WHERE trx_id='$trx_id'

    http_response_code(200);
    echo 'OK';
}
Polling Status (JavaScript)

Alternatif webhook — polling status dari frontend untuk update UI secara realtime tanpa reload.

JavaScript
async function pollPaymentStatus(trxId) {
  const url = `/merchant_api/status.php?trx=${trxId}`;

  const interval = setInterval(async () => {
    try {
      const res  = await fetch(url);
      const data = await res.json();

      if (data.status === 'paid') {
        clearInterval(interval);
        showSuccessUI(data);
        notifyServer(data.trx_id);

      } else if (data.status === 'expired') {
        clearInterval(interval);
        showExpiredUI();
      }
    } catch (err) {
      console.error('Polling error:', err);
    }
  }, 3000); // cek tiap 3 detik

  // Batas aman: stop setelah 20 menit
  setTimeout(() => clearInterval(interval), 20 * 60 * 1000);
}

pollPaymentStatus('TRX172093412345');