เปลี่ยน Rich Menu แบบ Personalize ใน LINE OA ให้ผู้ใช้งาน 1,000,000 คนใน Request เดียว

Jirawatee
LINE Developers Thailand
5 min readJul 11, 2023

--

การทำ Personalize Rich Menu เป็นการแสดง Rich Menu แบบเฉพาะเจาะจงกับผู้ใช้งาน เช่น การแสดง Rich Menu สำหรับบัญชีสมาชิกที่ได้รับการยืนยัน, การแสดง Rich Menu ตามภาษาของเครื่องผู้ใช้ หรือในกรณีที่มีการเก็บข้อมูลผู้ใช้มา ก็อาจแยกแสดง Rich Menu ตาม Preference ของผู้ใช้แต่ละคนได้

การเปลี่ยน(Link) Rich Menu แบบ Personalize ให้กับผู้ติดตามบัญชี LINE OA ที่มีจำนวนไม่มาก ก็คงไม่มีปัญหาอะไร เนื่องจากนักพัฒนาสามารถ Link ตัว Rich Menu เข้ากับผู้ใช้ได้ตั้งแต่ 1-500 userIds/request แต่กรณีที่บัญชี LINE OA มีผู้ติดตามจำนวนมาก เช่น 1,000,000 คน นักพัฒนาก็จะต้องเขียนโปรแกรมเพื่อ loop เปลี่ยน Rich Menu ถึง 2,000 รอบ ซึ่งไม่ใช่เรื่องง่ายแน่ๆ เพราะเราจะต้อง handle ข้อผิดพลาดที่อาจเกิดขึ้นไม่ว่าจะเป็น timeout หรือ error ระหว่างการ loop รวมถึง การจัดการคิว กรณีที่มีผู้ติดตามจำนวนมากและมี request ที่เกิน API limit

ซึ่งทาง LINE ก็ทราบถึงปัญหานี้ จึงได้พัฒนา 3 APIs ใหม่เพื่อมาช่วยให้การ Replace หรือ Unlink ตัว Rich Menu กับผู้ติดตามจำนวนมากๆง่ายและรวดเร็ว โดยเฉพาะอย่างยิ่ง Use case ที่ Rich Menu มีการ Link แบบ Personalize หลังการยืนยันตัวตนจะสะดวกสุดๆเลย เนื่องจากเมื่อ Replace แล้ว ผู้ติดตามจะสามารถใช้งาน Rich Menu ใหม่ได้เลย ไม่ต้องมายืนยันตัวตนอีกรอบ

คำแนะนำ

สำหรับนักพัฒนาที่ยังไม่คุ้นเคยกับการจัดการ Rich Menu ด้วย API มาก่อน โดยเฉพาะการ Link หรือ Unlink ผมขอแนะนำให้อ่านบทความด้านล่างนี้ตั้งแต่ข้อ 4 เป็นต้นไปก่อน เพื่อความเข้าใจและสามารถใช้งาน API ชุดใหม่นี้ได้นะครับ

1. Replace / Unlink Rich Menu in Batch API

ก่อนหน้านี้หากต้องการ Link หรือ Unlink ตัว Rich Menu เราจะต้องใช้ userId ซึ่งจะมีความยุ่งยากทั้งการเก็บและการดึงออกมาใช้งาน แต่ด้วย API ตัวใหม่นี้ นักพัฒนาจะสามารถ Replace หรือ Unlink ตัว Rich Menu ที่ผู้ติดตามใช้งานอยู่ทั้งหมด ไม่ว่าจะกี่ล้านคนโดยไม่ต้องใช้ userId อีกต่อไป

รายละเอียดของ API

Endpoint https://api.line.me/v2/bot/richmenu/batch
Method POST
Headers
Authorization: Bearer YOUR-CHANNEL-ACCESS-TOKEN
Body
operations: เป็น array ของ operation object ที่กำหนดได้สูงสุด 1,000 objects
resumeRequestKey[optional]: ข้อความในรูปแบบ [0-9a-zA-Z\-_]{1,100} ใช้สำหรับการ retry

โครงสร้างของ Operation Object ที่อยู่ภายใน Operations array

โครงสร้างภายในของ operations object จะมีอยู่ด้วยกัน 3 properties ดังนี้

  • type:
    link สำหรับ Replace ตัว Rich Menu จากตัวหนึ่งไปเป็นอีกตัวหนึ่ง
    unlink สำหรับถอด Rich Menu ที่กำหนดออกจากผู้ติดตามทั้งหมด unlinkAll สำหรับถอด Rich Menu ออกจากผู้ติดตามทั้งหมด (ใช้ร่วมกับ type อื่นไม่ได้)
  • from: คือ richMenuId ที่ต้องการจะ Replace หรือ Unlink โดยกรณีที่มี operation object มากกว่า 1 จะไม่สามารถมี richMenuId ซ้ำกันใน from ได้
  • to: richMenuId ที่ต้องการแสดง

ตัวอย่าง Body Request

// ตัวอย่าง body request ของ replace และ unlink ตัว Rich Menu ที่กำหนดใน request เดียว
{
"operations": [
{
"type": "link",
"from": "richmenu-1a3aa27e3159...",
"to": "richmenu-8bdc11f1953978..."
},
{
"type": "unlink",
"from": "richmenu-8b572263cdb3..."
}
],
"resumeRequestKey": "resume-1"
}
// ตัวอย่าง body request ของการ unlink ตัว Rich Menu ทั้งหมดที่ได้ link กับผู้ใช้ไว้
{
"operations": [
{
"type": "unlinkAll"
}
],
"resumeRequestKey": "resume-2"
}

resumeRequestKey พระเอกของการ Retry

ตัว property ที่ชื่อ resumeRequestKey ที่ถึงแม้มันจะเป็น optional แต่มันจะมีประโยชน์มากหากเราระบุมันลงไปใน body request ในกรณีที่มี Timeout หรือ Internal Server Error จากทาง LINE รวมถึงกรณีที่พบว่าสถานะจาก Get Status of Batch API มัน Fail เพราะถ้าเราต้องการจะ request ซ้ำ การระบุค่าเดิมที่ตั้งไปใน resumeRequestKey กับ request ก่อนหน้าให้เหมือนกัน ระบบจะเข้าไปดำเนินการเฉพาะกับผู้ใช้ที่ยังไม่ได้จัดการไปใน request ก่อนหน้าเท่านั้น

Response

  • กรณีที่ request สำเร็จจะได้ HTTP status เป็น 200 และได้ {} ใน body response
  • กรณีที่ request ไม่สำเร็จจะได้ HTTP status เป็น 400 หรือ 404 พร้อมสาเหตุใน body response
// ตัวอย่าง error จากการระบุ richMenuId ที่ไม่ถูกต้อง
{
"message": "The request body has 1 error(s)",
"details": [
{
"message": "Richmenu (richmenu-8bdc11...) is not found",
"property": "operations[0].to"
}
]
}

หมายเหตุ

  • API นี้มี limit การใช้งานที่ 3 requests/ชม.
  • การทำงานของ API เส้นนี้จะทำงานแบบ asynchronously ใน background กล่าวคือที่ระบบหลังบ้านทาง LINE จะจัดการคิวให้อัตโนมัติ
  • การทำงานเพื่อ Replace หรือ Unlink ตัว Rich Menu กรณีที่มี array ใน request body มีมากกว่า 1 จะทำงานแบบ Parallel

2. Get Status of Batch API

ด้วยการทำงานของ Replace / Unlink Rich Menu in Batch API จะทำงานแบบ asynchronously ใน background ดังนั้น response จาก API ดังกล่าวก็จะยังบอกไม่ได้ว่าการอัพเดท Rich Menu ให้กับกลุ่มผู้ติดตามนั้น กำลังดำเนินการอยู่ และสำเร็จแล้วหรือไม่ (ระยะเวลาในการดำเนินการจะขึ้นอยู่กับจำนวนผู้ติดตามบัญชี LINE OA) ซึ่งวิธีที่จะติดตามความคืบหน้า จะต้องเรียก Get Status of Batch API

รายละเอียดของ API

Endpoint https://api.line.me/v2/bot/richmenu/progress/batch
Method GET
Headers
Authorization: Bearer YOUR-CHANNEL-ACCESS-TOKEN
Query params
requestId: ค่า X-Line-Request-Id ที่มากับ response headers

Response

กรณีที่ request สำเร็จจะได้ HTTP status เป็น 200 และได้ body response ที่มีรายละเอียดดังนี้

{
"phase": "succeeded",
"acceptedTime": "2023-06-26T07:37:21.083Z",
"completedTime": "2023-06-26T09:12:12.197Z"
}
  • phase: สถานะของการดำเนินการ
    ongoing: กำลังดำเนินการ
    succeeded: การดำเนินการเสร็จเรียบร้อย
    failed: เกิดข้อผิดพลาดในการดำเนินการกับผู้ติดตามบางส่วนหรือทั้งหมด
  • acceptedTime: เวลาที่ระบบได้รับคำร้องจาก Replace / Unlink in Batch API
  • completedTime: เวลาที่ดำเนินการเสร็จเรียบร้อย จะเกิดขึ้นหลังจากสถานะของ phase เป็น succeeded หรือ failed

หมายเหตุ

  • API นี้มี limit การใช้งานที่ 100 requests/ชม.

3. Validate the Request of Batch API

ผลลัพธ์จากการเรียกใช้งาน Replace / Unlink Rich Menu in Batch API ไม่ว่าจะสำเร็จหรือไม่ก็จะถูกคิดโควต้าการใช้งานที่ 3 requests/ชม. ดังนั้น เพื่อให้มั่นใจแล้วค่อยปล่อยคิว ผมแนะนำนักพัฒนาให้ใช้ API นี้ก่อน โดย API เส้นนี้จะช่วยตรวจสอบดังนี้

  • richMenuId ถูกต้องหรือไม่
  • richMenuId นั้นๆมีการอัพโหลดรูปแล้วหรือยัง
  • กรณีที่มีการระบุ operation object มากกว่า 1
    + สมาชิกใน array เกิน 1,000 หรือไม่
    + มีการใช้ type อื่นร่วมกับ unlinkAll หรือไม่
    + มีการระบุ richMenuId ซ้ำใน from ภายใน array หรือไม่
  • มีการระบุ resumeRequestKey ผิดรูปแบบหรือไม่

รายละเอียดของ API

Endpoint https://api.line.me/v2/bot/richmenu/validate/batch
Method POST
Headers
Authorization: Bearer YOUR-CHANNEL-ACCESS-TOKEN
Body
operations: เป็น array ของ operation object ที่กำหนดได้สูงสุด 1,000 objects
resumeRequestKey[optional]: ข้อความในรูปแบบ [0-9a-zA-Z\-_]{1,100} ใช้สำหรับการ retry

ตัวอย่างของ Body Request

{
"operations": [
{
"type": "link",
"from": "richmenu-6a040980fd...",
"to": "richmenu-a3476ff0d2ec..."
}
],
"resumeRequestKey": "resume-1"
}

Response

  • กรณีที่ request สำเร็จจะได้ HTTP status เป็น 200 และได้ {} ใน body response
  • กรณีที่ request ไม่สำเร็จจะได้ HTTP status เป็น 400 หรือ 404 พร้อมสาเหตุใน body response
// ตัวอย่าง error จากการใช้ type อื่นร่วมกับ unlinkAll
{
"message": "The request body has 1 error(s)",
"details": [
{
"message": "'unlinkAll' type can't be combined with other type",
"property": "operations[].type"
}
]
}

หมายเหตุ

  • API นี้มี limit การใช้งานที่ 2,000 requests/วินาที

Use case การ Replace ตัว Rich Menu ที่กำหนดแบบ Switch Action

สำหรับนักพัฒนาที่กำลังมีคำถามว่า Rich Menu ที่ฉันใช้อยู่เป็นแบบ Swich Action จะสามารถใช้ Replace / Unlink Rich Menu in Batch API ในการ Replace ได้หรือไม่…คำตอบคือ ได้ แถมง่ายกว่าเดิมด้วยเพราะไม่ต้องสร้าง Rich Menu และ Link ให้กับผู้ใช้ใหม่ทั้งหมด

สำหรับใครที่ยังไม่คุ้นเคยกับคำว่า Switch Action หรือ Alias ผมแนะนำให้เข้าไปอ่านบทความด้านล่างนี้ก่อนนะครับ ไม่งั้นงงแน่นอน 😝

ผมจะขอยกตัวอย่างให้เห็นวิธีการแบบ Step by Step ง่ายๆผ่าน Rich Menu A และ B ที่มีเชื่อมต่อแบบ Switch Action ไว้แล้วดังนี้

{
"aliases": [
{
"richMenuAliasId": "richmenu-a",
"richMenuId": "richmenu-8bdc11f19..."
},
{
"richMenuAliasId": "richmenu-b",
"richMenuId": "richmenu-cdbf898ea..."
}
]
}

ก. เตรียมภาพ Rich Menu

ขั้นตอนนี้ให้เตรียมภาพ Rich Menu ขนาดใดก็ได้ โดยมีเงื่อนไขว่าความกว้างมากที่สุดไม่เกิน 2,500px และสูงอย่างน้อย 250px ซึ่งความกว้าง/สูง จะต้องเป็นอัตราส่วนอย่างน้อย 1.45 (ปัจจุบัน Rich Menu มีได้มากกว่า 2 ขนาดแล้ว)

ข. สร้าง Rich Menu

ขั้นตอนนี้ให้สร้าง Rich Menu ใหม่ขึ้นมา ในที่นี้คือ Rich Menu C ซึ่งผมจะเอาไปแทนที่ Rich Menu B โดยนักพัฒนาจะต้องเพิ่ม Action เข้าไปด้วยเพื่อให้คลิกแล้วสามารถสลับไปแสดงผล Rich Menu A ได้

areas.action.type: "richmenuswitch"
areas.action.richMenuAliasId: "richmenu-a"
areas.action.data: "richmenu=c"

ค. อัพโหลดภาพ Rich Menu

เมื่อได้ richMenuId จากข้อ มาแล้ว ก็ให้อัพโหลดภาพ Rich Menu ที่ได้เตรียมไว้ในข้อ มาอัพโหลดได้เลย

ง. อัพเดท Rich Menu Alias

ขั้นตอนนี้จะเป็นการอัพเดทชื่อ Alias ของ richmenu-b ให้ไปเชื่อมกับ richMenuId ตัวใหม่ของเรา โดยให้เราเอา richMenuId ที่ได้จากข้อ มาไปกำหนดแบบนี้

{
"richMenuAliasId": "richmenu-b",
"richMenuId": "richmenu-922cb150..."
}

จ. Replace ตัว Rich Menu จาก B เป็น C ด้วย Batch API

ขั้นตอนสุดท้ายก็ให้เราเรียกใช้ Replace / Unlink in Batch API ตามรายละเอียดในข้อ 1 ของบทความ เพื่อเปลี่ยน Rich Menu จาก B เป็น C ให้กับผู้ใช้งานทุกคนใน request เดียวได้เลย

{
"operations": [
{
"type": "link",
"from": "richmenu-cdbf898ea...",
"to": "richmenu-922cb150..."
}
],
"resumeRequestKey": "resume-1"
}

สรุป

การมาของ Replace / Unlink Rich Menu in Batch API นี่ช่วยให้ชีวิตนักพัฒนาสะดวกขึ้นมากๆเลย ทั้งการที่ไม่ต้องมาคอยเก็บคอยดึง userIds หรือไม่ต้องมา handle การ loop เพื่อ link ตัว Rich Menu เอง โดยเฉพาะอย่างยิ่ง use case ที่ต้องการเปลี่ยน Rich Menu แบบ Personalize ทั้งแบบธรรมดา และแบบ Switch Action ที่ไม่ต้องให้ผู้ใช้มายืนยันตัวตนซ้ำอีกรอบ

ผมเชื่อเหลือเกินว่า ใครที่มีบัญชี LINE OA ที่มีผู้ติดตามจำนวนมากๆต้องรัก API ชุดใหม่นี้แน่นอน เพราะของมันดีย์ สุดท้ายนี้ สั้นๆเลย Replace / Unlink Rich Menu in Batch API ใช้ซะ แล้วพบกันใหม่บทความหน้า สวัสดีครับ

--

--

Jirawatee
LINE Developers Thailand

Technology Evangelist at LINE Thailand / Google Developer Expert in Firebase