Merchant Integration · v1
คู่มือเชื่อมต่อระบบรับชำระเงินสำหรับร้านค้า — สร้างรายการ รับ QR PromptPay และรับแจ้งผลผ่าน webhook
ทุก request ที่ขึ้นต้นด้วย /v1/ ต้องแนบ API key ของร้านใน header:
X-Api-Key: gw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
gw_live_ ใช้ฝั่งเซิร์ฟเวอร์เท่านั้น ห้ามฝังในเว็บ/แอปฝั่งลูกค้า หากรั่วให้แจ้งเพื่อ rotate ทันที (key เดิมจะใช้ไม่ได้)POST /v1/payments ระบุยอดเงิน → ได้ checkout_url (หน้าจ่ายเงินพร้อม QR) และ qr_data_url (รูป QR)checkout_url หรือฝัง QR เอง — ลูกค้าสแกนจ่ายด้วยแอปธนาคาร (PromptPay)payment.paid มาที่ URL ที่ร้านตั้งไว้ (เซ็นด้วย HMAC)Idempotency-Key (สตริงไม่ซ้ำต่อ 1 ออร์เดอร์ เช่นเลขออร์เดอร์ของร้าน) — ยิงซ้ำด้วย key เดิมจะได้รายการเดิม ไม่เกิดรายการซ้ำ| Header | คำอธิบาย | |
|---|---|---|
| X-Api-Key | จำเป็น | API key ของร้าน |
| Idempotency-Key | จำเป็น | สตริงไม่ซ้ำต่อออร์เดอร์ (1–128 ตัวอักษร) |
| Content-Type | จำเป็น | application/json |
| Field | Type | คำอธิบาย | |
|---|---|---|---|
| amount | number | จำเป็น | ยอดเงิน (บาท) จำนวนบวก ≤ 1,000,000 ทศนิยมไม่เกิน 2 ตำแหน่ง |
| merchant_ref | string | จำเป็น | รหัสอ้างอิงของร้าน (1–64 ตัวอักษร) เช่นเลขออร์เดอร์ |
| description | string | ไม่บังคับ | คำอธิบายรายการ (≤255) |
| return_url | string | ไม่บังคับ | URL ให้ลูกค้ากลับหลังชำระ (ต้องเป็น http/https) |
curl -X POST https://gateway.alphaquestcom.com/v1/payments \
-H "X-Api-Key: gw_live_xxxxxxxx" \
-H "Idempotency-Key: ORDER-10023" \
-H "Content-Type: application/json" \
-d '{"amount": 300.00, "merchant_ref": "ORDER-10023"}'
{
"payment_id": "pay_01M1J9...",
"status": "pending",
"amount": 300,
"currency": "THB",
"checkout_url": "https://gateway.alphaquestcom.com/p/pay_01M1J9...",
"qr_data_url": "data:image/png;base64,iVBOR...",
"fee_amount": null,
"net_amount": null
}
fee_amount / net_amount เป็น null จนกว่าจะชำระสำเร็จ (ค่าธรรมเนียมคำนวณตอนจ่ายจริง)
curl https://gateway.alphaquestcom.com/v1/payments/pay_01M1J9... \
-H "X-Api-Key: gw_live_xxxxxxxx"
คืน object เดียวกับตอนสร้าง โดย status เป็นค่าใดค่าหนึ่ง:
pending รอชำระ · paid ชำระแล้ว · cancelled ยกเลิก · expired หมดอายุ (ไม่จ่ายใน 60 นาที)
ยกเลิกได้เฉพาะรายการที่ยังไม่ชำระ — ถ้าจ่ายไปแล้วจะได้ 409 already_paid
curl -X POST https://gateway.alphaquestcom.com/v1/payments/pay_01M1J9.../cancel \
-H "X-Api-Key: gw_live_xxxxxxxx"
ยอดสุทธิสะสมของร้าน (หลังหักค่าธรรมเนียม)
{ "balance": 1782.50, "currency": "THB" }
เมื่อสถานะรายการเปลี่ยน ระบบยิง POST ไปที่ webhook URL ของร้าน (ตั้งค่าตอนสมัคร) พร้อม headers:
| Header | ค่า |
|---|---|
| X-Gateway-Event | payment.paid หรือ payment.cancelled |
| X-Gateway-Signature | sha256=<hex> — HMAC-SHA256 ของ raw body ด้วย webhook secret |
payment.paid{
"event": "payment.paid",
"payment_id": "pay_01M1J9...",
"merchant_ref": "ORDER-10023",
"amount": 300,
"paid_amount": 300,
"fee_amount": 3,
"net_amount": 297,
"currency": "THB",
"paid_at": "2026-09-03T09:42:09.382Z"
}
payment.cancelled{
"event": "payment.cancelled",
"payment_id": "pay_01M1J9...",
"merchant_ref": "ORDER-10023",
"amount": 300,
"status": "cancelled" // หรือ "expired"
}
const crypto = require('crypto')
// rawBody = ตัว body ดิบ (Buffer/string) ก่อน JSON.parse
function verify(rawBody, signatureHeader, webhookSecret) {
const expected = 'sha256=' +
crypto.createHmac('sha256', webhookSecret)
.update(rawBody, 'utf8').digest('hex')
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(signatureHeader))
}
13.251.213.88 เสมอ — เปิดรับได้เฉพาะ IP นี้ · ควรตอบ 200 ทันทีที่รับได้ แล้วค่อยประมวลผลเบื้องหลังข้อผิดพลาดคืน JSON รูปแบบ { "error": "...", "code": "..." }
| HTTP | code | ความหมาย |
|---|---|---|
| 401 | invalid_api_key | API key ผิดหรือร้านถูกปิด |
| 403 | merchant_suspended | ร้านถูกระงับ |
| 422 | missing_idempotency_key | ไม่ได้แนบ Idempotency-Key |
| 422 | invalid_amount | amount ไม่ถูกต้อง (บวก ≤ 1,000,000 ทศนิยม ≤ 2) |
| 409 | idempotency_conflict | ใช้ Idempotency-Key เดิมแต่ยอดเงินไม่ตรง |
| 409 | already_paid | ยกเลิกรายการที่ชำระแล้วไม่ได้ |
| 404 | — | ไม่พบรายการ (route not found) |
| 502 | — | ระบบชำระเงินปลายทางขัดข้องชั่วคราว |