MULAI DARI SINI

Panduan Pemula

Belum pernah pakai payment gateway sebelumnya? Tenang, panduan ini menjelaskan dari nol dengan bahasa yang simpel.

Apa itu XentralPay?

XentralPay adalah layanan yang membantu Anda menerima pembayaran QRIS secara otomatis di aplikasi, bot Telegram, website, atau sistem apapun yang Anda bangun.

Tanpa XentralPay, Anda harus cek pembayaran manual. Dengan XentralPay, sistem otomatis memberi tahu Anda saat pelanggan sudah bayar.

Langkah-langkah dari Awal

1
Daftar Akun

Buka halaman pendaftaran. Isi nama, email, dan Telegram ID. Kode verifikasi dikirim via bot @xentralpaybot di Telegram.

2
Login dan Buat Project

Setelah akun terverifikasi, login ke dashboard. Klik menu Project, lalu klik "+ Project Baru". Isi nama project (contoh: "Toko Online Saya").

3
Simpan API Key

Setelah project dibuat, Anda akan mendapatkan API Key (kode panjang yang dimulai dengan cpay_live_). Simpan baik-baik! API Key ini hanya ditampilkan sekali dan tidak bisa dilihat lagi.

4
Buat Pembayaran QRIS

Kirim request ke API XentralPay dengan nominal pembayaran. Anda akan mendapatkan QR code dan link checkout yang bisa langsung dikirim ke pelanggan.

5
Pelanggan Bayar, Anda Dapat Notifikasi

Pelanggan scan QR atau buka link checkout. Setelah bayar, XentralPay otomatis mengirim notifikasi (webhook) ke server Anda. Atau Anda bisa cek status manual lewat API.

lightbulb

Tidak punya server? Anda tetap bisa pakai XentralPay! Gunakan checkout_url dari response API — itu adalah halaman pembayaran siap pakai yang otomatis menampilkan QR code, countdown timer, dan status pembayaran.

PANDUAN CEPAT

Quick Start

Integrasikan XentralPay ke aplikasi Anda dalam hitungan menit. REST API standar, response JSON. Tidak memerlukan SDK khusus.

1

Buat Project

Daftar di dashboard, buat project baru, dan salin API key yang dihasilkan.

2

Panggil API

Kirim POST ke /v1/qris/generate dengan nominal pembayaran.

3

Tampilkan QR

Render qr_content jadi gambar QR, atau arahkan pelanggan ke checkout_url.

4

Terima Webhook

Webhook dikirim otomatis saat pembayaran berhasil. Ditandatangani HMAC-SHA256 untuk keamanan.

CONTOH NYATA

Contoh Integrasi Lengkap

Contoh alur lengkap dari membuat pembayaran sampai menerima notifikasi. Copy-paste dan sesuaikan.

Skenario: User beli produk Rp 50.000
// ═══ LANGKAH 1: User klik "Bayar" di app kamu ═══ const API_KEY = 'cpay_live_xxxxxx'; // dari dashboard > project // Buat pembayaran QRIS const response = await fetch('https://api.xentralpay.com/v1/qris/generate', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 50000, // nominal Rp 50.000 order_id: 'ORDER-123', // ID dari sistem kamu (opsional) callback_url: 'https://app-kamu.com/webhook' // URL webhook (opsional) }) }); const result = await response.json(); // ═══ LANGKAH 2: Tampilkan ke user ═══ // Opsi A: Redirect user ke halaman checkout XentralPay console.log(result.data.checkout_url); // Output: https://xentralpay.com/pay/ORDER-123 // User tinggal buka link ini, scan QR, bayar. Selesai. // Opsi B: Tampilkan QR code sendiri di app kamu console.log(result.data.qr_image_url); // Output: https://xentralpay.com/pay/qr-image/ORDER-123 // Pakai sebagai src di tag <img> // ═══ LANGKAH 3: Terima webhook saat user bayar ═══ // Di server kamu, buat endpoint POST /webhook const crypto = require('crypto'); app.post('/webhook', (req, res) => { // Verifikasi signature (penting!) const timestamp = req.headers['x-xentralpay-timestamp']; const signature = req.headers['x-xentralpay-signature']; const expected = crypto .createHmac('sha256', 'WEBHOOK_SECRET_KAMU') .update(timestamp + '.' + JSON.stringify(req.body)) .digest('hex'); if (signature !== expected) return res.status(401).end(); // Proses pembayaran const { data } = req.body; if (data.status === 'settlement') { console.log(`Order ${data.order_id} LUNAS!`); console.log(`Diterima: Rp ${data.net_amount}`); // Update database kamu: tandai order sebagai "paid" // Kirim produk ke user } res.json({ received: true }); });
// ═══ LANGKAH 1: User klik "Bayar" ═══ $API_KEY = 'cpay_live_xxxxxx'; $ch = curl_init('https://api.xentralpay.com/v1/qris/generate'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $API_KEY, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'amount' => 50000, 'order_id' => 'ORDER-123', 'callback_url' => 'https://app-kamu.com/webhook' ])); $response = json_decode(curl_exec($ch), true); // ═══ LANGKAH 2: Redirect user ke checkout ═══ $checkout_url = $response['data']['checkout_url']; header("Location: $checkout_url"); // Atau tampilkan QR: <img src="$response['data']['qr_image_url']"> // ═══ LANGKAH 3: Terima webhook (file terpisah: webhook.php) ═══ $payload = file_get_contents('php://input'); $timestamp = $_SERVER['HTTP_X_XENTRALPAY_TIMESTAMP'] ?? ''; $signature = $_SERVER['HTTP_X_XENTRALPAY_SIGNATURE'] ?? ''; $expected = hash_hmac('sha256', $timestamp . '.' . $payload, 'WEBHOOK_SECRET_KAMU'); if (!hash_equals($expected, $signature)) { http_response_code(401); exit; } $event = json_decode($payload, true); if ($event['data']['status'] === 'settlement') { $order_id = $event['data']['order_id']; $net = $event['data']['net_amount']; // Update database: UPDATE orders SET paid=1 WHERE id='$order_id' } echo json_encode(['received' => true]);
import requests, hmac, hashlib, json from flask import Flask, request API_KEY = 'cpay_live_xxxxxx' WEBHOOK_SECRET = 'WEBHOOK_SECRET_KAMU' app = Flask(__name__) # ═══ LANGKAH 1: User klik "Bayar" ═══ def create_payment(amount, order_id): response = requests.post( "https://api.xentralpay.com/v1/qris/generate", headers={"Authorization": f"Bearer {API_KEY}"}, json={ "amount": amount, "order_id": order_id, "callback_url": "https://app-kamu.com/webhook" } ) data = response.json()["data"] # Redirect user ke checkout: print(f"Checkout: {data['checkout_url']}") # Atau tampilkan QR: print(f"QR Image: {data['qr_image_url']}") return data # ═══ LANGKAH 3: Terima webhook ═══ @app.route("/webhook", methods=["POST"]) def webhook(): timestamp = request.headers.get("X-XentralPay-Timestamp", "") signature = request.headers.get("X-XentralPay-Signature", "") expected = hmac.new( WEBHOOK_SECRET.encode(), (timestamp + "." + request.data.decode()).encode(), hashlib.sha256 ).hexdigest() if not hmac.compare_digest(expected, signature): return "", 401 event = request.get_json() if event["data"]["status"] == "settlement": order_id = event["data"]["order_id"] net = event["data"]["net_amount"] print(f"Order {order_id} LUNAS! Diterima: Rp {net}") # Update database return {"received": True}
tips_and_updates

Cara paling mudah: Kalau kamu nggak punya server untuk terima webhook, cukup pakai checkout_url dan polling /v1/qris/status setiap beberapa detik untuk cek apakah sudah bayar.

calculate Fee Mode

Setiap project bisa memilih siapa yang menanggung fee transaksi.

store Mode: Merchant

Fee dipotong dari saldo merchant. Pelanggan bayar nominal asli.

Harga produk:Rp 100.000
Pelanggan bayar:Rp 100.000
Fee (0.7% + 200):- Rp 900
Merchant terima:Rp 99.100
person Mode: Buyer

Fee ditambahkan ke nominal. Merchant terima full harga produk.

Harga produk:Rp 100.000
Fee (0.7% + 200):+ Rp 900
Pelanggan bayar:Rp 100.900
Merchant terima:Rp 100.000
settings

Fee mode bisa diatur per project di menu Project > Edit di dashboard. Besaran fee (persentase + flat) diatur oleh admin dan berlaku untuk semua merchant.

dns Base URL

Semua endpoint API menggunakan base URL berikut:

https://api.xentralpay.com
info

Untuk halaman checkout dan dashboard, gunakan https://xentralpay.com. Base URL API khusus untuk pemanggilan endpoint.

lock Autentikasi

Seluruh request ke endpoint QRIS memerlukan API key. Kirimkan melalui header Authorization dengan format Bearer token.

curl -H "Authorization: Bearer cpay_live_xxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ https://api.xentralpay.com/v1/qris/generate
const headers = { 'Authorization': 'Bearer cpay_live_xxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type': 'application/json' };
$headers = [ 'Authorization: Bearer cpay_live_xxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type: application/json' ];
headers = { "Authorization": "Bearer cpay_live_xxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json" }
warning

API key berbeda dengan token login dashboard. Jangan pernah menyertakan API key di kode frontend/client-side. Selalu panggil dari server Anda.

Cara mendapatkan API key
  1. Daftar di dashboard XentralPay
  2. Verifikasi akun via Telegram bot @xentralpaybot
  3. Buat project baru di menu Project
  4. Salin API key yang ditampilkan (hanya ditampilkan sekali)

qr_code_2 Generate QRIS

Membuat transaksi QRIS baru. Order ID bisa custom atau auto-generate.

POST /v1/qris/generate
Request Parameters
ParameterTipeWajibDeskripsi
amountintegerYaJumlah dalam Rupiah. Minimal 1, maksimal 10.000.000.
order_idstringTidakID transaksi custom. Huruf, angka, dash, underscore. Maks 50 karakter. Harus unik. Jika tidak diisi, otomatis di-generate dengan format CP-{timestamp}-{random}.
callback_urlstringTidakURL untuk menerima webhook khusus transaksi ini. Jika tidak diisi, menggunakan webhook URL default dari project.
metadataobjectTidakData tambahan (bebas). Akan dikembalikan di webhook saat pembayaran berhasil. Contoh: {"user_id": "123"}
Contoh Request
curl -X POST https://api.xentralpay.com/v1/qris/generate \ -H "Authorization: Bearer cpay_live_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "amount": 50000, "order_id": "INV-20240101-001", "callback_url": "https://yourapp.com/webhook", "metadata": {"user_id": "U-123", "product": "Premium Plan"} }'
const response = await fetch('https://api.xentralpay.com/v1/qris/generate', { method: 'POST', headers: { 'Authorization': 'Bearer cpay_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 50000, order_id: 'INV-20240101-001', callback_url: 'https://yourapp.com/webhook', metadata: { user_id: 'U-123', product: 'Premium Plan' } }) }); const data = await response.json(); console.log(data.data.checkout_url); // URL checkout siap pakai
$ch = curl_init('https://api.xentralpay.com/v1/qris/generate'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer cpay_live_xxxxx', 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'amount' => 50000, 'order_id' => 'INV-20240101-001', 'callback_url' => 'https://yourapp.com/webhook', 'metadata' => ['user_id' => 'U-123', 'product' => 'Premium Plan'] ])); $response = json_decode(curl_exec($ch), true); echo $response['data']['checkout_url']; // URL checkout siap pakai
import requests response = requests.post( "https://api.xentralpay.com/v1/qris/generate", headers={"Authorization": "Bearer cpay_live_xxxxx"}, json={ "amount": 50000, "order_id": "INV-20240101-001", "callback_url": "https://yourapp.com/webhook", "metadata": {"user_id": "U-123", "product": "Premium Plan"} } ) data = response.json() print(data["data"]["checkout_url"]) # URL checkout siap pakai
Response Sukses (201)
{
  "success": true,
  "message": "QRIS created successfully",
  "data": {
    "order_id": "INV-20240101-001",
    "amount": 50000,
    "status": "pending",
    "qr_content": "00020101021226610014COM.GO-JEK.WWW...",
    "qr_image_url": "https://xentralpay.com/qris/INV-20240101-001/qr.png",
    "checkout_url": "https://xentralpay.com/pay/INV-20240101-001",
    "expires_at": "2026-06-22T15:09:00.000Z",
    "created_at": "2026-06-22T14:54:00.000Z"
  }
}
Response Fields
FieldTipePenjelasan
order_idstringID unik transaksi. Gunakan untuk cek status atau membatalkan.
amountintegerNominal pembayaran dalam Rupiah.
statusstringStatus awal selalu pending.
qr_contentstringRaw QRIS payload. Render menjadi gambar QR pakai library seperti qrcode (Node.js) atau qrcode.react.
qr_image_urlstringURL gambar QR yang sudah di-render oleh server. Bisa langsung ditampilkan sebagai <img>.
checkout_urlstringHalaman checkout siap pakai. Arahkan pelanggan ke URL ini jika tidak ingin render QR sendiri. Halaman ini auto-polling status dan menampilkan confetti saat berhasil.
expires_atstringWaktu kedaluwarsa transaksi (ISO 8601). Setelah waktu ini, status otomatis menjadi expire.
Response Error
{
  "success": false,
  "message": "amount must be an integer between 1 and 10,000,000"
}

search Cek Status Transaksi

Mengambil status terbaru dari sebuah transaksi. Jika masih pending, sistem otomatis sinkronisasi ke provider sebelum merespons.

POST /v1/qris/status
Request Parameters
ParameterTipeDeskripsi
order_idstringOrder ID dari XentralPay. Gunakan order_id atau transaction_id, salah satu wajib diisi.
transaction_idstringTransaction ID dari provider (UUID). Alternatif dari order_id.
Contoh Request
curl -X POST https://api.xentralpay.com/v1/qris/status \ -H "Authorization: Bearer cpay_live_xxxxx" \ -H "Content-Type: application/json" \ -d '{"order_id": "INV-20240101-001"}'
const res = await fetch('https://api.xentralpay.com/v1/qris/status', { method: 'POST', headers: { 'Authorization': 'Bearer cpay_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ order_id: 'INV-20240101-001' }) }); const data = await res.json(); if (data.data.status === 'settlement') { console.log('Pembayaran berhasil!'); console.log('Diterima:', data.data.net_amount); }
$ch = curl_init('https://api.xentralpay.com/v1/qris/status'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer cpay_live_xxxxx', 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'order_id' => 'INV-20240101-001' ])); $response = json_decode(curl_exec($ch), true); if ($response['data']['status'] === 'settlement') { echo 'Pembayaran berhasil! Diterima: ' . $response['data']['net_amount']; }
response = requests.post( "https://api.xentralpay.com/v1/qris/status", headers={"Authorization": "Bearer cpay_live_xxxxx"}, json={"order_id": "INV-20240101-001"} ) data = response.json() if data["data"]["status"] == "settlement": print(f"Pembayaran berhasil! Diterima: {data['data']['net_amount']}")
Response Sukses (200)
{
  "success": true,
  "data": {
    "order_id": "INV-20240101-001",
    "amount": 50000,
    "net_amount": 49450,
    "fee_amount": 550,
    "status": "settlement",
    "payment_method": "QRIS",
    "created_at": "2026-06-22T14:54:00.000Z",
    "settled_at": "2026-06-22T14:56:12.000Z"
  }
}
Nilai Status
StatusKeterangan
settlementPembayaran berhasil. Dana masuk ke saldo tertunda merchant, cair otomatis setelah H+1.
pendingMenunggu pembayaran. Pelanggan belum scan/bayar.
expireWaktu pembayaran habis tanpa transaksi masuk.
cancelDibatalkan melalui endpoint /v1/qris/cancel.

cancel Batalkan Transaksi

Hanya transaksi berstatus pending yang dapat dibatalkan.

POST /v1/qris/cancel
Contoh Request
curl -X POST https://api.xentralpay.com/v1/qris/cancel \ -H "Authorization: Bearer cpay_live_xxxxx" \ -H "Content-Type: application/json" \ -d '{"order_id": "INV-20240101-001"}'
await fetch('https://api.xentralpay.com/v1/qris/cancel', { method: 'POST', headers: { 'Authorization': 'Bearer cpay_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ order_id: 'INV-20240101-001' }) });
$ch = curl_init('https://api.xentralpay.com/v1/qris/cancel'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer cpay_live_xxxxx', 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'order_id' => 'INV-20240101-001' ])); $response = json_decode(curl_exec($ch), true);
response = requests.post( "https://api.xentralpay.com/v1/qris/cancel", headers={"Authorization": "Bearer cpay_live_xxxxx"}, json={"order_id": "INV-20240101-001"} )
Response Sukses (200)
{
  "success": true,
  "data": {
    "order_id": "INV-20240101-001",
    "status": "cancel",
    "cancelled_at": "2026-06-22T14:58:30.000Z"
  }
}

webhook Menerima Webhook

Saat transaksi berhasil dibayar, XentralPay mengirimkan POST request ke webhook URL yang diset di project Anda.

Payload yang Dikirim
{
  "event": "payment.completed",
  "timestamp": "2026-06-22T14:56:12.000Z",
  "data": {
    "order_id": "INV-20240101-001",
    "amount": 50000,
    "net_amount": 49450,
    "fee_amount": 550,
    "status": "settlement",
    "payment_method": "QRIS",
    "metadata": {"user_id": "U-123", "product": "Premium Plan"}
  }
}
Header yang Dikirim
HeaderKeterangan
X-XentralPay-SignatureHMAC-SHA256 dari raw body, ditandatangani menggunakan webhook_secret project Anda.
X-XentralPay-TimestampUnix timestamp saat webhook dikirim. Gunakan untuk mencegah replay attack.
Content-Typeapplication/json
info

Server Anda harus mengembalikan HTTP 200 dalam 10 detik. Jika gagal, XentralPay akan retry otomatis hingga 5 kali dengan delay bertingkat: 0s, 5s, 30s, 2 menit, 10 menit.

Webhook Response Fields
FieldPenjelasan
eventSelalu payment.completed untuk pembayaran berhasil.
data.order_idOrder ID yang sama dengan saat generate.
data.amountNominal asli transaksi (sebelum fee).
data.net_amountJumlah yang diterima merchant (setelah fee dipotong).
data.fee_amountTotal fee yang dipotong (persentase + flat).
data.metadataObject metadata yang Anda kirim saat generate. Bisa dipakai untuk mencocokkan order di sistem Anda.

verified_user Verifikasi Signature

Selalu verifikasi header X-XentralPay-Signature sebelum memproses webhook, agar tidak ada yang bisa mengirim notifikasi palsu.

const crypto = require('crypto'); app.post('/webhook', (req, res) => { const signature = req.headers['x-xentralpay-signature']; const expected = crypto .createHmac('sha256', process.env.WEBHOOK_SECRET) .update(JSON.stringify(req.body)) .digest('hex'); if (signature !== expected) { return res.status(401).json({ error: 'Invalid signature' }); } const { data } = req.body; if (data.status === 'settlement') { // Pembayaran berhasil! // Update status order di database Anda // Kirim konfirmasi ke pelanggan console.log(`Order ${data.order_id} berhasil dibayar`); console.log(`Diterima: Rp ${data.net_amount}`); } res.json({ received: true }); });
$payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_XENTRALPAY_SIGNATURE'] ?? ''; $expected = hash_hmac('sha256', $payload, WEBHOOK_SECRET); if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Invalid signature'); } $event = json_decode($payload, true); if ($event['data']['status'] === 'settlement') { // Pembayaran berhasil! // Update status order di database Anda $orderId = $event['data']['order_id']; $netAmount = $event['data']['net_amount']; // ... proses order } echo json_encode(['received' => true]);
import hmac, hashlib, json from flask import Flask, request app = Flask(__name__) @app.route("/webhook", methods=["POST"]) def webhook(): signature = request.headers.get("X-XentralPay-Signature", "") expected = hmac.new( WEBHOOK_SECRET.encode(), request.data, hashlib.sha256 ).hexdigest() if not hmac.compare_digest(expected, signature): return "", 401 event = request.get_json() if event["data"]["status"] == "settlement": # Pembayaran berhasil! order_id = event["data"]["order_id"] net_amount = event["data"]["net_amount"] # ... proses order return {"received": True}
warning

Pastikan endpoint webhook Anda bersifat idempotent. Webhook dengan order_id yang sama mungkin dikirim lebih dari satu kali (retry). Cek apakah order sudah diproses sebelum mengupdate database.

error Kode Error

Semua response error menggunakan format konsisten:

{
  "success": false,
  "message": "Pesan error yang menjelaskan masalah"
}
StatusKeteranganContoh Message
400Parameter tidak valid"amount must be an integer between 1 and 10,000,000"
401API key tidak valid atau tidak disertakan"Invalid API key"
403Akun merchant atau project suspended"Merchant account is suspended"
404Order ID tidak ditemukan atau bukan milik Anda"Transaction not found"
409Transaksi sudah final (tidak bisa di-cancel)"Cannot cancel transaction in status settlement"
429Terlalu banyak request (rate limited)"Too many attempts. Try again in 15 minutes."
500Kesalahan internal XentralPay"Internal error generating QRIS"
502Provider QRIS tidak merespons"AutoGoPay rejected the request"
support_agent
Butuh bantuan?

Tim technical support kami siap membantu integrasi Anda. Hubungi di Telegram @cogil

help Pertanyaan Umum (FAQ)

Apa itu API Key dan di mana mendapatkannya? expand_more
API Key adalah kode unik yang dipakai untuk mengakses API XentralPay. Setiap project punya API Key sendiri. Cara mendapatkan: Login > Project > + Project Baru > Simpan API Key. API Key hanya ditampilkan sekali saat pembuatan. Kalau hilang, bisa generate ulang di halaman project (key lama langsung hangus).
Saya tidak punya server/website, bisa pakai XentralPay? expand_more
Bisa! Setiap transaksi menghasilkan checkout_url — halaman pembayaran siap pakai dari XentralPay. Kirim link itu ke pelanggan lewat WhatsApp, Telegram, atau di mana saja. Halaman itu otomatis menampilkan QR code, countdown timer, dan status pembayaran real-time. Untuk cek status, polling endpoint /v1/qris/status tanpa perlu server webhook.
Berapa lama QRIS berlaku sebelum expired? expand_more
QRIS berlaku sekitar 15 menit setelah dibuat. Waktu persis ada di field expires_at di response. Setelah expired, status otomatis berubah menjadi expire dan pembayaran tidak bisa dilakukan. Buat transaksi baru jika expired.
Apa bedanya fee mode "Merchant" dan "Buyer"? expand_more
Merchant: Fee dipotong dari saldo Anda. Pelanggan bayar harga asli. Contoh: produk Rp 100.000, pelanggan bayar Rp 100.000, Anda terima Rp 99.100.

Buyer: Fee ditambahkan ke nominal QRIS. Anda terima harga full. Contoh: produk Rp 100.000, pelanggan bayar Rp 100.900, Anda terima Rp 100.000.

Setting ini ada di menu Project > Edit > Fee dibebankan ke.
Kapan saldo saya bisa ditarik? expand_more
Saldo dari transaksi yang berhasil masuk ke "Saldo Tertunda" dulu. Setelah 24 jam (H+1), saldo otomatis pindah ke "Saldo Tersedia" dan bisa ditarik. Proses penarikan dilakukan manual oleh admin setelah Anda mengajukan request di menu Penarikan.
Apa itu webhook dan apakah wajib? expand_more
Webhook adalah notifikasi otomatis yang dikirim XentralPay ke server Anda saat pembayaran berhasil. Webhook tidak wajib. Alternatifnya: polling endpoint /v1/qris/status setiap beberapa detik untuk cek apakah pembayaran sudah masuk. Webhook lebih efisien untuk volume transaksi tinggi.
Bagaimana cara integrasi ke bot Telegram? expand_more
  1. Panggil /v1/qris/generate saat user mau bayar
  2. Kirim QR image (qr_image_url) atau checkout link ke chat user
  3. Polling /v1/qris/status setiap 5 detik
  4. Kalau status settlement, kirim pesan "Pembayaran berhasil!" dan proses order

Lihat Contoh Integrasi Lengkap untuk kode yang siap pakai.

Order ID custom itu apa? Wajib diisi? expand_more
Tidak wajib. Kalau tidak diisi, XentralPay otomatis generate ID (format: CP-timestamp-random). Kalau diisi, Anda bisa pakai ID sendiri (contoh: INV-001, ORDER-123) supaya mudah dicocokkan dengan data di sistem Anda. Aturan: huruf, angka, dash, underscore, maksimal 50 karakter, harus unik.
API Key saya hilang, bagaimana? expand_more
Login ke dashboard, buka menu Project, klik "Regenerate Key" pada project yang bersangkutan. API Key baru akan di-generate dan yang lama langsung hangus. Simpan key baru dengan baik.