Payment Gateway QRIS API

Dokumentasi resmi REST API VPay untuk integrasi pembayaran QRIS dinamis secara real-time ke sistem Anda.

Base URL: https://vitopediapay.com/api

API Key Unik

Autentikasi aman per merchant dengan Bearer Token.

QRIS Dinamis

Generate QR code unik per transaksi instant.

Saldo Real-time

Dana masuk hitungan detik, cek saldo kapan saja.

Autentikasi

Setiap request ke API VPay memerlukan API Key yang dikirim melalui HTTP Header Authorization.

Peringatan Keamanan: Jangan pernah mengekspos API Key Anda di frontend (browser, aplikasi mobile client-side). Lakukan request API hanya dari server backend Anda.
Authorization: Bearer YOUR_API_KEY_HERE

Cara Mulai

  1. Daftar akun di Portal Merchant VPay.
  2. Dapatkan API Key di halaman Dashboard.
  3. Integrasikan endpoint /api/pg/create untuk membuat QRIS pembayaran.
  4. Tampilkan qr_image (URL gambar) ke user Anda.
  5. Cek status pembayaran berkala via /api/pg/check/:id (polling) atau gunakan Webhook (coming soon).
  6. Jika status paid, berikan layanan/produk ke user Anda.

Buat QRIS

POST /api/pg/create

Membuat tagihan baru dan menghasilkan QRIS statis berbentuk gambar.

Request Body (JSON)

FieldTypeWajibDeskripsi
amountintegerYaNominal pembayaran (min: 1000)
ref_idstringTidakID referensi sistem Anda (max 50 char)

Response Sukses (200 OK)

{
  "success": true,
  "data": {
    "id": "pg_abc123xyz",
    "amount": 50000,
    "unique_code": 45,
    "total": 50045,
    "qr_image": "https://VPay.id/qr/pg_abc123xyz.png",
    "status": "pending",
    "created_at": "2024-03-10T10:00:00Z"
  }
}

Cek Status

GET /api/pg/check/:id

Mengecek status pembayaran berdasarkan ID transaksi.

Response (Belum Bayar)

{
  "success": true,
  "data": {
    "id": "pg_abc123xyz",
    "status": "pending",
    "total": 50045
  }
}

Response (Sudah Bayar)

{
  "success": true,
  "data": {
    "id": "pg_abc123xyz",
    "status": "paid",
    "total": 50045,
    "paid_at": "2024-03-10T10:05:12Z",
    "available_at": "2024-03-10T10:05:12Z"
  }
}

Riwayat Transaksi

GET /api/pg/history

Mendapatkan daftar 50 transaksi terakhir.

{
  "success": true,
  "data": [
    {
      "id": "pg_abc123xyz",
      "amount": 50000,
      "status": "paid",
      "created_at": "..."
    },
    // ...
  ]
}

Tabel Status

StatusDeskripsi
pendingMenunggu pembayaran dari user. QRIS masih aktif.
paidPembayaran berhasil diterima. Dana sudah ditambahkan ke saldo.
expiredWaktu pembayaran habis (default 24 jam).

Perhitungan Fee

VPay menggunakan model pricing transparan:

Contoh Kalkulasi

Amount yang direquest: Rp 100.000
Kode unik (random)   : Rp 23
Total tagihan user   : Rp 100.023

Perhitungan Fee:
Flat fee       : Rp 100
MDR (0.3%)     : Rp 300 (dari 100.000)
Total Fee      : Rp 400

Saldo Masuk ke Merchant:
= Total Tagihan - Total Fee
= 100.023 - 400
= Rp 99.623

List Produk

GET /api/products

Mendapatkan daftar produk yang tersedia di Toko App, dikelompokkan berdasarkan kategori.

{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "Layanan Premium",
      "icon": "📦",
      "products": [
        {
          "id": 1,
          "name": "Netflix Premium 1 Bulan",
          "price": 35000,
          "stock": 10
        }
      ]
    }
  ]
}

Beli Produk

POST /api/products/buy

Membeli produk dari Toko App menggunakan saldo merchant.

FieldTypeWajibDeskripsi
product_idintegerYaID produk yang ingin dibeli
qtyintegerTidakJumlah produk (default 1)

Response Sukses

{
  "success": true,
  "data": {
    "order_id": 12,
    "product_name": "Netflix Premium 1 Bulan",
    "amount": 35000,
    "license_keys": ["VITO-XXXX-XXXX-XXXX"],
    "balance_remaining": 115000
  }
}

Info Akun

GET /api/merchant/me
{
  "success": true,
  "data": {
    "merchant_name": "Toko Online Budi",
    "balance": 1500000,
    "pending_balance": 0,
    "api_key": "vito_live_xxxxxxxx..."
  }
}

Statistik

GET /api/merchant/stats
{
  "success": true,
  "data": {
    "total_transactions": 145,
    "success_rate": "92.5%",
    "revenue_today": 450000
  }
}

Tarik Saldo

POST /api/merchant/withdraw
FieldTypeDeskripsi
amountintegerNominal penarikan (min 50.000)
methodstringKode bank (cth: BCA, MANDIRI, BRI, BNI, GOPAY, OVO, DANA)
account_namestringNama pemilik rekening
account_numberstringNomor rekening / e-wallet

Node.js Example

const fetch = require('node-fetch');

const API_KEY = 'vito_live_YOUR_KEY';
const BASE_URL = 'https://vitopediapay.com/api';

async function createQRIS() {
    // 1. Create Transaction
    const response = await fetch(`${BASE_URL}/pg/create`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${API_KEY}`
        },
        body: JSON.stringify({ amount: 50000, ref_id: 'ORDER-123' })
    });
    const result = await response.json();
    
    if(!result.success) return console.error(result.message);
    console.log('QRIS URL:', result.data.qr_image);

    // 2. Poll Status every 5 seconds
    const interval = setInterval(async () => {
        const checkRes = await fetch(`${BASE_URL}/pg/check/${result.data.id}`, {
            headers: { 'Authorization': `Bearer ${API_KEY}` }
        });
        const checkData = await checkRes.json();
        
        if(checkData.data.status === 'paid') {
            console.log('Payment Received!');
            clearInterval(interval);
        }
    }, 5000);
}

Python Example

import requests
import time

API_KEY = 'vito_live_YOUR_KEY'
BASE_URL = 'https://vitopediapay.com/api'
headers = {'Authorization': f'Bearer {API_KEY}'}

# Create
res = requests.post(f'{BASE_URL}/pg/create', json={'amount': 50000}, headers=headers)
data = res.json()

if data.get('success'):
    txn_id = data['data']['id']
    print(f"QR Code URL: {data['data']['qr_image']}")
    
    # Check
    while True:
        check = requests.get(f'{BASE_URL}/pg/check/{txn_id}', headers=headers).json()
        if check['data']['status'] == 'paid':
            print("Paid successfully!")
            break
        time.sleep(5)

PHP Example

<?php
$api_key = 'vito_live_YOUR_KEY';

$ch = curl_init('https://vitopediapay.com/api/pg/create');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['amount' => 50000]),
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $api_key
    ]
]);

$response = json_decode(curl_exec($ch), true);
if($response['success']) {
    echo "Scan URL: " . $response['data']['qr_image'];
}
?>

cURL Examples

Create QRIS

curl -X POST https://vitopediapay.com/api/pg/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 50000}'

Check Status

curl -X GET https://vitopediapay.com/api/pg/check/pg_abc123xyz \
  -H "Authorization: Bearer YOUR_API_KEY"

History

curl -X GET https://vitopediapay.com/api/pg/history \
  -H "Authorization: Bearer YOUR_API_KEY"

Withdraw

curl -X POST https://vitopediapay.com/api/merchant/withdraw \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":100000, "method":"BCA", "account_name":"BUDI", "account_number":"1234567890"}'

Error & HTTP Status

HTTP StatusDeskripsiPenyebab Umum
401 UnauthorizedAkses DitolakAPI Key salah, kosong, atau format Bearer tidak sesuai.
400 Bad RequestFormat SalahAmount kurang dari minimal, tipe data salah.
404 Not FoundData Tidak DitemukanID Transaksi tidak valid saat cek status.
402 Payment RequiredSaldo Tidak CukupSaat melakukan penarikan (withdraw).
500 Internal ErrorGangguan ServerKesalahan di sistem VPay. Silakan coba lagi.

Binance Pay USDT

VitopediaPay mendukung pembayaran USDT via Binance Pay. Customer mengirim USDT langsung ke Binance Pay ID merchant, sistem otomatis mendeteksi dan memverifikasi pembayaran.

⚡ Keunggulan Binance Pay:
  • Fee jaringan 0% (gratis) antar pengguna Binance
  • Konfirmasi instan (tanpa on-chain)
  • Customer cukup scan QR atau masukkan Pay ID
  • Deteksi otomatis setiap 60 detik oleh sistem
  • Tidak perlu wallet address — cukup Binance Pay ID
ParameterNilai
JaringanBinance Pay (P2P Internal)
TokenUSDT (Tether)
KursReal-time dari Binance
Masa Berlaku2 jam per payment
DeteksiOtomatis setiap 60 detik
MinimumRp 10.000

Buat Payment Binance Pay

Endpoint untuk membuat permintaan pembayaran USDT baru via Binance Pay.

POST /api/usdt/request

Request Headers

HeaderWajibKeterangan
AuthorizationBearer <api_key> dari dashboard
Content-Typeapplication/json

Request Body

FieldTipeWajibKeterangan
idr_amountintegerNominal IDR (min 10.000)

Contoh Request

curl -X POST https://vitopediapay.com/api/usdt/request \
  -H "Authorization: Bearer vp_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"idr_amount":50000}'

Response Sukses

{
  "success": true,
  "data": {
    "id": 42,
    "usdt_amount": "3.031298",
    "idr_amount": 50000,
    "usdt_rate": 16500,
    "binance_pay_id": "1269823812",
    "address": "1269823812",
    "status": "pending",
    "expires_at": "2024-08-18T06:00:00.000Z"
  }
}
⚠️ Penting: Customer harus mengirim USDT dengan jumlah TEPAT sesuai usdt_amount. Jumlah mengandung kode unik untuk matching otomatis.

Biaya Layanan (Fee)

KomponenNilaiKeterangan
Fee FlatRp 100Per transaksi
Fee Persen0,3%Dari nominal IDR
Total FeeRp 100 + 0,3% × nominalDipotong otomatis dari saldo merchant

Contoh: Deposit Rp 50.000 → fee = Rp 100 + Rp 150 = Rp 250 → merchant terima Rp 49.750

Cek Status Payment

Gunakan endpoint ini untuk polling status pembayaran setelah customer melakukan transfer.

GET /api/usdt/status/:id

Request Headers

HeaderWajibKeterangan
AuthorizationBearer <api_key>

Contoh Request

curl https://vitopediapay.com/api/usdt/status/42 \
  -H "Authorization: Bearer vp_YOUR_API_KEY"

Response

{
  "success": true,
  "data": {
    "id": 42,
    "status": "completed",
    "usdt_amount": "3.031298",
    "idr_amount": 50000,
    "tx_hash": "P_A23U3MQA69D71119",
    "completed_at": "2024-08-18T04:05:22.000Z"
  }
}
StatusKeterangan
pendingMenunggu transfer dari customer
completedPembayaran berhasil terdeteksi
expiredWaktu habis (2 jam), buat request baru

Alur Integrasi

Berikut alur lengkap integrasi Binance Pay di sistem kamu:

// 1. Buat payment request
const res = await fetch('https://vitopediapay.com/api/usdt/request', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer vp_YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ idr_amount: 50000 })
});
const { data } = await res.json();

// 2. Tampilkan ke customer
console.log('Binance Pay ID:', data.binance_pay_id); // 1269823812
console.log('Kirim USDT (TEPAT):', data.usdt_amount); // 3.031298
console.log('Berlaku sampai:', data.expires_at);

// 3. Polling status (setiap 10 detik)
const depositId = data.id;
const poll = setInterval(async () => {
  const statusRes = await fetch(
    `https://vitopediapay.com/api/usdt/status/${depositId}`,
    { headers: { 'Authorization': 'Bearer vp_YOUR_API_KEY' } }
  );
  const { data: s } = await statusRes.json();

  if (s.status === 'completed') {
    clearInterval(poll);
    console.log('Pembayaran berhasil! Proses order...');
    // proses order / kirim produk
  } else if (s.status === 'expired') {
    clearInterval(poll);
    console.log('Payment expired, minta customer buat ulang');
  }
}, 10000);

Implementasi Telegram Bot (Node.js)

// Buat request Binance Pay
const res = await fetch('https://vitopediapay.com/api/usdt/request', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer ' + vpay_key, 'Content-Type': 'application/json' },
  body: JSON.stringify({ idr_amount: total_harga })
});
const { data } = await res.json();

// Kirim instruksi ke user
await bot.sendMessage(chat_id,
  `💜 Pembayaran Via Binance Pay\n\n` +
  `Binance Pay ID: ${data.binance_pay_id}\n` +
  `Jumlah USDT (TEPAT): ${data.usdt_amount}\n\n` +
  `Berlaku 2 jam`
);

// Cek status setelah user konfirmasi
const statusRes = await fetch(
  `https://vitopediapay.com/api/usdt/status/${data.id}`,
  { headers: { 'Authorization': 'Bearer ' + vpay_key } }
);
const status = await statusRes.json();
if (status.data.status === 'completed') {
  // kirim produk ke user
}