การประมวลผล LINE Webhook
ภาพรวม
เมื่อผู้ใช้ทักแชท กดติดตาม เลิกติดตาม หรือกดปุ่ม postback บน LINE ระบบจะได้รับ webhook เข้ามาที่ line-management-webhook-go ซึ่งทำหน้าที่ตรวจสอบเบื้องต้นแล้วส่งเข้าคิว line_webhook ทันที การประมวลผลจริงทั้งหมดเกิดขึ้นที่ worker ตัวนี้ จึงถือได้ว่าเป็น จุดเข้าหลักของทุก interaction ที่มาจากผู้ใช้
ความรับผิดชอบของงานนี้มี 5 ส่วน คือ ตรวจลายเซ็น resolve ว่าเป็น OA ใด อุ่น cache ให้ edge upsert แถว line_user และกระจาย event แต่ละตัวไปยังคิวหรือฟีเจอร์ปลายทาง
Business Flow
-
รับ payload ที่ประกอบด้วย
webhookId,headersและbodyโดย body คือ LINE webhook request แบบดิบ -
อ่าน header
x-line-signatureหากไม่มีจะคืนค่า error ทำให้ข้อความถูก nack และไหลลง DLQ -
getLineOAByWebhookId(webhookId)resolve หา OA ที่เกี่ยวข้อง โดยมี Redis cache ช่วยลดภาระฐานข้อมูล -
ตรวจลายเซ็นด้วยการคำนวณ
HMAC-SHA256บน body ด้วยoa.channelSecretIdแล้วเข้ารหัส base64 เทียบกับค่าใน header หากไม่ตรงจะคืนค่า error และข้อความไหลลง DLQ -
อุ่น cache แบบ best-effort คือหากล้มเหลวก็ไม่กระทบงานหลัก โดยเขียน Redis hash ที่ key
webhook_config:<webhookId>เก็บlineOaId,forwardWebhookUrlและค่าตั้งค่า mbox ทั้งชุด (สถานะเปิดใช้งาน คำสำคัญ และข้อความ greeting / warning / end / timeout) ตั้ง TTL ไว้ 1 ชั่วโมง พร้อมเขียน mappingmbox_inbox:<inboxId>เพื่อให้ webhook-go อ่าน config ได้เร็วโดยไม่ต้องแตะฐานข้อมูล -
ค้นหาหรือสร้างแถว
line_userจากuserIdของ event แรก หากยังไม่มีผู้ใช้รายนี้ ระบบจะตรวจ access token ดึงโปรไฟล์จาก LINE แล้วเรียกcreateLineUser -
วนกระจาย event ทุกตัวตามชนิด
ข้อความตัวอักษร — routing ตามค่า
line_oa.message_handling_config.priorityauto_response_onlyซึ่งเป็นค่าเริ่มต้น จะ publish เข้าคิวline_auto_responseai_classifier_onlyจะ publish เข้าคิวmessage_received_triggerauto_response_firstจะ publish เข้าคิวline_auto_responseพร้อมตั้งค่าfallbackToAiเป็น true
ข้อความพิเศษ
- ข้อความ
memberจะ publish เข้าคิวline_change_richmenuชนิดmemberเพื่อเปลี่ยน rich menu เป็นเมนูสมาชิก - ข้อความ
guestจะเปลี่ยนค่าuser_typeเป็น guest
ทุกกรณีของ event ชนิดข้อความจะอัปเดต
last_activity_typeเป็นmessageและlast_activity_statusเป็นactiveevent ชนิดอื่น
postbackจะตั้งlogEventTypeเป็นwebhookแล้ว publish payload ทั้งก้อนเข้าคิวtracking_logfollowจะรีเฟรชโปรไฟล์ อัปเดตข้อมูลผู้ใช้ ตั้ง rich menu สำหรับสมาชิก แล้วรันกระบวนการ friend-track attributionunfollowจะทำเครื่องหมายfollowเป็นnoและบันทึก unfollow event
-
การ publish ในสายข้อความเป็นแบบ fire-and-forget หากการ publish ล้มเหลวระบบจะบันทึก log แล้วประมวลผล event ถัดไปต่อ ซึ่งตรงกับพฤติกรรมของระบบ NestJS เดิมที่ไม่รอผลลัพธ์
-
ข้อผิดพลาดในระดับ event จะถูกจัดการโดย
handleWebhookErrorซึ่งบันทึก log ไว้ ส่วนฟังก์ชันProcessLineWebhookจะคืนค่า nil เสมอเพื่อ ack ข้อความ
ไฟล์และฟังก์ชันหลัก
internal/lineoa/webhook.goService.ProcessLineWebhook(ctx, payload)— entry pointwarmWebhookConfigCache(),processEvents(),handleMessageEvent(),handleFollowEvent(),handleUnfollowEvent(),runFriendTrackAttribution(),handleWebhookError()
internal/lineoa/consumer.go—Consumer.HandleLineWebhookผูกกับคิวline_webhookinternal/lineoa/service.go—getLineOAByWebhookId(),findById(),issueAccessToken()และverifyAccessToken()โดย token ถูก cache ไว้ 1 ชั่วโมงใน Redis key ที่ขึ้นต้นด้วยLINE_OA:internal/lineoa/lineuser.go—findByLineUserId(),createLineUser(),updateLineUser()internal/lineoa/types.go—LineForwardWebhookPayload,WebhookEventและ enum ของชนิด event กับ priority- คิวที่เกี่ยวข้อง: consume จาก
line_webhookและ publish ไปยังline_auto_response,message_received_trigger,line_change_richmenuและtracking_log(runtime profilemain)
จุดเชื่อมต่อกับ Service อื่น
- ต้นทางของงาน —
line-management-webhook-goซึ่งเป็น endpoint ที่รับ webhook จาก LINE - ฐานข้อมูล —
line_oa(channel secret, access token และmessage_handling_config),line_user(find-or-create พร้อมข้อมูลกิจกรรมล่าสุด) รวมถึงfriend_track_eventและfriend_track_campaign - Redis — key กลุ่ม
LINE_OA:สำหรับ cache token,webhook_config:<webhookId>และmbox_inbox:<inboxId> - LINE API —
GET /v2/bot/profile/{userId}และ OAuth endpoint สำหรับออกและตรวจสอบ channel access token - ปลายทางที่ถูกกระตุ้นต่อ — งาน auto response, งาน AI message trigger, งานจัดการ rich menu, งานบันทึก tracking log และงาน friend track