ออกแบบการเรียก API ให้เหมาะกับข้อจำกัดอัตราการเรียก
อ่าน 2 นาที
ไม่มีรูปภาพ
API ทุกตัวมีเพดานการเรียก ถ้าออกแบบระบบโดยไม่คิดถึงเพดานนี้ ช่วงที่ร้านขายดีหรือมีแคมเปญใหญ่คือช่วงที่ระบบตรวจสลิปของคุณจะสะดุดพอดี บทความนี้อธิบายตัวเลขข้อจำกัดตามคู่มือ API ของ PPay และวิธีออกแบบฝั่งผู้เรียกให้ลื่นไหลแม้มีสลิปเข้ามาพร้อมกันจำนวนมาก
ข้อจำกัดที่ควรรู้ก่อนเขียนโค้ด
ตามคู่มือ มีตัวเลขสำคัญดังนี้
| รายการ | ค่าตามคู่มือ |
|---|---|
| ความถี่การเรียก | 60 ใบต่อนาทีต่อบัญชี (รวม verify, async และ batch) เกินจะได้ 429 พร้อม Retry-After |
| ขนาดรูป | ไม่เกิน 5MB ต่อใบ เฉพาะ PNG หรือ JPG |
| batch | สูงสุด 10 ไฟล์ และรวมไม่เกิน 25MB ต่อคำขอ |
| งานค้างในคิว | สูงสุด 100 งานต่อบัญชี (queued และ processing) |
| สร้าง QR พร้อมเพย์ | 120 ครั้งต่อนาทีต่อบัญชี และไม่หักโควต้า |
ข้อสังเกตสำคัญคือ 60 ใบต่อนาทีนับรวมทั้งสามรูปแบบการส่ง การเปลี่ยนจาก verify มาเป็น batch จึงไม่ได้เพิ่มเพดานต่อนาที แต่ช่วยลดจำนวนคำขอ HTTP และทำให้ฝั่งคุณไม่ต้องรอผลทีละใบ
เลือกรูปแบบการเรียกให้ตรงกับงาน
- ลูกค้าส่งสลิปทีละใบและรอผลหน้าจอ ใช้
/api/v1/verifyแบบรอผล และรองรับ HTTP 202 เสมอ เพราะช่วงหนาแน่นระบบอาจรับเข้าคิวให้เอง - ระบบหลังบ้านประมวลผลเป็นรอบ เช่นสลิปที่สะสมมาทั้งวัน ใช้
/api/v1/verify/batchทีละไม่เกิน 10 ใบ แล้วรับผลทาง Webhook - ต้องจับคู่กับออเดอร์ ใช้
/api/v1/verify/asyncพร้อมreferenceเป็นเลขออเดอร์
การรับผลทาง Webhook ดีกว่าการ poll เพราะไม่ต้องเสียคำขอสอบถามสถานะ ถ้าจำเป็นต้อง poll คู่มือแนะนำให้เว้น 2-5 วินาทีต่อครั้ง
จัดคิวฝั่งคุณเอง ไม่ให้ชนเพดาน
วิธีที่ได้ผลคือมีตัวคุมอัตรา (throttle) ฝั่งผู้เรียก แทนที่จะรอให้เจอ 429 แล้วค่อยถอย ตัวอย่างแนวคิดง่าย ๆ ด้วย Node.js คือกำหนดช่องว่างขั้นต่ำระหว่างคำขอ
// simple spacing: at most ~50 requests per minute (headroom below 60)
const GAP_MS = 1200;
let last = 0;
async function throttled(fn) {
const wait = Math.max(0, last + GAP_MS - Date.now());
last = Date.now() + wait;
if (wait) await new Promise(function (r) { setTimeout(r, wait); });
return fn();
}
ตั้งค่าให้ต่ำกว่าเพดานเล็กน้อยเพื่อเผื่อช่องว่าง หากระบบของคุณมีหลายเซิร์ฟเวอร์หรือหลายโปรเซสที่ใช้ API key เดียวกัน ตัวนับต้องอยู่ที่ศูนย์กลาง (เช่น คิวงานกลาง) เพราะเพดานนับต่อบัญชี ไม่ใช่ต่อเครื่อง
เมื่อเจอ 429 ทำอย่างไร
มี 429 สองแบบที่ความหมายต่างกัน
RATE_LIMITED— เรียกถี่เกิน ให้รอตามค่า headerRetry-After(วินาที) แล้วลองใหม่ ไม่หักโควต้าQUEUE_FULL— มีงานค้างในคิวครบ 100 งาน การรอเพียงไม่กี่วินาทีอาจไม่พอ ให้ชะลอการส่งชุดใหม่จนกว่างานที่ค้างจะเสร็จ
อย่าวนลูปลองใหม่ทันทีโดยไม่หน่วงเวลา เพราะจะยิ่งชนเพดานซ้ำ และอย่าลืมว่า INSUFFICIENT_BALANCE (402) ไม่ใช่เรื่องอัตราการเรียก ต้องแก้ด้วยการเติมโควต้าหรือเครดิต
ลดคำขอที่ไม่จำเป็น
- ตรวจขนาดและชนิดไฟล์ฝั่งคุณก่อนส่ง (PNG หรือ JPG ไม่เกิน 5MB) เพื่อไม่เสียคำขอกับไฟล์ที่ถูกปฏิเสธอยู่แล้ว
- อย่าส่งสลิปใบเดิมซ้ำเพียงเพราะผู้ใช้กดปุ่มรัว ๆ ให้ปิดปุ่มระหว่างรอและตรวจฝั่งคุณว่าออเดอร์นี้กำลังตรวจอยู่หรือไม่
- แคชผลการสร้าง QR ที่ยอดเท่ากันไว้ชั่วคราว ถ้าใช้ endpoint สร้าง QR พร้อมเพย์ ซึ่งจำกัด 120 ครั้งต่อนาที ดูรายละเอียดการสร้าง QR ที่ หน้าสร้าง QR พร้อมเพย์
- ตั้งการแจ้งเตือนเมื่อสัดส่วน 429 สูงผิดปกติ จะได้รู้ก่อนลูกค้าบ่น
เช็กลิสต์สรุป
- รู้เพดาน 60 ใบต่อนาทีและ 100 งานค้างต่อบัญชี
- เลือก verify, async หรือ batch ให้ตรงกับรูปแบบงาน
- มี throttle และคิวกลางฝั่งคุณ
- จัดการ 429 ด้วย Retry-After และ backoff
- ใช้ Webhook แทนการ poll
- ป้องกันผู้ใช้ส่งซ้ำจากหน้าจอ
ตัวเลขทั้งหมดอาจมีการปรับในอนาคต ควรเปิดตรวจ คู่มือ API ฉบับล่าสุดเป็นหลัก และดูแนวคิดเรื่อง retry เพิ่มเติมที่ การ retry โดยไม่เกิดผลซ้ำ