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
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;
}
});
{"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;
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]);
?>
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);
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.