โหลดข้อความ WhatsApp เก่าด้วยคำขอประวัติแบบออนดีมานด์
หากต้องการโหลดข้อความ WhatsApp ที่เก่ากว่าผ่าน UnifyPort ให้สมัครรับ conversation.history ก่อน แล้วส่งคำขอโดยใช้ข้อความที่บันทึกไว้เป็นจุดอ้างอิง before การตอบกลับ HTTP ไม่มีเนื้อหาข้อความ: 202 และ status: accepted หมายถึงรับคำขอแล้วเท่านั้น ประวัติที่มีจะมาถึงแบบอะซิงโครนัส จึงควรสร้างปุ่ม “โหลดข้อความก่อนหน้า” ที่ทำงานแบบ best-effort ไม่ใช่เครื่องมือส่งออกประวัติครบถ้วน หรือวงรอบแบ่งหน้าที่อ้างว่ารู้จุดสิ้นสุดของประวัติ
ประเด็นสำคัญ
- การทำงานนี้รองรับแชตส่วนตัวของ
provider=whatsappไม่รองรับกลุ่ม ช่อง หรือwhatsapp-protocol - เตรียมการสมัครรับเหตุการณ์และการจัดเก็บถาวรก่อนส่งคำขอ
- เลื่อนจุดอ้างอิงด้วย ID เวลาในการส่ง และทิศทางของข้อความเนื้อหาจริง
- ข้อมูลอาจมาหลายชุด ซ้ำ ล่าช้า หรือไม่มาเลย การไม่มี callback ไม่ได้แปลว่าเสร็จแล้ว
- ใช้ข้อความเก่าเติมไทม์ไลน์ ไม่ใช่กระตุ้นระบบตอบกลับข้อความใหม่
แยกการรับคำขอออกจากผลลัพธ์ประวัติ
เอกสารขอประวัติการสนทนา ระบุ POST /v1/accounts/{account_id}/conversations/history/request ซึ่งเริ่มการส่งข้อมูลแบบอะซิงโครนัส ไม่ใช่ REST API สำหรับอ่านข้อความที่เก็บไว้แล้วส่งกลับโดยตรง
| สิ่งที่พบ | สิ่งที่ยืนยันได้ | สิ่งที่ยืนยันไม่ได้ |
|---|---|---|
HTTP 202, data.status: accepted | รับคำขอแล้ว | ข้อความมาถึงแล้วหรืองานเสร็จแล้ว |
HTTP request_id | ใช้อ้างอิงเพื่อวิเคราะห์คำขอ HTTP | ID งานหรือคีย์เชื่อมโยง callback |
conversation.history พร้อม data.history.source: on_demand | ได้รับชุดประวัติแบบออนดีมานด์ | เป็นชุดเดียวหรือชุดสุดท้าย |
| ชุดข้อมูลว่างหรือมีน้อย | เนื้อหาของชุดนั้น | ประวัติที่มีสิ้นสุดแล้ว |
| HTTP หมดเวลา | ไคลเอนต์ไม่ได้รับคำตอบที่สรุปผลได้ | คำขอไม่มีผลใด ๆ |
คู่มือกู้คืน runtime ของบัญชีรับส่งข้อความ แก้ปัญหาการเชื่อมต่อ ซึ่งเป็นคนละงานกับการเติมประวัติ ทั้งการเชื่อมต่อใหม่และการขอประวัติไม่รับประกันว่าจะกู้ข้อความทั้งหมดที่ขาดไปในช่วงหยุดทำงานได้
เตรียมตัวรับก่อนเปิดใช้ปุ่ม
เพิ่ม conversation.history ในรายการเหตุการณ์ที่ endpoint รับ โดยคงเหตุการณ์เดิมที่กล่องข้อความยังต้องใช้ไว้ ใช้ message.received ต่อไปสำหรับข้อความสด เมื่อแก้ไข endpoint เดิม ให้ดู เอกสารตั้งค่า webhook และอย่าล้าง signing_secret โดยไม่ตั้งใจ
ทำตาม ข้อกำหนดการส่ง webhook: ตรวจ X-Device-Signature ด้วย HMAC-SHA256 บนข้อมูลที่ประกอบจาก X-Device-Timestamp จุดหนึ่งตัว และ raw request body ตรวจอายุ timestamp จากนั้นบันทึกข้อมูลที่ผ่านการยืนยันลงพื้นที่จัดเก็บถาวรก่อนตอบ 2xx
ประวัติต้องมีเส้นทางกำจัดข้อมูลซ้ำแยกต่างหาก ชังก์ของ WhatsApp HistorySync อาจใช้ event ID ระดับบนซ้ำกัน อย่าทิ้งทั้งชุดเพียงเพราะเคยเห็น event ID นั้นแล้ว ภายใน workspace ให้รวมข้อความด้วย provider, account_id, data.conversation.id และ data.messages[].id ของแต่ละข้อความ
อย่าส่งข้อความเก่าเข้า trigger ตอบกลับอัตโนมัติสำหรับข้อความสด การได้รับคำถามเก่าในวันนี้ไม่ได้หมายความว่าลูกค้าถามอีกครั้งในวันนี้
สร้างจุดอ้างอิง before ที่ถูกต้อง
เลือกข้อความที่สังเกตได้จริงจากบัญชีรับส่งข้อความเดียวกันและแชตส่วนตัวเดียวกัน จุดอ้างอิงต้องมี message_id, sent_at และ direction อย่าเดาจากชื่อการสนทนา เวลาที่ระบบรับข้อมูล หรือหมายเลขโทรศัพท์
ตัวอย่าง request body ต่อไปนี้ใช้โครงสร้างตามเอกสาร ให้แทนค่าตัวอย่างด้วยค่าที่บันทึกไว้จริง:
{
"conversation_id": "100000000000002@lid",
"before": {
"message_id": "MSG_HISTORY_ANCHOR_001",
"sent_at": "2026-09-28T03:00:00Z",
"direction": "inbound"
},
"limit": 50
}
ส่ง body ไปยัง POST operation ที่ระบุ โดยใช้ X-Api-Key ที่เก็บฝั่งแบ็กเอนด์ account_id ต้องเป็น path segment เดียวที่ไม่ว่าง ไม่มีช่องว่างหรือเครื่องหมายทับ รวมถึงเครื่องหมายทับที่เข้ารหัสแล้ว อย่านำ ID การสนทนาไปใส่ในส่วน path ของบัญชี
สำหรับคำขอถัดไป ให้เลือก ข้อความเนื้อหาจริงจากแพลตฟอร์มที่เก่าที่สุด ในข้อมูลที่รับมาและมีฟิลด์จุดอ้างอิงครบ ตัดระเบียนสังเคราะห์ type: call ออก JavaScript ต่อไปนี้เพียงสร้างจุดอ้างอิงจากข้อความที่เลือกและตรวจสอบแล้ว ไม่ใช่ตัวรับ webhook หรือ worker แบ่งหน้าอัตโนมัติ:
function beforeFromMessage(message) {
if (!message || message.type === 'call' ||
typeof message.id !== 'string' || !message.id ||
typeof message.sent_at !== 'string' ||
!Number.isFinite(Date.parse(message.sent_at)) ||
!['inbound', 'outbound'].includes(message.direction)) {
throw new Error('Select a native content message with complete anchor fields');
}
return {
message_id: message.id,
sent_at: message.sent_at,
direction: message.direction
};
}
สังเกตว่าไม่ได้คัดลอก type ไปยัง before ถ้าไม่มีจุดอ้างอิงที่ใช้ได้ ให้ปิดการส่งคำขอและอธิบายสาเหตุ อย่าใช้ระเบียนการโทรสังเคราะห์หรือสร้างเวลาที่เก่ากว่าขึ้นเอง
แสดงความไม่แน่นอนในกล่องข้อความ
รายการต่อไปนี้คือพฤติกรรมแอปที่แนะนำ ไม่ใช่สถานะ API เพิ่มเติม:
- ก่อนส่ง: บันทึกบัญชี การสนทนา จุดอ้างอิง และเวลาขอของระบบคุณ จัดคำขอของเจ้าหน้าที่ต่อการสนทนาให้ทำตามลำดับเพื่อลดงานทับซ้อน
- เมื่อรับคำขอแล้ว: แสดง “รับคำขอแล้ว กำลังรอประวัติที่มี” และรับข้อความสดแยกกันต่อไป
- เมื่อแต่ละชุดมาถึง: รวมข้อความแบบ idempotent รักษาสถานะการแก้ไขจากข้อมูลสดและตัวป้องกันการนำข้อความที่ลบแล้วกลับมา อย่าให้ประวัติเก่าเขียนทับสถานะใหม่
- หลังได้รับข้อความเก่ากว่า: อนุญาตให้ผู้ใช้สั่งคำขอถัดไปอย่างชัดเจนด้วยจุดอ้างอิงที่เก่าที่สุดและใช้ได้ ถ้าไม่มีจุดอ้างอิงที่เก่ากว่า ให้แสดง “ยังไม่ได้รับจุดอ้างอิงที่เก่ากว่า” ไม่ใช่ “โหลดประวัติครบแล้ว”
- เมื่อหมดเวลาหรือไม่มี callback: คงสถานะที่ยังสรุปไม่ได้ และรับข้อมูลที่มาช้าต่อไป อย่าส่งคำขอเดิมซ้ำอัตโนมัติ
เอกสารไม่ได้กำหนด cursor หน้าถัดไปหรือสถานะเสร็จสมบูรณ์ account.history.synced คือสรุปของ batch/chunk ของ HistorySync ไม่ใช่หลักฐานว่าคำขอออนดีมานด์เสร็จแล้วหรือประวัติครบ อย่าแปลงให้เป็นสัญญาณจบงานที่ API ไม่ได้ระบุ
แยกความสัมพันธ์การอ้างข้อความออกจากความสามารถในการส่งด้วย ข้อความประวัติไม่มี reply_token คู่มือตอบกลับแบบอ้างข้อความ อธิบายว่าทำไม ID ข้อความต้นทางจึงใช้แทนไม่ได้ ส่วนไฟล์แนบที่ใช้ไม่ได้ควรแสดงว่าไม่พร้อมใช้งาน ไม่ใช่แสดงว่าดาวน์โหลดแล้ว
ข้อผิดพลาดและการทดสอบก่อนใช้งานจริง
400 อาจเป็น invalid_request, provider_invalid_request ซึ่งรวมจุดอ้างอิงการโทรสังเคราะห์ หรือ unsupported_conversation_type ส่วน provider อื่นคืน 501 unsupported_by_provider ให้แก้ขอบเขตหรือข้อมูลเข้า แทนการวนลองใหม่ เก็บ HTTP request_id เพื่อวิเคราะห์ปัญหา แต่ไม่ใช้เป็นคีย์เชื่อม callback
ก่อนเปิดใช้งานจริง ควรทดสอบชุดข้อมูลซ้ำ ชังก์ต่างกันที่มี event ID เดียวกัน callback หลัง HTTP หมดเวลา ข้อความสดที่สลับกับประวัติ และจุดอ้างอิงที่ขาด direction นี่คือรายการทดสอบที่เสนอ ไม่ใช่ผลการทดสอบที่เกิดขึ้นแล้ว
UnifyPort ให้บริการอินเทอร์เฟซที่ไม่เป็นทางการ ความสามารถนี้ช่วยเติมบริบทแบบ best-effort ไม่ใช่ข้อมูลสำรองครบชุด การรับประกันส่งซ้ำ หรือสิทธิ์เข้าถึงบัญชีใดก็ได้ คุณยังต้องมีพื้นที่เก็บข้อความที่ได้รับอนุญาตและกฎการเก็บรักษาของตนเอง
คำถามที่พบบ่อย
202 หมายความว่าดึงข้อความเก่าแล้วใช่ไหม?
ไม่ใช่ หมายถึงรับคำขอแล้วเท่านั้น ข้อความที่มีจะมาถึงทางเหตุการณ์ประวัติแบบอะซิงโครนัส
ขอไปเรื่อย ๆ จนได้ชุดที่มีข้อความน้อยได้ไหม?
อย่าใช้เป็นเงื่อนไขจบ จำนวนข้อความในชุดไม่ยืนยันความครบถ้วน และคำขออัตโนมัติอาจทับซ้อนกับผลที่มาช้า
ใช้กับกลุ่ม WhatsApp, LINE หรือ Zalo ได้ไหม?
operation นี้ระบุเฉพาะแชตส่วนตัวของ provider=whatsapp แม้ทีมจะรวม LINE ไว้ในกล่องข้อความเดียวกัน ก็ไม่ควรอนุมานว่าทุกช่องทางรองรับการขอประวัติเหมือนกัน
ขั้นตอนถัดไปและแหล่งอ้างอิง
ทำตัวรับและการจัดการสถานะที่ยังสรุปไม่ได้ตาม เอกสารขอประวัติการสนทนา ก่อนเปิดปุ่มในกล่องข้อความ
ตรวจสอบเอกสารทางการเมื่อ 2026-09-30:
เปลี่ยนการเชื่อมต่อข้อความให้เป็น pipeline ผลิตภัณฑ์ที่เสถียร
เริ่มจากการส่งผ่าน API เดียว แล้วส่งข้อความขาเข้าทั้งหมดกลับสู่ระบบธุรกิจของคุณด้วย event มาตรฐาน