บทความทั้งหมด

ออกแบบการเรียก API ให้เหมาะกับข้อจำกัดอัตราการเรียก

อ่าน 2 นาที

ไม่มีรูปภาพ
ออกแบบการเรียก API ให้เหมาะกับข้อจำกัดอัตราการเรียก

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 — เรียกถี่เกิน ให้รอตามค่า header Retry-After (วินาที) แล้วลองใหม่ ไม่หักโควต้า
  • QUEUE_FULL — มีงานค้างในคิวครบ 100 งาน การรอเพียงไม่กี่วินาทีอาจไม่พอ ให้ชะลอการส่งชุดใหม่จนกว่างานที่ค้างจะเสร็จ

อย่าวนลูปลองใหม่ทันทีโดยไม่หน่วงเวลา เพราะจะยิ่งชนเพดานซ้ำ และอย่าลืมว่า INSUFFICIENT_BALANCE (402) ไม่ใช่เรื่องอัตราการเรียก ต้องแก้ด้วยการเติมโควต้าหรือเครดิต

ลดคำขอที่ไม่จำเป็น

  • ตรวจขนาดและชนิดไฟล์ฝั่งคุณก่อนส่ง (PNG หรือ JPG ไม่เกิน 5MB) เพื่อไม่เสียคำขอกับไฟล์ที่ถูกปฏิเสธอยู่แล้ว
  • อย่าส่งสลิปใบเดิมซ้ำเพียงเพราะผู้ใช้กดปุ่มรัว ๆ ให้ปิดปุ่มระหว่างรอและตรวจฝั่งคุณว่าออเดอร์นี้กำลังตรวจอยู่หรือไม่
  • แคชผลการสร้าง QR ที่ยอดเท่ากันไว้ชั่วคราว ถ้าใช้ endpoint สร้าง QR พร้อมเพย์ ซึ่งจำกัด 120 ครั้งต่อนาที ดูรายละเอียดการสร้าง QR ที่ หน้าสร้าง QR พร้อมเพย์
  • ตั้งการแจ้งเตือนเมื่อสัดส่วน 429 สูงผิดปกติ จะได้รู้ก่อนลูกค้าบ่น

เช็กลิสต์สรุป

  1. รู้เพดาน 60 ใบต่อนาทีและ 100 งานค้างต่อบัญชี
  2. เลือก verify, async หรือ batch ให้ตรงกับรูปแบบงาน
  3. มี throttle และคิวกลางฝั่งคุณ
  4. จัดการ 429 ด้วย Retry-After และ backoff
  5. ใช้ Webhook แทนการ poll
  6. ป้องกันผู้ใช้ส่งซ้ำจากหน้าจอ

ตัวเลขทั้งหมดอาจมีการปรับในอนาคต ควรเปิดตรวจ คู่มือ API ฉบับล่าสุดเป็นหลัก และดูแนวคิดเรื่อง retry เพิ่มเติมที่ การ retry โดยไม่เกิดผลซ้ำ

ลองตรวจสลิปอัตโนมัติกับร้านของคุณ

สมัครแล้วเริ่มใช้งานได้ภายในไม่กี่นาที

บทความอื่น ๆ