← บทความทั้งหมด
บทช่วยสอน

LINE Webhook กด Verify ไม่ผ่าน? จัดการ events ว่างให้ถูกต้อง

การตรวจสอบ Webhook URL ของ LINE จะส่งคำขอ HTTP POST ที่มีอาร์เรย์ events ว่าง ตัวรับควรตรวจสอบลายเซ็นแล้วตอบ 200 โดยไม่พยายามอ่านข้อความหรือส่งคำตอบ หากโค้ดคิดว่า events[0] ต้องมีเสมอ การทดสอบ Verify อาจล้มเหลวแม้จะรับข้อความปกติได้ ในทางกลับกัน Verify ผ่านก็ไม่ได้ยืนยันว่าข้อความจริงเข้าสู่คิวหรือกล่องข้อความของทีมบริการลูกค้าแล้ว

ประเด็นสำคัญ

  • คำขอ events: [] ที่ผ่านการตรวจสอบลายเซ็นคือการทดสอบการเชื่อมต่อ ไม่ใช่ข้อความสูญหาย
  • ตรวจสอบ x-line-signature ด้วย channel secret และเนื้อหาคำขอดิบก่อนอ่าน JSON
  • ทดสอบการเชื่อมต่อและการทำงานของระบบแยกกัน ผลหนึ่งใช้แทนอีกผลไม่ได้
  • Webhook ของ LINE โดยตรงกับอีเวนต์มาตรฐานของ UnifyPort ใช้ข้อกำหนดคนละชุด

ปุ่ม Verify ของ LINE ส่งอะไรมา

คู่มือตรวจสอบ Webhook URL ของ LINE ระบุสองวิธี ได้แก่ API ทดสอบ Webhook และปุ่ม Verify ใน LINE Developers Console ทั้งสองวิธีตรวจสอบว่า LINE ติดต่อกับเซิร์ฟเวอร์รับได้หรือไม่ LINE กำหนดให้ตอบ 200 สำหรับคำขอทดสอบที่ไม่มีอีเวนต์

ด้านล่างคือรูปแบบเนื้อหาคำขอจากตัวอย่างการตรวจสอบลายเซ็นของ LINE ไม่ใช่ข้อความของลูกค้า:

{"destination":"U8e742f61d673b39c7fff3cecb7536ef0","events":[]}

ไม่มีออบเจ็กต์อีเวนต์ที่จะบรรจุข้อความ ผู้ส่ง หรือ reply token อย่าสร้างข้อมูลลูกค้าจาก destination อย่าสร้างรหัสข้อความขึ้นเอง และอย่าเพิ่มงานตอบกลับอัตโนมัติ หากต้องการติดตามสถานะ ให้บันทึกการทดสอบการเชื่อมต่อแยกจากปริมาณข้อความลูกค้า

ก่อนเปลี่ยน URL ให้ตรวจสอบว่าใครดูแลปลายทางนี้ หากหลายเครื่องมือใช้บัญชีทางการเดียวกัน ให้อ่านเช็กลิสต์ Webhook สำหรับหลายเครื่องมือ เพื่อไม่ให้การแก้ข้อผิดพลาดของตัวแยกข้อมูลย้ายทราฟฟิกออกจากตัวรับที่ทำงานอยู่

ตรวจสอบลายเซ็นก่อนยอมรับอาร์เรย์ว่าง

คู่มือลายเซ็นของ LINE ระบุให้คำนวณ HMAC-SHA256 จากเนื้อหาคำขอที่ได้รับ โดยใช้ channel secret เป็นคีย์ และเปรียบเทียบลายเซ็นในรูปแบบ Base64 ค่านี้ไม่ใช่ channel access token ที่ใช้เรียก API ส่งข้อความ

เก็บไบต์ต้นฉบับไว้ การแปลง JSON เป็นออบเจ็กต์แล้วแปลงกลับอาจเปลี่ยนช่องว่างหรืออักขระ escape ทำให้ลายเซ็นไม่ตรง แม้ events จะว่างก็ต้องตรวจสอบ เพราะผู้ส่งที่ไม่ได้รับอนุญาตสามารถสร้าง JSON รูปแบบเดียวกันได้

ฟังก์ชัน Node.js ต่อไปนี้เป็นตัวอย่างการตรวจสอบและอ่านคำขอ LINE โดยตรง rawBody ต้องเป็น Buffer ต้นฉบับที่ HTTP framework เก็บไว้ ส่วน channelSecret มาจากที่เก็บความลับฝั่งเซิร์ฟเวอร์ ตัวอย่างนี้ไม่ใช่เซิร์ฟเวอร์หรือระบบคิวแบบสมบูรณ์

import { createHmac, timingSafeEqual } from 'node:crypto';

export function readLineEvents(rawBody, signature, channelSecret) {
  if (!Buffer.isBuffer(rawBody) || !channelSecret) {
    throw new Error('Raw body and channel secret are required');
  }
  const expected = createHmac('sha256', channelSecret)
    .update(rawBody)
    .digest('base64');
  const supplied = Buffer.from(signature ?? '', 'utf8');
  const calculated = Buffer.from(expected, 'utf8');
  if (supplied.length !== calculated.length ||
      !timingSafeEqual(supplied, calculated)) {
    return { status: 401 };
  }
  try {
    const payload = JSON.parse(rawBody.toString('utf8'));
    if (!payload || !Array.isArray(payload.events)) {
      return { status: 400 };
    }
    return { status: 200, events: payload.events };
  } catch {
    return { status: 400 };
  }
}

สถานะ 400 และ 401 เป็นทางเลือกในการป้องกันของตัวอย่างนี้ ไม่ใช่รหัสข้อผิดพลาดของ LINE API เมื่อนำไปใช้ ให้ทำตามลำดับนี้:

  1. ส่งเฮดเดอร์ x-line-signature และเนื้อหาคำขอที่ไม่ถูกแก้ไขเข้าฟังก์ชัน
  2. ปฏิเสธคำขอที่ไม่ถูกต้องโดยไม่สร้างงานธุรกิจ
  3. หากตรวจสอบผ่านและ events.length === 0 ให้ตอบ HTTP 200 ทันที
  4. หากมีอีเวนต์ ให้บันทึกลงที่เก็บถาวรก่อนยืนยันการรับ แล้วประมวลผลงานที่ใช้เวลานานแบบอะซิงโครนัส หากบันทึกไม่สำเร็จ อย่าตอบ 200 เพียงเพราะฟังก์ชันส่งสถานะนี้กลับมา

LINE แนะนำให้ประมวลผลแบบอะซิงโครนัส ส่วนการออกแบบที่เก็บถาวรและ worker เป็นหน้าที่ของแอปพลิเคชัน ต้องวนอ่านทุกอีเวนต์ในอาร์เรย์ ไม่ใช่เลือกเฉพาะตัวแรก

ตรวจหาจุดที่ล้มเหลว

สิ่งที่พบสิ่งที่ควรตรวจต่อ
ไม่มีคำขอถึงแอปโฮสต์และพาธที่ตั้งไว้, TLS, การกำหนดเส้นทาง และล็อกของพร็อกซี
ลายเซ็นไม่ผ่านchannel secret, ไบต์ต้นฉบับ และการส่งต่อเฮดเดอร์
คำขอว่างที่ตรวจสอบแล้วทำให้เกิด exceptionการอ่านอีเวนต์แรก ข้อความ หรือ reply token โดยไม่ตรวจเงื่อนไข
แอปบันทึกว่าสำเร็จ แต่ Verify ไม่ผ่านสถานะที่จุดรับสาธารณะตอบจริงและเวลาประมวลผล
Verify ผ่าน แต่ข้อความไม่เข้า inboxการบันทึกอีเวนต์จริง การส่งต่องาน และการทำงานของ worker

อย่าเปลี่ยนข้อมูลรับรองหรือย้ายผู้ดูแล Webhook เพียงเพราะตัวรับที่ออกแบบมาสำหรับข้อความไม่รองรับอาร์เรย์ว่าง หากอีเวนต์จริงมาถึงแต่ไม่มี reply token นั่นเป็นอีกปัญหาหนึ่ง คู่มือ LINE standby อธิบายสิทธิ์ในการตอบ ส่วนคำขอทดสอบว่างไม่มีอีเวนต์และไม่มี mode ให้ตรวจ

พิสูจน์การเชื่อมต่อและการรับข้อความแยกกัน

ต่อไปนี้เป็นกรณีทดสอบที่แนะนำ ไม่ใช่ผลการทดสอบระบบจริงที่รายงานแล้ว:

  • คำขอว่างที่มีลายเซ็นถูกต้องตอบ 200 โดยไม่สร้างข้อความลูกค้าหรืองานส่งข้อความ
  • เนื้อหาว่างแบบเดียวกันแต่ไม่มีลายเซ็นหรือลายเซ็นผิดถูกปฏิเสธ
  • คำขอที่มีอีเวนต์และลายเซ็นถูกต้องถูกบันทึกถาวรก่อนยืนยันการรับ
  • หลัง Verify ผ่าน ให้ส่งข้อความทดสอบที่ควบคุมได้ไปยังบัญชีทางการเป้าหมาย และติดตามจนเข้ากระบวนการ inbox ที่ต้องการ
  • การบันทึกล้มเหลวไม่ถูกระบุภายในว่าเสร็จสมบูรณ์เพียงเพราะลายเซ็นถูกต้อง

เก็บข้อมูลวินิจฉัยเท่าที่จำเป็น เช่น ผลการตรวจลายเซ็น จำนวนอีเวนต์ สถานะ HTTP และเวลาที่ตรวจพบ ไม่ควรเขียน channel secret, reply token หรือเนื้อหาข้อความลูกค้าลงล็อกทั่วไป

แยกตัวรับของ UnifyPort ออกให้ชัดเจน

อินเทอร์เฟซที่ไม่เป็นทางการของ UnifyPort เชื่อมบัญชี LINE ผ่านขั้นตอนอนุญาต LINE ไม่ใช่บริการทดสอบ Webhook โดยตรงของบัญชีทางการ

ข้อกำหนดการส่ง Webhook ใช้ X-Device-Signature เมื่อกำหนด signing_secret ระบบคำนวณ HMAC-SHA256 จาก X-Device-Timestamp ตามด้วยจุดและเนื้อหาคำขอดิบ แล้วเข้ารหัสแบบเลขฐานสิบหก โครงสร้างมาตรฐานมี id, type, provider, account_id, occurred_at และ data ไม่ใช่อาร์เรย์ events ของ LINE

ใช้คนละ route หรือกำหนดตัวรับให้แยกกันอย่างชัดเจน อย่าตีความว่า payload ของ UnifyPort ที่ไม่มี events คือคำขอทดสอบว่างของ LINE การผ่าน LINE Verify ไม่ได้ทดสอบการส่งของ UnifyPort การอนุญาตบัญชี หรือการประมวลผลข้อความมาตรฐาน หากต้องทำงานในนาม LINE Official Account ให้คงเส้นทาง Messaging API ทางการไว้

คำถามที่พบบ่อย

events: [] เป็นข้อผิดพลาดหรือไม่?

ไม่ใช่สำหรับคำขอตรวจสอบ Webhook URL ของ LINE ให้ตรวจลายเซ็นแล้วตอบ 200 โดยไม่สร้างงานข้อความ ฟิลด์ที่หายไปหรือมีชนิดข้อมูลผิดไม่เหมือนอาร์เรย์ว่าง

ทำไมรับข้อความปกติได้ แต่ Verify ไม่ผ่าน?

สาเหตุหนึ่งคือโค้ดสมมติว่าทุกคำขอมีอีเวนต์ข้อความตัวแรกเสมอ ตรวจสถานะตอบกลับและล็อก exception จริง ปัญหาการเชื่อมต่อหรือลายเซ็นก็ทำให้ล้มเหลวได้เช่นกัน

Verify ผ่านแปลว่าบอตตอบกลับได้แล้วหรือไม่?

ไม่ใช่ เป็นการตรวจการสื่อสารกับตัวรับ ไม่ได้ยืนยันการบันทึก การทำงานของ worker สิทธิ์ในการตอบ หรือความสำเร็จของ API ส่งข้อความ

ขั้นตอนถัดไปและแหล่งอ้างอิง

สำหรับบัญชีทางการ ให้ใช้การตรวจ Webhook URL ของ LINE แล้วติดตามข้อความทดสอบจริงหนึ่งข้อความ สำหรับการเชื่อมต่อ UnifyPort ที่แยกต่างหาก ให้ใช้ข้อกำหนด Webhook ที่ระบุในเอกสาร แทน

ตรวจสอบเอกสารทางการเมื่อ 2026-10-28:

UnifyPort API

เปลี่ยนการเชื่อมต่อข้อความให้เป็น pipeline ผลิตภัณฑ์ที่เสถียร

เริ่มจากการส่งผ่าน API เดียว แล้วส่งข้อความขาเข้าทั้งหมดกลับสู่ระบบธุรกิจของคุณด้วย event มาตรฐาน