Panduan Integrasi Tenant

Dokumentasi PayGate API

Semua yang perlu Anda ketahui untuk menghubungkan sistem toko/aplikasi Anda ke PayGate - mulai dari setup awal hingga verifikasi webhook.

REST APIJSONHMAC-SHA256Base URL: https://pg-be.belanjamu.company
Download Postman CollectionKoleksi endpoint siap pakai (tinggal import ke Postman)
1

Langkah Awal - Mendapatkan Akses

Langkah awal: daftar sendiri untuk mendapatkan Tenant ID & pilihan paket

  1. Buka halaman Pendaftaran Tenant โ†’ isi nama toko, nomor WhatsApp, dan jenis usaha โ†’ pilih paket langganan (mis. Monthly, Unlimited).
  2. Penyelesaian pembayaran paket akan menerbitkan Tenant ID Anda dan, jika admin aktifkan tenant, Admin akan menerbitkan tiga kredensial utama (dikirim via WA) setelah pembayaran terverifikasi:
    • Tenant ID - ID unik tenant Anda (contoh: tenant_9a8b7c)
    • X-API-Key - Kunci rahasia untuk memanggil endpoint API (simpan di .env server Anda)
    • Webhook Secret - Kunci rahasia untuk memverifikasi keaslian callback notifikasi pembayaran
  3. Setelah tenant aktif, masuk ke Tenant Workspace untuk melengkapi konfigurasi payment provider Anda.
2

Setup Provider di Dashboard Tenant

PayGate mendukung berbagai upstream payment provider. Masukkan kredensial provider Anda di Tenant Dashboard.

Keamanan & Enkripsi Kredensial Provider (AES-256-GCM)
Semua API key, auth token, dan secret pihak ketiga dari provider andalan Anda yang dimasukkan dienkripsi at-rest menggunakan AES-256-GCM sebelum disimpan ke database. Bahkan administrator sistem tidak dapat membaca kunci Anda dalam bentuk plaintext.
ProviderMetodeKunci yang Diperlukan
PAKASIRQRISprojectSlug, apiKey
VALQENIXQRISapiKey, webhookSecret
GOPAYQRIS Statis & MutasiqrisStatic, merchantId, email, password, deviceId, accessToken, refreshToken

Contoh format JSON config untuk PAKASIR:

json
{
  "projectSlug": "toko-elektronik-anda",
  "apiKey": "pks_live_xxxxxxxxxxxxxxxx"
}
3

Autentikasi API

๐Ÿ’ก Rekomendasi: Gunakan SDK resmi
Install paygate-belanjamu โ€” SDK resmi yang menangani auth, request, dan webhook verification otomatis. Tidak perlu set header manual.
bash
npm install paygate-belanjamu
typescript
import { PayGate } from "paygate-belanjamu";

const pg = new PayGate({ apiKey: process.env.PAYGATE_API_KEY });

// Buat pembayaran
const payment = await pg.createPayment({ orderId: "ORD-001", amount: 50000 });

// Cek status
const tx = await pg.getPayment(payment.reference);

Alternatif: jika tidak menggunakan SDK, semua request dari backend Anda ke PayGate API wajib menyertakan header autentikasi berikut:

http
POST https://pg-be.belanjamu.company/api/v1/payments HTTP/1.1
Content-Type: application/json
X-API-Key: YOUR_TENANT_API_KEY
Peringatan Keamanan
Jangan pernah menyimpan atau memanggil API Key dari browser/frontend/mobile app client langsung. Panggil selalu dari server backend Anda.
4

Membuat Transaksi Pembayaran

POST/api/v1/payments

Kirim request untuk membuat transaksi baru:

bash (cURL)
curl -X POST https://pg-be.belanjamu.company/api/v1/payments \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_TENANT_API_KEY" \
  -H "Idempotency-Key: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" \
  -d '{
    "order_id": "INV-2026-001",
    "amount": 75000,
    "method": "qris",
    "note": "Pembelian Paket Pro",
    "expire_minutes": 15,
    "metadata": { "customer_id": "CUST-99" }
  }'
Proteksi Idempotency & Collision Retry
Sertakan header Idempotency-Key (UUID) untuk mencegah pembayaran ganda jika terjadi network retry. Untuk provider mutasi, gateway secara otomatis menghasilkan kode unik 1โ€“999 dan memeriksa tabrakan transaksi aktif (max 5 retry).

Contoh response sukses dari gateway:

json
{
  "success": true,
  "data": {
    "reference": "PAY-20260904-A1B2C3",
    "order_id": "INV-2026-001",
    "tenant_id": "tenant_9a8b7c",
    "provider": "PAKASIR",
    "method": "qris",
    "amount": 75000,
    "unique_code": 380,
    "unique_amount": 380,
    "fee": 380,
    "total_amount": 75380,
    "status": "PENDING",
    "qr_image_url": "https://pg-be.belanjamu.company/api/v1/qr/INV-2026-001.png",
    "account_number": null,
    "checkout_url": null,
    "paid_at": null,
    "expires_at": "2026-09-04T10:30:00.000Z",
    "created_at": "2026-09-04T10:15:00.000Z",
    "metadata": { "customer_id": "CUST-99" }
  }
}
โ€ข reference - ID transaksi unik dari PayGate untuk pelacakan (gunakan saat cek status).
โ€ข unique_code / unique_amount - Kode unik / fee selisih transaksi (misal: 380).
โ€ข total_amount - Total rupiah yang harus dibayarkan pelanggan (amount + unique_code).
โ€ข qr_image_url - Link gambar PNG publik, render on-the-fly (tanpa file disimpan di server). Langsung pasang ke tag HTML: <img src="qr_image_url" />. Link aktif selama transaksi belum kedaluwarsa (max-age cache 5 menit).
5

Memeriksa Status Transaksi

GET/api/v1/payments/:reference

Periksa status transaksi menggunakan `reference` atau `order_id` Anda:

bash (cURL)
curl https://pg-be.belanjamu.company/api/v1/payments/PAY-20260904-A1B2C3 \
  -H "X-API-Key: YOUR_TENANT_API_KEY"

Status transaksi baku (uppercase):

PENDINGPAIDEXPIREDFAILED
6

Menerima & Verifikasi Webhook

Setiap kali ada pembayaran yang berhasil, PayGate secara otomatis akan mengirim notifikasi ke URL server Anda (yang sudah Anda daftarkan di Dashboard Tenant). Ini berguna agar aplikasi/toko Anda bisa langsung memproses pesanan begitu pembayaran dikonfirmasi - tanpa perlu cek status manual.

Berikut contoh data yang akan dikirim ke server Anda:

json
{
  "event_id": "evt_PAY-20260904-A1B2C3",
  "event_type": "payment.paid",
  "timestamp": "2026-09-04T10:20:15.000Z",
  "data": {
    "reference": "PAY-20260904-A1B2C3",
    "order_id": "INV-2026-001",
    "provider": "PAKASIR",
    "method": "qris",
    "amount": 75000,
    "paid_amount": 75000,
    "status": "PAID",
    "paid_at": "2026-09-04T10:20:15.000Z"
  }
}

Verifikasi header `X-Signature` atau `X-Gateway-Signature` dengan HMAC-SHA256:

javascript (Node.js)
const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/webhook/paygate', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-signature'] || req.headers['x-gateway-signature'];
  const secret    = process.env.PAYGATE_WEBHOOK_SECRET;

  // Hitung HMAC-SHA256 dari raw payload body (string/buffer)
  const expected = crypto
    .createHmac('sha256', secret)
    .update(req.body)
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const payload = JSON.parse(req.body);

  if (payload.status === 'PAID') {
    // Jalankan fulfillment pesanan di sistem Anda
    await fulfillOrder(payload.order_id, payload.amount);
  }

  // Wajib response HTTP 2xx
  res.status(200).json({ received: true });
});
Selalu kembalikan HTTP status 200/204. Jika server Anda mengembalikan selain 2xx, PayGate akan melakukan exponential backoff retry hingga maksimal 8 kali (~24 jam).
7

Daftar Endpoint API

MethodEndpointAuthDeskripsi
POST/api/v1/paymentsX-API-KeyBuat transaksi pembayaran baru
GET/api/v1/payments/:referenceX-API-KeyPeriksa status transaksi (on-demand sync)
POST/api/v1/payments/:reference/cancelX-API-KeyBatalkan transaksi PENDING
POST/api/v1/sandbox/simulate-paidX-API-KeySimulasi pembayaran sukses (mode sandbox)
POST/api/v1/sandbox/test-webhookX-API-KeyUji coba pengiriman webhook HMAC
GET/api/v1/config/providerX-API-KeyAmbil nama provider aktif
PUT/api/v1/config/providerX-API-KeyUpdate konfigurasi provider aktif
PUT/api/v1/config/webhookX-API-KeyUpdate URL webhook & secret
GET/api/v1/public/statsPublikStatistik publik gateway (GMV & total transaksi)
8

Tips & Error Umum

PayGate mengembalikan kode error terstandar (`code`) dan deskripsi (`error`) yang jelas pada setiap kegagalan API. Berikut tabel referensi lengkapnya:

PG-01Autentikasi Gagal
401 Unauthorized

Header X-API-Key salah, kedaluwarsa, atau tidak disertakan.

๐Ÿ’ก Solusi: Pastikan menyertakan header 'X-API-Key: your_api_key'.
PG-02Konfigurasi Provider Belum Diset
422 Unprocessable

Belum ada kredensial provider terpasang. Hubungkan salah satu provider di dashboard.

๐Ÿ’ก Solusi: Setup provider di menu Pengaturan Portal Tenant terlebih dahulu.
PG-03Payload Tidak Valid
400 Bad Request

order_id tidak disertakan atau amount bukan angka positif.

๐Ÿ’ก Solusi: Kirim request body JSON dengan order_id dan amount yang benar.
PG-04Transaksi Tidak Ditemukan
404 Not Found

Reference pembayaran atau order_id tidak ada dalam database tenant ini.

๐Ÿ’ก Solusi: Cek kembali reference ID atau status transaksi di dashboard.
PG-05Status Transaksi Bentrok
409 Conflict

Transaksi sudah berstatus final (PAID/EXPIRED) sehingga tidak bisa diubah.

๐Ÿ’ก Solusi: Buat order baru jika customer ingin mencoba pembayaran kembali.
PG-06Gangguan Server Upstream
502 Bad Gateway

Provider pembayaran pihak ketiga mengalami timeout atau kegagalan sistem.

๐Ÿ’ก Solusi: Coba beberapa saat lagi atau beralih ke provider backup.
PG-07Batas Rate Limit Terlampaui
429 Too Many Requests

Request melebihi batas 30 req/menit untuk pembuatan transaksi.

๐Ÿ’ก Solusi: Terapkan jeda (backoff) di aplikasi client Anda.
PG-08Sandbox Mode Diperlukan
403 Forbidden

Endpoint simulasi dipanggil saat sandbox_mode tenant masih dinonaktifkan.

๐Ÿ’ก Solusi: Aktifkan toggle Sandbox Mode di halaman Pengaturan Tenant.
PG-99Internal Server Error
500 Internal Error

Terjadi kesalahan internal tak terduga pada server PayGate.

๐Ÿ’ก Solusi: Periksa log server atau hubungi admin gateway.
9

Menghubungkan Webhook Provider ke PayGate

Agar PayGate tahu saat customer selesai bayar via Pakasir atau Valqenix, daftarkan URL Penerima Callback berikut di dashboard provider Anda:

text
POST https://pg-be.belanjamu.company/api/v1/webhooks/incoming/<NAMA_PROVIDER>

Contoh:
  PAKASIR  โ†’ https://pg-be.belanjamu.company/api/v1/webhooks/incoming/pakasir
  VALQENIX โ†’ https://pg-be.belanjamu.company/api/v1/webhooks/incoming/valqenix

Langkah setup per provider:

PAKASIRQRIS via Project Slug
  1. Login ke dashboard Pakasir, buka menu Project Settings.
  2. Pada kolom Callback / Notification URL, masukkan:
    https://pg-be.belanjamu.company/api/v1/webhooks/incoming/pakasir
  3. Simpan. Pastikan Project Slug di konfigurasi tenant PayGate cocok dengan slug project Pakasir Anda.
Tenang, PayGate otomatis mengecek ulang setiap ada info bayar dari Pakasir langsung ke server Pakasir agar aman dari kecurangan/pemalsuan data.
VALQENIXQRIS + HMAC Signature
  1. Login ke panel Valqenix, buka Webhook Settings.
  2. Daftarkan Callback URL:
    https://pg-be.belanjamu.company/api/v1/webhooks/incoming/valqenix
  3. Salin Webhook Secret dari Valqenix, lalu tempel di Dashboard PayGate pada konfigurasi Valqenix Anda di kolom webhookSecret. Ini digunakan PayGate untuk memverifikasi keaslian notifikasi yang dikirim Valqenix.
GOPAYOtomatis Cek Mutasi Akun (Tanpa Perlu Setup Webhook)

Khusus GoPay, Anda tidak perlu mendaftarkan URL apapun. Sistem PayGate otomatis mengecek mutasi akun GoPay Anda di background setiap 30 detik untuk mencocokkan nominal pembayaran yang masuk.

Tidak ada settingan webhook tambahan untuk GoPay. Langsung aktif!

Setelah PayGate menerima dan memvalidasi pembayaran di atas, PayGate akan langsung meneruskan notifikasi ke server toko Anda secara otomatis.

10

Simulasi Pembayaran (Sandbox Universal)

PayGate menyediakan endpoint simulasi pembayaran universal yang berlaku untuk seluruh provider saat tenant mengaktifkan Sandbox Mode.

UNIVERSAL SIMULATEPOST /api/v1/sandbox/simulate-paid

Mengubah status transaksi PENDING menjadi PAID secara internal dan langsung men-trigger pengiriman webhook bertanda tangan HMAC ke URL merchant Anda. Sangat penting untuk provider seperti GoPay yang tidak menyediakan API sandbox/simulasi bawaan.

bash
curl -X POST https://pg-be.belanjamu.company/api/v1/sandbox/simulate-paid \
  -H "X-API-Key: YOUR_TENANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "order_id": "PG-PLAY-1788510076922" }'
PROVIDER-SPECIFIC SIMULATESimulasi Bawaan Provider (Contoh: Pakasir)

Jika provider upstream memiliki API sandbox sendiri (misal Pakasir), Anda juga dapat menembak langsung endpoint simulasi provider untuk menguji alur webhook ingestion end-to-end:

bash
# Contoh: Simulasi Pakasir Sandbox
curl -X POST https://app.pakasir.com/api/paymentsimulation \
  -H "Content-Type: application/json" \
  -d '{
    "project": "slug_project_anda",
    "order_id": "PG-PLAY-1788510076922",
    "amount": 10000,
    "api_key": "api_key_pakasir_anda"
  }'
11

Multi-Provider Failover & Redundancy Otomatis

PayGate mendukung konfigurasi multi-provider sekaligus untuk satu tenant. Sistem akan secara cerdas menjalankan pembayaran dengan strategi sequential failover:

FAILOVER MEKANISMECara Kerja Fallback Sequential
  1. Prioritas Terendah Utama: Gateway mencoba membuat pembayaran menggunakan provider dengan nilai priority terkecil (contoh: priority 0 = Pakasir).
  2. Upstream Error Catching: Jika provider utama mengalami gangguan (maintenance, timeout, network error, balance habis), PayGate secara otomatis mencatat log peringatan tanpa menggugurkan request merchant.
  3. Sequential Fallback: Gateway langsung mencoba provider aktif berikutnya (contoh: priority 1 = GoPay) sampai berhasil membuat QRIS / tagihan.
  4. Provider Tagging: Kolom provider di data transaksi akan otomatis mencatat nama provider yang berhasil menangani transaksi tersebut.
Zero Merchant Downtime
Toko Anda tetap dapat menerima pembayaran meskipun salah satu provider payment gateway sedang mengalami gangguan teknis.
12

NPM SDK โ€” paygate-belanjamu

npm paygate-belanjamuDual: Node.js + Browser ยท TypeScript ยท HMAC-SHA256 webhook

SDK resmi PayGate untuk integrasi pembayaran di server Node.js dan polling status di browser. Publish ke NPM, install dalam 1 baris:

bash
npm install paygate-belanjamu
Node.js โ€” Create & Poll
bash
import { PayGate } from "paygate-belanjamu";

const pg = new PayGate({ apiKey: "pg_live_xxxx" });

// Create a QRIS payment
const payment = await pg.createPayment({
  orderId: "ORD-001",
  amount: 50000,
  method: "QRIS",
});

console.log(payment.qr_image_url);  // SVG/PNG
console.log(payment.reference);     // PAY-20260909-XXXX

// Poll status
const tx = await pg.getPayment(payment.reference);
console.log(tx.status); // PENDING | PAID | EXPIRED | FAILED

// List & cancel
const { transactions } = await pg.listPayments({ page: 1, limit: 20 });
await pg.cancelPayment(payment.reference);
Webhook Verification (Express)

Selalu baca raw body sebelum JSON.parse. Jangan pakai === untuk cek signature (timing leak).

bash
import { verifyWebhook } from "paygate-belanjamu";
import express from "express";

app.post(
  "/webhooks/paygate",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const rawBody = req.body.toString("utf8");
    const valid = await verifyWebhook(
      rawBody,
      req.header("X-Signature"),
      process.env.WEBHOOK_SECRET
    );
    if (!valid) return res.status(401).send("invalid signature");
    const event = JSON.parse(rawBody);
    // event.reference, event.order_id, event.status === "PAID"
    res.json({ status: "ok" });
  }
);
Browser

Pakai SDK yang sama di bundle browser untuk polling. Webhook verification pakai WebCrypto otomatis.

bash
import { PayGate, verifyWebhook } from "paygate-belanjamu";

const pg = new PayGate({ apiKey: "pg_live_xxxx" });
const tx = await pg.getPayment("PAY-20260909-XXXX");
const valid = await verifyWebhook(rawBody, sig, secret);
TypeScript
Semua response sudah ter-typed. Lihat src/types.ts di repo SDK untuk referensi lengkap.
Siap mulai integrasi?
Login ke workspace tenant untuk setup provider dan webhook Anda.
Buka Tenant Workspace โ†’