ออกแบบสถาปัตยกรรมบอท LINE ที่รับรูปสลิปแล้วตรวจอัตโนมัติ
อ่าน 2 นาที
ไม่มีรูปภาพ
ร้านที่ขายผ่านแชตมักให้ลูกค้าส่งรูปสลิปทาง LINE แล้วแอดมินนั่งตรวจทีละใบ ซึ่งช้าและพลาดง่ายในช่วงที่ลูกค้าเยอะ บอทที่รับรูปแล้วส่งตรวจอัตโนมัติช่วยได้มาก แต่ถ้าออกแบบไม่ดี จะเจอปัญหาเช่นตอบลูกค้าไม่ทัน ตรวจสลิปซ้ำ หรืออนุมัติผิดออเดอร์ บทความนี้เสนอสถาปัตยกรรมระดับแนวคิด ไม่ผูกกับเฟรมเวิร์กใด โดยใช้ความสามารถของ API ตรวจสลิปตามคู่มือของ PPay และ LINE Messaging API ในหลักการทั่วไป
ภาพรวมของระบบ
ระบบประกอบด้วยส่วนหลักต่อไปนี้
- LINE Messaging API Webhook — รับเหตุการณ์ข้อความและรูปจากลูกค้า
- ตัวรับ (receiver) — ตรวจลายเซ็นของ LINE ตามเอกสารของ LINE ตอบกลับเร็ว แล้วโยนงานเข้าคิวภายใน
- Worker — ดาวน์โหลดรูปจาก LINE ตรวจชนิดและขนาด แล้วเรียก API ตรวจสลิป
- ฐานข้อมูลออเดอร์ — เก็บออเดอร์ สถานะ และผลการตรวจ
- ตัวรับ Webhook ของ PPay — รับผลตรวจแบบคิว ตรวจลายเซ็น แล้วอัปเดตออเดอร์
- ตัวตอบกลับ — ส่งข้อความกลับลูกค้าผ่าน LINE
หัวใจคือแยก "รับเรื่อง" ออกจาก "ประมวลผล" เพราะ Webhook ของแพลตฟอร์มแชตต้องตอบเร็ว ขณะที่การตรวจสลิปและเทียบออเดอร์ใช้เวลามากกว่า
ผูกลูกค้ากับออเดอร์ให้ชัด
ปัญหาแรกคือบอทรู้ได้อย่างไรว่าสลิปใบนี้เป็นของออเดอร์ไหน ทางเลือกที่ใช้ได้ เช่น ให้ลูกค้าพิมพ์เลขออเดอร์ก่อนส่งรูป ให้บอทจำสถานะว่ากำลังรอสลิปของออเดอร์ล่าสุดที่รอชำระ หรือให้ลูกค้ากดปุ่มเลือกออเดอร์จากรายการ สิ่งสำคัญคือกำหนดสถานะการสนทนาไว้ในฐานข้อมูล ไม่เก็บไว้ในหน่วยความจำของโปรเซส เพราะถ้าบอทรีสตาร์ต สถานะจะหาย
เมื่อรู้เลขออเดอร์แล้ว ให้ส่งไปกับการตรวจสลิปด้วยฟิลด์ reference ของ /api/v1/verify/async (1-64 ตัวอักษร ใช้ได้ A-Z a-z 0-9 . _ : -) ระบบจะส่งค่านี้คืนมาในผลลัพธ์และ Webhook ทำให้จับคู่กลับได้แม่นยำ
ขั้นตอนการทำงาน
- ลูกค้าส่งรูปมาที่ LINE ตัวรับตรวจลายเซ็นของ LINE บันทึกเหตุการณ์ แล้วตอบ 200 ทันที
- Worker ดึงรูปจาก LINE ตรวจว่าเป็น PNG หรือ JPG และไม่เกิน 5MB
- บอทตอบกลับสั้น ๆ ว่า "ได้รับสลิปแล้ว กำลังตรวจสอบ" เพื่อให้ลูกค้าไม่ต้องส่งซ้ำ
- Worker เรียก
POST /api/v1/verify/asyncพร้อมreferenceเป็นเลขออเดอร์ ได้jobIdกลับมา บันทึกคู่กับออเดอร์ - เมื่อตรวจเสร็จ PPay ส่ง
verification.completedมาที่ Webhook ของคุณ ตัวรับตรวจลายเซ็นและกันซ้ำด้วย id ของเหตุการณ์ - ระบบเทียบยอดและผู้รับกับออเดอร์ ถ้าถูกต้องเปลี่ยนสถานะเป็นชำระแล้ว และส่งข้อความยืนยันผ่าน LINE
- ถ้าไม่ผ่านหรือต้องคนช่วย ส่งข้อความอธิบายตามสาเหตุ หรือเปิดเคสให้แอดมิน
การใช้แบบคิวมีประโยชน์คือไม่ต้องค้างรอผลต่อรูป และรองรับช่วงที่ลูกค้าส่งสลิปพร้อมกันจำนวนมาก (ข้อจำกัดต่อบัญชีคือ 60 ใบต่อนาที และงานค้างสูงสุด 100 งาน) ถ้าอยากได้ผลในคำขอเดียว ใช้ /api/v1/verify ได้เช่นกัน แต่ต้องรองรับ 202 เสมอ
เนื่องจากบอทมักได้รับรูปเป็นไบต์ในหน่วยความจำ คู่มือรองรับการส่งเป็น base64 ผ่านฟิลด์ image แบบ JSON ซึ่งสะดวกสำหรับกรณีนี้
จุดเสี่ยงที่ต้องออกแบบไว้
| ความเสี่ยง | แนวทางรับมือ |
|---|---|
| ลูกค้าส่งรูปซ้ำหลายใบ | จำกัดจำนวนรูปต่อออเดอร์ และตอบรับทันทีว่าได้รับแล้ว |
| รูปที่ไม่ใช่สลิป หรือรูปถูกบีบอัด | ตรวจชนิดและขนาดก่อนส่ง และบอกลูกค้าให้ส่งรูปต้นฉบับจากแอปธนาคาร |
| ผลตรวจมาซ้ำหรือล่าช้า | handler แบบ idempotent ใช้ id ของเหตุการณ์ ดู การรับ webhook ซ้ำ |
| สลิปใบเดียวใช้กับหลายออเดอร์ | เก็บเลขอ้างอิงสลิปที่ใช้แล้ว ปฏิเสธถ้าซ้ำ และผล DUPLICATE_SLIP |
| โอนเกินหรือโอนขาด | กำหนดนโยบายชัดเจน เช่น ขาดให้โอนเพิ่ม เกินให้คืนส่วนต่างหลังตรวจสอบ |
| API ขัดข้อง | ระบบรับเข้าคิวและลองใหม่เอง ถ้าปิดงานเป็น SERVICE_UNAVAILABLE จะคืนโควต้า และบอทส่งเคสให้คนตรวจ |
ข้อความตอบลูกค้า
ข้อความของบอทเป็นส่วนหนึ่งของประสบการณ์ลูกค้า ควรมีทุกกรณีและบอกขั้นตอนถัดไป
- ผ่าน — ยืนยันยอดและบอกว่าจะดำเนินการต่อภายในเวลาเท่าใด (ตามนโยบายร้านคุณ)
- ไม่พบรายการ — อาจเพิ่งโอน ให้รอ 1-2 นาทีแล้วส่งใหม่ หรือส่งรูปต้นฉบับ
- สลิปซ้ำ — แจ้งว่าสลิปใบนี้ถูกใช้แล้ว และให้ติดต่อแอดมินหากเข้าใจผิด
- ยอดไม่ครบ — แจ้งยอดที่ต้องโอนเพิ่ม
- ระบบขัดข้อง — ขออภัยและแจ้งว่าทีมงานจะตรวจให้ ไม่ให้ลูกค้ารู้สึกว่าเป็นความผิดของตน
อ่านแนวทางสร้างประสบการณ์ที่ดูน่าเชื่อถือเพิ่มเติมที่ ขั้นตอนรับชำระสำหรับผู้ขายใน LINE OA และ ประสบการณ์การชำระเงินของลูกค้า
ความปลอดภัยและข้อมูล
- เก็บ API key ของ PPay, channel secret และ access token ของ LINE ใน secret manager ไม่ใส่ในโค้ดหรือ log
- ตรวจลายเซ็นของทั้งสองทิศทาง คือ LINE มาที่บอท และ PPay มาที่ตัวรับผล
- เก็บรูปสลิปในที่เก็บแบบไม่เปิดสาธารณะ และกำหนดอายุการเก็บตามนโยบายความเป็นส่วนตัวของร้านคุณ
- เก็บ id และ jobId ของทุกรายการเพื่อตรวจสอบย้อนหลัง
- แยก API key ของบอทออกจากระบบอื่น เพื่อเพิกถอนได้โดยไม่กระทบส่วนอื่น
เช็กลิสต์สรุป
- ตอบ Webhook ของ LINE เร็ว แล้วทำงานหนักใน worker
- เก็บสถานะการสนทนาและออเดอร์ในฐานข้อมูล
- ส่ง reference เป็นเลขออเดอร์ทุกครั้ง
- กันซ้ำด้วย id ของเหตุการณ์และเลขอ้างอิงสลิป
- เทียบยอดและผู้รับเองก่อนอนุมัติ
- มีทางสำรองให้แอดมินตรวจเมื่อระบบขัดข้อง
- มีข้อความตอบลูกค้าครบทุกกรณี
รายละเอียดของ endpoint, Webhook และข้อจำกัดอยู่ใน คู่มือ API ถ้าอยากเริ่มจากแนวทางที่ไม่ต้องเขียนโค้ด ดูที่ หน้าเริ่มต้นใช้งาน