เรียก API ตรวจสลิปจาก Node.js ตั้งแต่อัปโหลดจนอ่านผล
อ่าน 2 นาที
ไม่มีรูปภาพ
Node.js ตั้งแต่เวอร์ชัน 18 มี fetch, FormData และ Blob ในตัว ทำให้เรียก API ตรวจสลิปได้โดยไม่ต้องพึ่งไลบรารีเพิ่ม บทความนี้พาเขียนฟังก์ชันตรวจสลิปที่รองรับทั้งผลทันที ผลแบบเข้าคิว และข้อผิดพลาด โดยโค้ดอิงตัวอย่างและข้อกำหนดในคู่มือ API ของ PPay
เตรียมค่าที่ต้องใช้
คุณต้องมีสามอย่าง คือ API key ที่ขึ้นต้นด้วย ppk_ Base URL ของ API ที่ระบุในคู่มือ และรูปสลิปแบบ PNG หรือ JPG ขนาดไม่เกิน 5MB เก็บ key และ URL ไว้ใน environment variable เพราะการเรียก API ต้องทำจากเซิร์ฟเวอร์ของคุณเท่านั้น API นี้ไม่เปิด CORS จึงเรียกจากเบราว์เซอร์ไม่ได้ ซึ่งเป็นผลดีด้านความปลอดภัยอยู่แล้ว ดูเพิ่มที่ การดูแล API key
// .env (never commit this file to a public repository)
// PPAY_API_BASE=https://your-api-base-from-the-docs
// PPAY_API_KEY=ppk_...
ฟังก์ชันตรวจสลิปแบบรอผล
ส่งรูปด้วย multipart/form-data ที่ฟิลด์ชื่อ file และส่ง key ใน header Authorization แบบ Bearer
import { readFile } from "node:fs/promises";
async function verifySlip(path) {
const form = new FormData();
form.append("file", new Blob([await readFile(path)], { type: "image/jpeg" }), "slip.jpg");
const res = await fetch(process.env.PPAY_API_BASE + "/api/v1/verify", {
method: "POST",
headers: { Authorization: "Bearer " + process.env.PPAY_API_KEY },
body: form,
});
const data = await res.json();
if (res.status === 202) return { pending: true, jobId: data.jobId };
if (!res.ok) throw new Error(data.code + ": " + data.error);
return { pending: false, valid: data.valid, code: data.code, slip: data.slip };
}
จุดที่ควรเข้าใจ มีสามข้อ ข้อแรก อย่าตั้ง header Content-Type เองเมื่อใช้ FormData ให้ไลบรารีใส่ boundary ให้ ข้อสอง ต้องรองรับ HTTP 202 เสมอ เพราะช่วงระบบหนาแน่นจะรับเข้าคิวให้และตอบ jobId ข้อสาม HTTP 200 ไม่ได้แปลว่าสลิปถูกต้อง ให้ดู valid และ code เสมอ
ส่งรูปเป็น base64
ถ้ารูปอยู่ในหน่วยความจำเป็น base64 อยู่แล้ว เช่นมาจากบอทแชต ส่งเป็น JSON ได้ที่ฟิลด์ image (จะมี prefix data:image/png;base64, หรือไม่ก็ได้)
async function verifyBase64(b64) {
const res = await fetch(process.env.PPAY_API_BASE + "/api/v1/verify", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.PPAY_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ image: b64 }),
});
return res.json();
}
ส่งเข้าคิวพร้อมเลขออเดอร์
สำหรับร้านที่มีสลิปเข้าเยอะ ใช้ /api/v1/verify/async พร้อม reference (1-64 ตัวอักษร ใช้ได้ A-Z a-z 0-9 . _ : -) เพื่อให้ได้เลขนี้คืนมาใน Webhook
async function queueSlip(path, orderNo) {
const form = new FormData();
form.append("file", new Blob([await readFile(path)], { type: "image/jpeg" }), "slip.jpg");
form.append("reference", orderNo);
const res = await fetch(process.env.PPAY_API_BASE + "/api/v1/verify/async", {
method: "POST",
headers: { Authorization: "Bearer " + process.env.PPAY_API_KEY },
body: form,
});
if (res.status !== 202) throw new Error((await res.json()).code);
return (await res.json()).jobId; // store next to the order
}
เมื่อได้ jobId ให้บันทึกคู่กับออเดอร์ แล้วรับผลทาง Webhook (verification.completed) หรือดึงด้วย GET /api/v1/jobs/{jobId} ซึ่งคู่มือแนะนำให้เว้น 2-5 วินาทีต่อครั้งถ้า poll
หลังได้ valid ต้องทำอะไรต่อ
API ยืนยันว่าสลิปเป็นของจริงและไม่ซ้ำ แต่ไม่รู้ว่าออเดอร์ของคุณควรได้ยอดเท่าใด ให้เทียบเอง
function approve(order, result) {
if (!result.valid) return false;
if (result.slip.amount < order.total) return false; // underpaid: handle separately
// compare result.slip.receiver with your shop account details as well
return true;
}
หากผูกร้านค้าไว้ในระบบ ส่งฟิลด์ shop เพิ่มเพื่อให้ระบบตรวจผู้รับให้ ถ้าไม่ตรงจะได้ RECEIVER_MISMATCH อ่านเพิ่มที่ การตรวจบัญชีผู้รับ
ข้อควรระวังเฉพาะ Node.js
- ตั้ง timeout เช่น
AbortSignal.timeout(30000)ผ่านตัวเลือกsignalของ fetch เพื่อไม่ให้คำขอค้างตลอดไป - ห้ามพิมพ์ API key ลง log หรือแนบในข้อความ error
- จัดการ 429 โดยอ่าน header
retry-afterแล้วรอก่อนลองใหม่ - ไม่ลองซ้ำอัตโนมัติเมื่อผลเป็น invalid เพราะส่งซ้ำจะถูกหักเพิ่ม ดู การ retry โดยไม่เกิดผลซ้ำ
เช็กลิสต์
- Node.js 18 ขึ้นไป ใช้ fetch กับ FormData
- เก็บ key ใน environment variable
- รองรับ 200, 202 และ error ทุกชนิด
- เทียบยอดและผู้รับเองก่อนอนุมัติ
- เก็บ id หรือ jobId ไว้ตรวจย้อนหลัง
ดูตัวอย่างและรายละเอียดครบที่ คู่มือ API หรือเริ่มทดลองกับบัญชีของคุณได้ที่ สมัครสมาชิก