ภาพรวม
ยอดรับชำระรายวัน (บาท)
ตามช่องทาง
ตามประเภท
Site ยอดสูงสุด
รายการชำระเงิน
ตั้งค่าช่องทางชำระเงินต่อ Site
site ที่ไม่ได้ตั้ง merchant ของตัวเอง จะใช้ merchant กลางจาก env ของ gateway — secret เป็นแบบเขียนอย่างเดียว (ดูได้แค่ว่าตั้งแล้วหรือยัง)
API สำหรับ client
สำหรับระบบที่ต้องการรับชำระเงินผ่าน gateway (เช่น pssgogo, pss-ee, บริการใหม่ในอนาคต)
การยืนยันตัวตน
ทุก endpoint ใต้ /api/payments/* ต้องส่ง header:
Authorization: Bearer <token>
สร้าง/เพิกถอน token ได้ที่หน้า API Tokens — token แสดงครั้งเดียวตอนสร้าง
1. สร้างรายการชำระเงิน + QR
POST /api/payments/create
| field | ชนิด | คำอธิบาย |
|---|---|---|
purpose | string * | PARKING | WALLET | PACKAGE | LIFF_PAYMENT |
amountBaht | number * | ยอดเงิน (บาท) ขั้นต่ำ 1 |
siteId | number | site ของ pssgogo — ใช้เลือก merchant ตามที่ตั้งในหน้า "ตั้งค่า Site" |
referenceId | number | อ้างอิงรายการฝั่งระบบหลัก (เช่น parking transaction id) |
meta | object | context ที่ต้องใช้ตอน finalize (เช่น netFee, viewerLineId) |
ตอบกลับ:
{ "success": true, "qrImage": "data:image/png;base64,...", "mchOrderNo": "P2026...", "amountBaht": 40, "provider": "ksher" }
2. เช็คสถานะ
GET /api/payments/{mchOrderNo}/status
ตอบกลับ: { "success": true, "status": "...", "paid": true|false } โดย status =
PENDING | ยังไม่จ่าย (ระบบ reconcile กับผู้ให้บริการให้อัตโนมัติ — จ่ายแล้วจะ finalize จาก polling ได้เลย) |
PAID | จ่ายแล้ว + finalize สำเร็จ |
SUCCESS_PENDING_CONFIRM | เงินเข้าแล้วแต่ finalize ฝั่งระบบหลักยังไม่สำเร็จ (จะ retry) |
FAILED / NOT_FOUND | สร้าง QR ไม่สำเร็จ / ไม่พบรายการ |
3. ดึงรายการไป reconcile (สำหรับ pssgogo)
GET /api/payments/reconcile?state=unsettled
ดึงรายการที่ ธนาคารยืนยันจ่ายแล้ว แต่ยังปิดงานไม่สำเร็จ (เงินเข้าแล้วแต่ค้าง) — pssgogo ดึงไปปิดงานเองได้
| param | ค่า |
|---|---|
state | unsettled (default: จ่ายแล้วแต่ค้าง) · paid · all |
siteId, from, to | กรอง site / ช่วงวันที่ (YYYY-MM-DD) |
limit, offset | แบ่งหน้า (limit สูงสุด 500) |
ตอบกลับ:
{ "success": true, "state": "unsettled", "total": N, "count": N, "orders": [
{ "mchOrderNo", "provider", "purpose", "referenceId", "siteId", "amountSatang",
"status", "bankPaid": true, "bankConfirmedAt", "providerOrderNo", "meta",
"payment": { "bankRef", "approvalCode", "payerName", "fromBank", "amount" }, "createdAt" } ] }
ใช้ Bearer token เดียวกับ create/status · bankPaid=true คือธนาคารยืนยันจ่ายแล้ว (มี bankRef/approvalCode ให้ตรวจสอบ)
4. Callback แจ้งเงินเข้า (gateway → ระบบหลัก)
เมื่อเงินเข้า gateway จะ POST ไปที่ endpoint ของระบบหลัก (ตอนนี้คือ pssgogo /api/payments/gateway-callback) พร้อมลายเซ็น:
X-Gateway-Timestamp: <epoch ms> (คลาดได้ไม่เกิน 5 นาที — กัน replay)
X-Gateway-Signature: HMAC-SHA256(GATEWAY_CALLBACK_SECRET, "{timestamp}.{rawBody}") hex
body: { mchOrderNo, provider, purpose, referenceId, siteId, amountSatang, meta, providerOrderNo }
ฝั่งรับควรเชื่อแค่ mchOrderNo แล้วอ่านรายการจริงจาก DB, ตรวจลายเซ็นแบบ timing-safe, และต้อง idempotent — ตอบ { "ok": true } เมื่อ finalize สำเร็จ (gateway จะตอบ SUCCESS ให้ผู้ให้บริการหยุด retry)
ตัวอย่าง (curl)
curl -X POST /api/payments/create \
-H "Authorization: Bearer gwk_..." \
-H "Content-Type: application/json" \
-d '{"purpose":"PARKING","siteId":233,"amountBaht":40,"referenceId":12345,"meta":{"netFee":40}}'
ผู้ให้บริการ QR — ปัจจุบัน 3 เจ้า
gateway เลือกเจ้าตามที่ตั้งค่าแต่ละ site (แท็บ "ตั้งค่า Site") — API สำหรับ client ด้านบนใช้เหมือนกันทุกเจ้า
① Ksher — PromptPay QR
สร้าง QR: gateway เรียก Ksher native_pay (merchant per-site หรือ merchant กลาง)
เงินเข้า (webhook): Ksher POST → /api/ksher/notify · verify ลายเซ็น RSA-MD5 ด้วย public key ของ site · ตอบ {"result":"SUCCESS"}
② BBL (PromptPay) — CAPS ThaiQR
สร้าง QR: gateway POST → https://capsparkingapi.cityparking.asia/portal/qr (header x-api-key/x-req-sig) ได้ QR base64
ขาเข้า — ให้ทีม CAPS/Peaw ยิงเข้าที่ endpoint เหล่านี้ · ยืนยันตัวตนด้วย header x-caps-key: <secret ที่ตกลงกัน> · ตอบกลับ { responseMesg, responseCode } (000 = สำเร็จ)
1. Validation — เช็คก่อนให้ลูกค้าจ่าย
POST /api/bbl/validate
{ "billerId", "amount", "transTime", "transDate", "reference1"(=order), "reference2"(=card code), "reference3" }
→ 000 สำเร็จ · 209 ไม่พบ order · 211 ข้อมูลไม่ถูกต้อง/ยอดไม่ตรง · 215 token ไม่ถูกต้อง
2. Notification — แจ้งเมื่อเงินเข้า (finalize + ปิดตั๋ว)
POST /api/bbl/notify
{ "data": { "billerId", "amount", "reference1"(=order), "reference2"(=card code),
"fromBank", "approvalCode", "bankRef", "retryFlag", ... }, "type": "ThaiQR" }
→ 000 สำเร็จ (ปิดตั๋ว) · 209 ไม่พบ order · 211 ยังไม่สำเร็จ/ข้อมูลผิด (ส่งซ้ำได้) · 215 token ไม่ถูกต้อง
match order ด้วย reference1 (หมายเลข Order ที่ gateway ส่งไปตอนสร้าง QR) · responseCode: 000 success · 209 order not found · 211 invalid data · 215 invalid token
—
③ Stripe (PromptPay)
สร้าง QR: gateway → Stripe PaymentIntent (payment_method promptpay, amount เป็นสตางค์) → คืน PromptPay QR
เงินเข้า (webhook): ตั้งที่ Stripe Dashboard ให้ยิง event payment_intent.succeeded มาที่ /api/stripe/notify · verify ด้วย header Stripe-Signature (STRIPE_WEBHOOK_SECRET)
ต้องเปิดใช้ PromptPay ใน Stripe account ก่อน · match order ด้วย metadata.mchOrderNo
API Tokens
token สำหรับ client (เช่น pssgogo) ใช้เรียก /api/payments/* — ระบบเก็บเฉพาะ hash ค่าเต็มเห็นครั้งเดียวตอนสร้าง · key หลักจาก env (GATEWAY_API_KEY) ยังใช้ได้เสมอ