BotKit
บทความ › แชทบอท LINE / Facebook

สร้าง LINE Rich Menu ผ่าน API ด้วย Python และสาเหตุที่เมนูไม่ขึ้น

Rich Menu คือแถบเมนูรูปภาพด้านล่างของห้องแชท LINE OA ที่ลูกค้ากดได้โดยไม่ต้องพิมพ์ สำหรับบอทจองคิวหรือบอทร้านค้า มันคือปุ่มหลักที่ลูกค้าใช้มากที่สุด บทความนี้สอนสร้าง Rich Menu ผ่าน Messaging API ด้วย Python พร้อมเรื่องที่ทำให้เมนูไม่ขึ้นแบบงงๆ

สร้างใน OA Manager หรือผ่าน API ดี

LINE OA Manager (หน้าเว็บ)Messaging API
ความง่ายลากวางได้ ไม่ต้องเขียนโค้ดต้องเขียนสคริปต์
ปุ่มส่งข้อความให้บอทได้ได้
ปุ่มแบบ postback / เปลี่ยนเมนูตามผู้ใช้จำกัดได้ครบ
ทำซ้ำให้หลายร้านต้องกดใหม่ทุกร้านรันสคริปต์เดิม เปลี่ยนรูป/ข้อความ

ถ้าทำบอทให้ลูกค้าหลายร้าน แนะนำทำผ่าน API เพราะทำซ้ำได้และเก็บไว้ในโค้ดได้

1. เตรียมรูป

  • ไฟล์ PNG หรือ JPEG ขนาดไม่เกิน 1 MB
  • ขนาดที่ใช้กันบ่อย: 2500 × 1686 (เต็ม 6 ปุ่ม) และ 2500 × 843 (ครึ่งจอ 3 ปุ่ม)
  • รูปเป็นแค่ภาพ จุดที่กดได้กำหนดแยกด้วยพิกัด ต้องออกแบบรูปให้ช่องปุ่มตรงกับพิกัดที่จะกำหนด

2. กำหนดเมนู

ตัวอย่างเมนูครึ่งจอ 3 ปุ่มสำหรับบอทจองคิว แต่ละปุ่มส่งข้อความเข้าไปให้บอทเหมือนลูกค้าพิมพ์เอง

RICH_MENU = {
    "size": {"width": 2500, "height": 843},
    "selected": True,                 # เปิดเมนูไว้ตั้งแต่เข้าห้องแชท
    "name": "Booking Menu",
    "chatBarText": "📋 เมนูบริการ",    # ข้อความบนแถบด้านล่าง
    "areas": [
        {"bounds": {"x": 0,    "y": 0, "width": 833, "height": 843},
         "action": {"type": "message", "text": "นัดหมาย"}},
        {"bounds": {"x": 833,  "y": 0, "width": 834, "height": 843},
         "action": {"type": "message", "text": "บริการ"}},
        {"bounds": {"x": 1667, "y": 0, "width": 833, "height": 843},
         "action": {"type": "message", "text": "ดูนัดหมาย"}},
    ],
}

สังเกตว่าความกว้างรวมของ 3 ช่องต้องเท่ากับ 2500 พอดี (833 + 834 + 833) ไม่อย่างนั้นจะมีบางพื้นที่ที่กดแล้วไม่เกิดอะไร

3. สร้าง อัปโหลดรูป และตั้งเป็นเมนูหลัก

import json, os, requests
TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]     # อย่าฝัง token ในไฟล์
H = {"Authorization": f"Bearer {TOKEN}"}

# 1) สร้างเมนู ได้ richMenuId กลับมา
r = requests.post("https://api.line.me/v2/bot/richmenu", headers=H, json=RICH_MENU)
r.raise_for_status()
menu_id = r.json()["richMenuId"]

# 2) อัปโหลดรูป — สังเกตโดเมน api-data ไม่ใช่ api
with open("richmenu.png", "rb") as f:
    requests.post(f"https://api-data.line.me/v2/bot/richmenu/{menu_id}/content",
                  headers={**H, "Content-Type": "image/png"}, data=f.read()).raise_for_status()

# 3) ตั้งเป็นเมนูตั้งต้นของทุกคน
requests.post(f"https://api.line.me/v2/bot/user/all/richmenu/{menu_id}",
              headers=H).raise_for_status()

ทำไมเมนูไม่ขึ้น

มีเมนูหลายชั้นซ้อนกัน

LINE เลือกเมนูที่จะแสดงตามลำดับนี้ (ลำดับบนชนะ)

  1. เมนูที่ผูกให้ผู้ใช้รายคนผ่าน API
  2. เมนูตั้งต้นที่ตั้งผ่าน API
  3. เมนูตั้งต้นที่ตั้งใน OA Manager

ถ้าตั้งเมนูใหม่ใน OA Manager แต่ยังมีเมนูตั้งต้นที่เคยตั้งผ่าน API ค้างอยู่ เมนูใน OA Manager จะไม่ขึ้นเลย และเมนูที่สร้างผ่าน API ก็ไม่แสดงในหน้า OA Manager ด้วย ทำให้งงมาก ให้เลือกใช้ทางใดทางหนึ่งให้ชัด

อัปโหลดรูปไม่สำเร็จ

เมนูที่สร้างแล้วแต่ยังไม่มีรูป ตั้งเป็นเมนูหลักไม่ได้ เช็คขนาดไฟล์ (ไม่เกิน 1 MB) และขนาดภาพให้ตรงกับ size ที่กำหนด

แอปของผู้ใช้ยังจำเมนูเก่า

หลังเปลี่ยนเมนู ผู้ใช้บางคนอาจต้องออกจากห้องแชทแล้วเข้าใหม่ถึงจะเห็นเมนูใหม่

ทริคจากงานจริง

  • ลบเมนูเก่าก่อนสร้างใหม่ ในสคริปต์ ดึงรายการด้วย GET /v2/bot/richmenu/list แล้วลบทิ้ง ไม่อย่างนั้นทุกครั้งที่รันจะมีเมนูค้างเพิ่มขึ้นเรื่อยๆ (จำนวนเมนูต่อ OA มีเพดาน)
  • ข้อความในปุ่มต้องตรงกับที่บอทรอรับ ถ้าปุ่มส่ง "นัดหมาย" แต่บอทรอคำว่า "จองคิว" ลูกค้ากดแล้วบอทจะตอบไม่ตรง ให้เก็บคำเหล่านี้ไว้ที่เดียวแล้วใช้ร่วมกันทั้งเมนูและบอท
  • ใช้ปุ่มแบบ uri สำหรับแผนที่และเบอร์โทร เช่นลิงก์ Google Maps ของร้าน ไม่ต้องผ่านบอท
  • อย่าลืมปิดข้อความตอบกลับอัตโนมัติ ใน OA Manager เมื่อใช้ webhook ไม่อย่างนั้นลูกค้าจะได้คำตอบสองชุด

อ่านต่อ: ทำบอทจองคิวผ่าน LINE ด้วย state machine

เกี่ยวกับผู้เขียน — Jark นักพัฒนา LINE Bot และระบบ AI อัตโนมัติ อยู่เชียงใหม่ ทำระบบตอบแชทและจองคิวให้ร้านค้าจริง บทความในเว็บนี้มาจากงานที่ลงมือทำเอง อ่านเพิ่ม