Panduan Integrasi

Step-by-step mengintegrasikan Bukasir ke aplikasi Anda dengan PHP dan JavaScript.

Persiapan

Sebelum memulai integrasi, pastikan Anda sudah:

  • Memiliki akun Bukasir yang terverifikasi
  • Memiliki API Key dari dashboard (Pengaturan > API)
  • Memiliki minimal satu Project yang sudah dibuat
Catatan Selalu simpan API Key di environment variable. API key adalah string hex 64 karakter.

Integrasi dengan PHP

Langkah 1: Buat Form Checkout

Buat halaman checkout dengan form sederhana yang mengumpulkan data dari customer:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <title>Checkout - Toko Kita</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
  <style>
    body { font-family: -apple-system, sans-serif; max-width: 480px; margin: 40px auto; padding: 20px; }
    .form-group { margin-bottom: 16px; }
    label { display: block; font-weight: 600; margin-bottom: 6px; }
    input, select { width: 100%; padding: 10px 14px; border: 1px solid #ddd; border-radius: 8px; font-size: 15px; }
    button { width: 100%; padding: 12px; background: #0071E3; color: #fff; border: none; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; }
    button:hover { background: #0060c0; }
  </style>
</head>
<body>
  <h2>Checkout</h2>
  <form action="/api/charge" method="POST" id="checkout">

    <div class="form-group">
      <label for="order_id">Order ID</label>
      <input type="text" id="order_id" name="order_id" placeholder="ORDER-001" required>
    </div>

    <div class="form-group">
      <label for="amount">Jumlah (Rp)</label>
      <input type="number" id="amount" name="amount" placeholder="50000" min="100" required>
    </div>

    <div class="form-group">
      <label for="payment_method">Metode Pembayaran</label>
      <select id="payment_method" name="payment_method" required>
        <option value="">-- Pilih Metode --</option>
        <option value="qris">QRIS</option>
        <option value="gopay">GoPay</option>
        <option value="bank_transfer">Bank Transfer</option>
      </select>
    </div>

    <div class="form-group" id="bank-group" style="display:none">
      <label for="bank">Bank</label>
      <select id="bank" name="bank">
        <option value="">-- Pilih Bank --</option>
        <option value="bni">BNI</option>
        <option value="bri">BRI</option>
        <option value="mandiri">Mandiri</option>
        <option value="permata">Permata</option>
        <option value="cimb">CIMB Niaga</option>
      </select>
    </div>

    <button type="submit" id="payBtn">
      <i class="bi bi-lock"></i> Bayar Sekarang
    </button>
  </form>

  <script>
    document.getElementById('payment_method').addEventListener('change', function() {
      document.getElementById('bank-group').style.display = this.value === 'bank_transfer' ? 'block' : 'none';
    });
  </script>
  <script src="checkout.js"></script>
</body>
</html>

Langkah 2: Handle Submit via JavaScript

Kirim data form ke API Bukasir dan redirect ke halaman pembayaran:

// checkout.js
const API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

document.getElementById('checkout').addEventListener('submit', async (e) => {
  e.preventDefault();

  const btn = document.getElementById('payBtn');
  const originalText = btn.innerHTML;
  btn.disabled = true;
  btn.innerHTML = '<i class="bi bi-arrow-repeat spin"></i> Memproses...';

  try {
    const form = new FormData(e.target);
    const data = Object.fromEntries(form);

    const res = await fetch('https://bukasir.biz.id/api/charge', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': API_KEY
      },
      body: JSON.stringify(data)
    });

    const result = await res.json();

    if (result.payment_url) {
      // Redirect ke halaman pembayaran
      window.location.href = result.payment_url;
    } else {
      alert('Gagal: ' + result.message);
      btn.disabled = false;
      btn.innerHTML = originalText;
    }
  } catch (err) {
    console.error('Error:', err);
    alert('Terjadi kesalahan. Silakan coba lagi.');
    btn.disabled = false;
    btn.innerHTML = originalText;
  }
});
Response Format API mengembalikan flat JSON. Sukses: {"order_id":"...","status":"pending","payment_method":"qris","amount":50000,"fee":350,"payment_url":"https://bukasir.biz.id/pay/slug/ORDER-001","expired_at":"..."}. Error: {"status":"error","message":"..."}. Tidak ada wrapper {success, data}.

Mode Multi-Payment (Opsional)

Jika Anda tidak ingin menentukan metode pembayaran di kode merchant, kirim /api/charge tanpa field payment_method. Customer akan melihat halaman pemilihan metode pembayaran (QRIS, GoPay, Bank Transfer) dan memilih sendiri:

// Mode multi-payment — payment_method tidak dikirim
const data = {
  order_id: 'ORDER-001',
  amount: 50000
  // payment_method: tidak dikirim → customer pilih sendiri
};

const res = await fetch('https://bukasir.biz.id/api/charge', { ... });
const result = await res.json();
// result.status = "awaiting_method"
// result.payment_url = "https://bukasir.biz.id/pay/slug/ORDER-001"

// Redirect customer ke payment_url — mereka pilih metode di sana
window.location.href = result.payment_url;
Catatan Mode Multi Metode yang tersedia: QRIS, GoPay, dan Bank Transfer (BNI, BRI, Mandiri, Permata, CIMB). Fee dihitung saat customer memilih metode pembayaran di halaman hosted. Status transaksi akan berubah dari awaiting_method ke pending setelah customer memilih.

Langkah 3: Handle Webhook

Buat file webhook.php untuk menerima notifikasi otomatis dari Bukasir saat status transaksi berubah. Bukasir meneruskan notifikasi Midtrans (tanpa signature_key) ke merchant, sehingga field menggunakan format Midtrans:

<?php
// webhook.php
header('Content-Type: application/json');

$payload = file_get_contents('php://input');
$data = json_decode($payload, true);

// 1. Verifikasi sumber request
$bukasirHeader = $_SERVER['HTTP_X_BUKASIR_WEBHOOK'] ?? '';
if ($bukasirHeader !== '1') {
    http_response_code(403);
    die(json_encode(['error' => 'Unauthorized']));
}

// 2. Proses data (format field Midtrans)
$orderId   = $data['order_id'];
$status    = $data['transaction_status'];  // settlement, pending, expire, cancel, deny
$amount    = $data['gross_amount'];        // string, e.g. "50000.00"
$payType   = $data['payment_type'];        // qris, gopay, bank_transfer, etc
$settled   = $data['settlement_time'] ?? null;

// 3. Update database Anda
$pdo = new PDO('mysql:host=localhost;dbname=yourdb', 'user', 'pass');
$stmt = $pdo->prepare('UPDATE orders SET status = :status WHERE order_id = :order_id');
$stmt->execute([
    ':status'   => $status,
    ':order_id' => $orderId
]);

// 4. Kirim response sukses
echo json_encode(['success' => true]);
?>
Penting Selalu verifikasi header X-Bukasir-Webhook: 1 untuk memastikan request berasal dari Bukasir. Jangan proses webhook tanpa verifikasi. Webhook menggunakan format field Midtrans: transaction_status (bukan status), gross_amount (bukan amount), payment_type (bukan payment_method).

Integrasi dengan JavaScript (Vanilla)

Untuk aplikasi frontend tanpa backend, Anda dapat menggunakan fetch API langsung:

// Simpan API Key di environment variable untuk production
const API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

async function createPayment({ order_id, amount, payment_method, bank }) {
  const body = { order_id, amount };
  if (payment_method) body.payment_method = payment_method;
  if (payment_method === 'bank_transfer' && bank) body.bank = bank;

  const response = await fetch('https://bukasir.biz.id/api/charge', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify(body)
  });

  return response.json();
}

async function checkStatus(orderId) {
  const response = await fetch(
    `https://bukasir.biz.id/api/status/${orderId}`,
    { headers: { 'X-API-Key': API_KEY } }
  );
  return response.json();
}

// Mode single — customer langsung ke QRIS
const result = await createPayment({
  order_id: 'ORDER-001',
  amount: 50000,
  payment_method: 'qris'
});

// Mode multi — customer pilih sendiri di halaman hosted
const result = await createPayment({
  order_id: 'ORDER-002',
  amount: 50000
  // payment_method tidak dikirim
});

if (result.payment_url) {
  window.location.href = result.payment_url;
} else {
  alert('Gagal: ' + result.message);
}

Integrasi dengan Node.js / Express

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

const app = express();
app.use(express.json());

const API_KEY = process.env.BUKASIR_API_KEY; // 64-char hex string

app.post('/api/charge', async (req, res) => {
  const response = await fetch('https://bukasir.biz.id/api/charge', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify(req.body)
  });
  const data = await response.json();
  res.json(data);
});

app.post('/webhook', (req, res) => {
  const bukasirHeader = req.headers['x-bukasir-webhook'];

  if (bukasirHeader !== '1') {
    return res.status(403).json({ error: 'Unauthorized' });
  }

  // Proses pembayaran - field menggunakan format Midtrans
  const { order_id, transaction_status, gross_amount, payment_type } = req.body;
  console.log(`Order ${order_id} status: ${transaction_status} amount: ${gross_amount}`);

  res.json({ success: true });
});

app.listen(3000);
Tips Untuk environment production, simpan API Key di environment variable, bukan di source code.

Testing Integrasi

Mode sandbox/live diatur per-project di dashboard (Project > Pengaturan). Tidak ada URL terpisah untuk sandbox — gunakan base URL yang sama:

// Base URL sama untuk sandbox maupun production
const BASE_URL = 'https://bukasir.biz.id';
const API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

// Sandbox/live ditentukan oleh pengaturan project di dashboard,
// bukan oleh URL yang berbeda.