สร้าง WhatsApp send guard 24 ชั่วโมงสำหรับข้อความตอบกลับใน queue
ข้อความตอบกลับ WhatsApp ใน queue อาจข้ามกรอบ 24 ชั่วโมงระหว่างรออนุมัติ retry หรือรอ worker รับ job send guard ที่เชื่อถือได้ต้องอ่าน state จาก server ใหม่ก่อนส่งจริง คำนวณเวลาหมดอายุจากข้อความผู้ใช้ล่าสุดที่ตรวจสอบแล้ว และหยุด free-form text ที่หมดอายุ ใช้decision tree ของ service และ utility messageสำหรับ category และ pricing ส่วนบทความนี้เน้นขอบเขตการทำงานที่ป้องกันการส่งผิด
ประเด็นสำคัญ
- เก็บเวลาหมดอายุสองค่าและ
state_versionที่เพิ่มขึ้นเสมอ ไม่ใช้ boolean เพียงตัวเดียว - เฉพาะ inbound message จากผู้ใช้ที่ตรวจสอบและ deduplicate แล้วเท่านั้นที่รีเซ็ตกรอบ 24 ชั่วโมง
- หลังรับ job แล้ว worker ต้องอ่าน state ใหม่ใน transaction หรือ lock เดียวกันก่อนเลือกเส้นทางส่ง
- draft ที่หมดอายุต้องหยุดและ route ใหม่ ห้ามเปลี่ยนเป็น template โดยเงียบ ๆ
- ทดสอบ event ซ้ำ event ผิดลำดับ worker ที่แข่งขันกัน และขอบเขตระดับวินาที
สร้าง WhatsApp send guard รอบข้อความตอบกลับใน queue
หน้าราคา Business Platform ทางการระบุว่า ข้อความผู้ใช้จะเปิดหรือรีเซ็ตกรอบ 24 ชั่วโมง ในชั้น implementation ให้ใช้ขอบเขตสิทธิ์นี้เป็นเงื่อนไขสุดท้ายก่อนส่ง ส่วน category และการเปลี่ยน pricing เดือนตุลาคม 2026 อธิบายไว้ในคู่มือที่มีอยู่แล้ว จึงไม่ทำซ้ำที่นี่
สำหรับทุก job ใน queue ตัว sender ต้องตอบคำถาม implementation สามข้อ:
- อ่าน state version ล่าสุดหรือยัง worker เก่าห้ามเขียนทับกรอบที่อัปเดตแล้ว
- กรอบยังเปิดตอนส่งจริงหรือไม่ ห้ามใช้ผลประเมินเดิมจากตอนสร้างหรืออนุมัติ draft
- เส้นทางส่งที่เลือกยังได้รับอนุญาตหรือไม่ หลังกรอบปิด ใช้ได้เฉพาะ template ที่อนุมัติและตรง intent จริง มิฉะนั้นให้หยุดและคืนให้เจ้าหน้าที่
เก็บนาฬิกาสองตัวแทนสถานะเดียว
timestamp ที่ชัดเจนช่วยให้ retry, delayed job และการส่งต่อ agent ประเมินสถานะใหม่ได้
| ค่าที่เก็บ | สิ่งที่เปิดหรือรีเซ็ต | สิ่งที่ควบคุม |
|---|---|---|
service_window_expires_at | inbound message ทุกข้อความจากผู้ใช้ | อนุญาต non-template service reply หรือไม่ |
free_entry_expires_at | ผู้ใช้เข้าจากโฆษณา Click-to-WhatsApp หรือปุ่ม Facebook Page CTA ที่เข้าเงื่อนไข | ยกเว้นค่าการส่งเป็นเวลา 72 ชั่วโมงหรือไม่ |
last_user_message_id | inbound message ที่ยอมรับทุกข้อความ | idempotency และหลักฐาน audit |
state_version | event ที่เปลี่ยนสถานะทุกครั้ง | ป้องกัน job เก่าเขียนทับสถานะใหม่ |
free entry point 72 ชั่วโมงไม่ใช่กรอบอนุญาตให้ตอบกลับ 72 ชั่วโมง ข้อความใหม่ของผู้ใช้อาจรีเซ็ตสิทธิ์ 24 ชั่วโมง แต่เวลายกเว้นค่าการส่งยังเป็นขอบเขตอีกชุดหนึ่ง
สร้าง send guard
ตัวอย่าง TypeScript ต่อไปนี้เป็น model ใน application ไม่ใช่ schema payload ของ Meta และแยกสิทธิ์ส่งออกจากค่าบริการที่คาดไว้:
type WindowState = {
serviceWindowExpiresAt: Date | null;
freeEntryExpiresAt: Date | null;
};
function evaluateWhatsAppSend(state: WindowState, now: Date) {
const serviceWindowOpen =
state.serviceWindowExpiresAt !== null && now < state.serviceWindowExpiresAt;
const freeEntryActive =
state.freeEntryExpiresAt !== null && now < state.freeEntryExpiresAt;
return {
maySendNonTemplate: serviceWindowOpen,
expectedDeliveryCharge: serviceWindowOpen && !freeEntryActive,
requiredPath: serviceWindowOpen ? "service" : "approved_template",
} as const;
}
ใช้ผลลัพธ์เป็นด่านสุดท้ายก่อนส่ง ไม่ใช่แค่ข้อความใน UI คำตอบที่ร่างเวลา 10:00 อาจอยู่ใน approval queue จนกรอบปิด เมื่อ worker รับ job ต้องอ่าน state ปัจจุบันใหม่แล้วเลือก:
- ส่ง non-template service reply ขณะที่กรอบยังเปิด
- เปลี่ยนเป็น template ที่อนุมัติแล้ว หากกรอบปิดและเจตนาตรงกับ template
- หยุดส่งและคืนบทสนทนาให้เจ้าหน้าที่ หากทั้งสองทางใช้ไม่ได้
อย่าเปลี่ยน free-form text เป็น template แบบเงียบ ๆ และอย่าตัดเนื้อหาให้พอดี template เพราะ category, variables และการอนุมัติเป็นคนละ contract
อย่ายืดกรอบด้วย event ที่ไม่ถูกต้อง
มีเพียงข้อความที่ผู้ใช้ส่งเท่านั้นที่รีเซ็ตกรอบได้ Delivery receipt, status update, draft ของ agent, internal note, retry และ echo ของข้อความฝั่งธุรกิจห้ามยืดเวลา
ลำดับการประมวลผลที่แนะนำ:
- ตรวจสอบ provider webhook ก่อนเปลี่ยน state
- ตัดข้อมูลซ้ำด้วย message ID หรือ event ID ที่คงที่
- ยืนยันว่าเป็น inbound message จากผู้ใช้ ไม่ใช่ receipt หรือ echo
- ตั้ง
service_window_expires_atเป็นเวลาข้อความที่ยอมรับบวก 24 ชั่วโมง - สร้างเวลา free entry 72 ชั่วโมงเฉพาะ referral ที่เข้าเงื่อนไข
- เพิ่ม
state_versionและเก็บ event ต้นทางเพื่อ audit - ประเมินนาฬิกาทั้งสองใหม่ก่อนส่งทุกครั้ง
อย่าบวก 24 ชั่วโมงต่อจากเวลาหมดอายุเดิม หากผู้ใช้ส่งตอน 09:00 และ 12:00 เวลาหมดอายุใหม่คือ 12:00 ของวันถัดไป
ทดสอบขอบเขต queue และลำดับ event
ใช้ fixed clock เพื่อทดสอบขอบเขตระดับหนึ่งวินาทีได้ซ้ำ
| สถานการณ์ | ผลที่คาดหวัง |
|---|---|
| ผู้ใช้ส่ง 10:00; ตอบ 09:59:59 วันถัดไป | อนุญาต non-template reply |
| ตอบตรง 10:00 วันถัดไป | ถือว่ากรอบปิดแล้ว |
| ผู้ใช้ส่งใหม่ 09:50 วันถัดไป | รีเซ็ตหมดอายุเป็น 09:50 ของอีกวัน |
| อนุมัติก่อนหมดอายุ แต่ worker รับ job หลังหมดอายุ | block และ route ใหม่ |
| ข้อความผู้ใช้เดียวกันถูกส่งมาสองครั้ง | deduplicate แล้วเปลี่ยน state เพียงครั้งเดียว |
| ข้อความเก่ามาถึงหลังข้อความใหม่ | เก็บเวลาหมดอายุที่ใหม่กว่า ไม่ย้อน state |
| worker สองตัวรับข้อความตอบกลับเดียวกัน | มีเพียงตัวเดียวที่ผ่าน version check และส่ง |
หลังขึ้น production ให้เทียบผลคาดการณ์กับ status และ pricing record ทางการ คู่มือติดตามค่าบริการ service messageแยกปริมาณส่งถึงออกจากอัตราตามตลาด หากกำลังเลือกระหว่าง Meta Business Agent กับ AI ของคุณเอง ให้อ่านการเปรียบเทียบราคาและสถาปัตยกรรม
UnifyPort เหมาะตรงไหน
state machine ด้านบนใช้กับ WhatsApp Business Platform ทางการ อินเทอร์เฟซที่ไม่เป็นทางการของ UnifyPort เป็นอีกเส้นทางสำหรับ messaging account ปกติ และไม่ให้สถานะกรอบบริการลูกค้าหรือ Pricing Analytics ของ Meta
ในเส้นทางนี้ inbound message ของ WhatsApp จะมาถึงเป็น event มาตรฐาน message.received หาก webhook endpoint มี signing_secret ให้ตรวจ X-Device-Timestamp และ X-Device-Signature กับ raw request body ก่อนประมวลผล การตอบกลับมาตรฐานที่รองรับใช้ POST /v1/messages ดูรายละเอียดในเอกสาร webhook delivery และ signatureกับเอกสาร event message.received
อย่านำ event ของ UnifyPort เข้า state machine คิดราคา Cloud API แล้วบอกว่า Meta เป็นผู้จัด category หากใช้สองเส้นทางพร้อมกัน ให้เก็บ transport หรือ control_plane และแยก ledger
ข้อจำกัดและสิ่งที่ต้องแลก
เลือก WhatsApp Business Platform ทางการเมื่อจำเป็นต้องใช้ template ที่อนุมัติ, campaign, Click-to-WhatsApp attribution, analytics ของ Meta หรือบริการจาก BSP Record ทางการเป็นแหล่งข้อมูลจริงของค่าบริการ delivery ทางการ
อินเทอร์เฟซที่ไม่เป็นทางการไม่อนุมัติ template, ไม่ยืดกรอบ Meta, ไม่ให้ Pricing Analytics และไม่เปลี่ยนนโยบาย WhatsApp คุณค่าของมันคือเส้นทางสำหรับ messaging account ปกติและ event หลายแพลตฟอร์มที่เป็นรูปแบบเดียวกัน ทั้งสองเส้นทางยังต้องมี idempotency, concurrency control และ audit log
ราคาและกฎอาจเปลี่ยนแปลง ตรวจเอกสารทางการอีกครั้งก่อนวันที่ 1 ตุลาคม และอย่า hard-code อัตราที่ใช้วางแผนไว้ใน transition logic
FAQ
send guard ควรใช้ timestamp ใด
ใช้เวลาของข้อความผู้ใช้ล่าสุดที่ตรวจสอบและระบบยอมรับแล้ว ไม่ใช้เวลารับ webhook เวลาสร้าง job หรือตัวนับถอยหลังใน UI
webhook ที่มาผิดลำดับทำให้กรอบสั้นลงหรือไม่
ไม่ควร ใช้ event ID ที่คงที่เพื่อ deduplicate และอัปเดตเวลาหมดอายุกับ state_version เมื่อ inbound message ใหม่กว่า record ปัจจุบันเท่านั้น
ข้อความตอบกลับใน queue หมดอายุก่อนส่งต้องทำอย่างไร
หยุด free-form text และ route ใหม่ ใช้ template ได้เฉพาะเมื่อ intent ตรงกับ template ที่อนุมัติจริง มิฉะนั้นคืนบทสนทนาให้เจ้าหน้าที่
แปลง free-form text ที่หมดอายุเป็น template อัตโนมัติได้ไหม
ห้ามแปลงโดยเงียบ ๆ category, variable และ approval ของ template เป็น contract แยกที่ต้องเลือกและตรวจสอบอย่างชัดเจน
ป้องกัน event ซ้ำทำให้ส่งสองครั้งอย่างไร
บันทึก message ID หรือ event ID แล้วให้ worker ตรวจ idempotency key และ state_version ใน transaction หรือ lock ก่อนส่ง
ขั้นตอนถัดไป
เริ่มจาก inbound boundary ที่ถูกต้อง อ่านเอกสาร webhook delivery และ signature แล้วทดสอบว่า event ซ้ำหรือมาผิดลำดับไม่ยืดกรอบส่งโดยไม่ตั้งใจ
แหล่งข้อมูล
ตรวจสอบแหล่งข้อมูลทางการเมื่อวันที่ 27 กรกฎาคม 2026: