Bài này hướng dẫn tích hợp chuyển khoản cho web end-to-end với BeePay — 5 bước, ~30 phút làm xong cho dev đã quen Node/PHP.
Bước 1: Tạo Connected System
Lấy API key tại id.beepay.vn/account. Gọi:
POST https://id.beepay.vn/api/systems
X-Api-Key: YOUR_API_KEY
Content-Type: application/json
{
"name": "Tên shop của bạn",
"payment_prefix": "SHOP",
"website": "https://yourshop.com"
}
payment_prefix = 2-10 ký tự A-Z0-9 (vd SHOP, BEELEARN) — sẽ là tiền tố mọi order_id.
Bước 2: Register Webhook
POST https://id.beepay.vn/api/webhooks
X-Api-Key: YOUR_API_KEY
{
"name": "Shop webhook",
"url": "https://yourshop.com/api/beepay-webhook",
"system_id": <id từ bước 1>,
"http_method": "POST",
"filter_banks": [],
"filter_type": "credit",
"payload_format": "standard"
}
BeePay trả về secret_key (48 ký tự hex) — chỉ trả 1 lần. Lưu vào .env làm BEEPAY_WEBHOOK_SECRET.
Bước 3: Generate VietQR khi tạo đơn
Khi user checkout, sinh order_id duy nhất + VietQR URL:
const orderId = 'SHOP' + Date.now().toString(36).toUpperCase()
const qrUrl = `https://qr.beepay.vn/img/${BANK}-${ACCOUNT}.png?amount=${amount}&addInfo=${orderId}`
Hiển thị QR + thông tin TK + nội dung CK lên trang. Bắt đầu polling /api/order/:id ngay khi modal mở (3s/lần).
Bước 4: Verify Webhook HMAC
Khi BeePay POST về /api/beepay-webhook, verify chữ ký bằng raw body:
import crypto from 'crypto'
function verify(rawBody, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
)
}
Sai chữ ký → return 401. Đúng → parse JSON, lookup order theo body.order_id, mark paid.
Bước 5: Polling status frontend
const interval = setInterval(async () => {
const r = await fetch(`/api/order/${orderId}`).then(r => r.json())
if (r.status === 'paid') {
clearInterval(interval)
showSuccess()
}
}, 3000)
Đừng bắt user click "Tôi đã chuyển" mới poll — tự động phát hiện. UX đúng là người dùng chuyển khoản xong nhìn QR, vài giây sau thấy "✓ Thành công" tự bật lên.
Done
Test bằng cách chuyển 1.000đ với content đúng order_id → kiểm tra /admin/orders/:id. Nếu webhook không tới, check log dashboard BeePay (id.beepay.vn/webhook-logs) — thường là URL chưa public-reachable (cần ngrok / tunnel cho dev).
Source code mẫu Next.js + Postgres tại SaaS Boilerplate.
