Lewati ke konten utama

Quick Start (5 Minutes)

This guide walks you through accepting your first QRIS payment using the V1 API.

Prerequisites​

  1. An active merchant account (FlyPay or FlyPay)
  2. Your API key from the merchant dashboard: Settings → API Credentials
  3. A server that can receive HTTP POST requests (for webhooks)

Step 1: Create an Order​

Send a POST to /v1/orders with your item amount and customer details.

cURL
curl -X POST https://api.flypay.asia/v1/orders \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-$(date +%s)" \
-d '{
"merchant_order_id": "INV-001",
"amount": 50000,
"payment_method": "QRIS",
"customer_name": "Budi Santoso",
"notify_url": "https://your-site.com/webhooks/payment",
"expire_minutes": 15
}'

amount: 50000 means IDR 50,000. Do not multiply by 100.

Response:

{
"success": true,
"data": {
"ref_code": "ORD-260601103045-A1B2",
"status": "PENDING",
"qris_string": "00020101021226...",
"qr_url": "https://example.com/qr/ORD-260601103045-A1B2.png",
"expires_at": "2026-06-01T10:45:45Z"
}
}

Step 2: Display the QR Code​

Render qris_string as a QR code in your checkout UI, or display qr_url as an image:

Use the actual qr_url returned by your order, or render qris_string as a QR image. The URLs in examples are illustrative and are not hosted images.

JavaScript — render QRIS string with a library
import QRCode from 'qrcode';

const canvas = document.getElementById('qr-canvas');
await QRCode.toCanvas(canvas, data.qris_string, { width: 300 });

The QR code is valid until expires_at. Show a countdown timer and disable payment after expiry.

Step 3: Receive the Payment Webhook​

When the customer pays, the system POSTs to your notify_url:

{
"event": "order.PAID",
"ref_code": "ORD-260601103045-A1B2",
"merchant_order_id": "INV-001",
"amount": 50000,
"status": "PAID",
"paid_at": "2026-06-01T10:38:12Z"
}

Your handler must return HTTP 200. Process the event asynchronously:

PHP — webhook handler
<?php
$rawBody = file_get_contents('php://input');

// Optional: verify signature
$webhookSecret = getenv('WEBHOOK_SECRET');
if ($webhookSecret) {
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $webhookSecret);
if (!hash_equals($expected, $_SERVER['HTTP_X_SIGNATURE'] ?? '')) {
http_response_code(401);
exit;
}
}

// Acknowledge immediately
http_response_code(200);
echo json_encode(['received' => true]);
if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();

$payload = json_decode($rawBody, true);

if ($payload['status'] === 'PAID') {
$orderId = $payload['merchant_order_id']; // your INV-001
// mark order as paid in your database
// trigger fulfillment
}

Step 4: Poll for Status (Optional Fallback)​

If your webhook endpoint was unavailable, poll the order:

cURL
curl https://api.flypay.asia/v1/orders/ORD-260601103045-A1B2 \
-H "X-API-Key: YOUR_API_KEY"

Check data.status: PAID = success, EXPIRED/FAILED = unsuccessful.


What's Next?​