iT邦幫忙

第 11 屆 iThome 鐵人賽

7
Software Development

Line Bot 心得分享 LineMessagingApi + LUIS + BotFramework系列 第 6

[Day06] 如何建立 LINE Bot 的圖文選單 - Rich Menu

今天要介紹的是在 Line Bot 加入圖文選單,那什麼是圖文選單呢?
下方紅框的部分就是圖文選單。

https://ithelp.ithome.com.tw/upload/images/20191216/20106865YSTH7HQqyY.jpg

圖文選單的主要用途如下:

  • 讓第一次使用的人快速了解 Bot 的功能
  • 將 Bot 功能寫在按鈕方便使用者操作
  • 放廣告或最新消息做品牌行銷

要建立圖文選單有兩種方式,第一種進入 Line@ 後台有功能可以使用,第二種透過 Postman 等軟體或寫程式呼叫 API。

雖然下面要介紹的是 API,不過不是因為 "身為工程師當然是要寫程式" 這個原因,我其實很想用功能,沒用的原因是我以為後台建立圖文選單的功能需要收費,小弟口袋不深只好選擇 API,不過最近查資料發現此功能已經變成免費的,可以安心服用了。

2019/4/18 後只要升級官方帳號 2.0 就可以免費使用

既然功能都免費了,當然要用好用滿,不過這篇還是以介紹 API 為主,後台編輯功能可以參考這篇文章,連結: 【功能介紹】圖文影音內容 - 圖文選單 - 電腦版


建立圖文選單

建立 Line Bot 圖文選單需要 Line Bot 的 channel access token,還沒有建立 Line Bot 的讀者可以參考第一篇 [Day01] LINE Bot 帳號申請

這裡會使用 Postman 呼叫 API,Postman 網址

建立圖文選單有三個步驟:

  1. 建立圖文選單
  2. 上傳圖文選單的圖片
  3. 設定預設的圖文選單

1. 建立圖文選單

POST https://api.line.me/v2/bot/richmenu

Request headers

Authorization: Bearer {channel access token}
Content-Type: application/json

Request body

{
    "size": {
      "width": 2500,
      "height": 843
    },
    "selected": false,
    "name": "richmenu-1",
    "chatBarText": "選單1",
    "areas": [
      {
        "bounds": {
          "x": 0,
          "y": 0,
          "width": 833,
          "height": 843
        },
        "action": {
          "type": "message",
          "label": "文字",
          "text": "Hello, iBot!"
        }
      },
      {
        "bounds": {
          "x": 833,
          "y": 0,
          "width": 833,
          "height": 843
        },
        "action": {
          "type": "uri",
          "label": "網址",
          "uri": "https://ithelp.ithome.com.tw/users/20106865/ironman/2732"
        }
      },
      {
        "bounds": {
          "x": 1666,
          "y": 0,
          "width": 833,
          "height": 843
        },
        "action": {
          "type": "postback",
          "label": "選單2",
          "data": "action=changeMenu2"
        }
      }
   ]
}

Response

{
    "richMenuId": "{rich menu id}"
}

這裡稍微解釋一下 API 的用法,詳細說明可以參考官方文件

第一個區塊是 API 的網址,需要使用 POST 方法呼叫

第二區塊是 header 的參數,{channel access token} 要替換成自己申請 Line Bot 時的那個 token,application/json 表示下方 Request body 的格式為 json

第三區塊為 http 的主體,用來定義圖文選單相關的設定

  • size: 圖文選單圖片的長寬,必需為以下尺寸:
    2500x16862500x8431200x8101200x405800x540800x270

  • selected: 選單是否預設開啟,這裡我設定為 false,預設不開啟。

  • name: 選單名稱,用於識別和管理選單,不會顯示給使用者。

  • chatBarText: 顯示在聊天視窗下方的選單文字。

  • areas: 用於定義按鈕的可點墼區域。

    • bounds 用於定義座標和大小

      • x、y: 起始座標

      • width: 寬度

      • height: 高度

    • action 用於定義觸發的動作

      • type: 動作類型,詳細說明可以參考 官方文件

      • label: 動作標籤,用於客戶端輔助功能

      • text: 發送到聊天視窗的文字

      • data: 透過 webhook 回傳到後端的字串

第四區塊為回傳訊息,選單建立成功後會回傳 {rich menu id} 後面 API 會使用到。

Postman 結果

  • Header 部分

https://ithelp.ithome.com.tw/upload/images/20191216/20106865CkXvzBj6iD.jpg

  • Body 部分

https://ithelp.ithome.com.tw/upload/images/20191216/201068657ZKXJHj1pf.jpg


2. 上傳圖文選單的圖片

POST https://api.line.me/v2/bot/richmenu/{rich menu id}/content

[Request headers]
-----------------
Authorization: Bearer {channel access token}
Content-Type: image/jpeg or image/png
Content-Length: request body 大小 (byte)

[Request body]
--------------
圖片主體
格式: JPEG 或 PNG
長寬: 2500x1686, 2500x843, 1200x810, 1200x405, 800x540, 800x270
大小限制: 1 MB

[Response]
----------
{}

將第一步得到的 {rich menu id} 帶入網址,接著 Body 部分選擇 binary 可以選擇圖片,最後按送出,這個步驟比較簡單,成功會回傳 JSON 空物件。

Postman 結果

  • Header 部分

Content-Length 好像可以省略,怕算錯乾脆不要了 (╯‵□′)╯︵┻━┻

https://ithelp.ithome.com.tw/upload/images/20191216/20106865IAMo23I9pa.jpg

  • Body 部分

https://ithelp.ithome.com.tw/upload/images/20191216/201068655dJLezWOOD.jpg


3. 設定預設的圖文選單

POST https://api.line.me/v2/bot/user/all/richmenu/{rich menu id}

[Request headers]
Authorization: Bearer {channel access token}

[Request body]
無

[Response]
{}

這步驟會設定所有用戶預設看到的圖文選單,還有另一個 API 可以單獨設定某位用戶的選單,後面介紹動態選單的時候會用到。

Postman 結果

  • Header 部分

https://ithelp.ithome.com.tw/upload/images/20191216/20106865JFHqXW0ZFF.jpg


結果

https://ithelp.ithome.com.tw/upload/images/20191216/20106865iudV2vWTJr.jpg

。:.゚ヽ(*´∀`)ノ゚.:。


HTML 轉圖片

因為對 Photoshop 不熟,這裡我用 HTML + Font Awesome 把樣子排出來,再用 JS 套件將 HTML 轉成圖片,用於製作陽春的選單還蠻方便的。

JSFiddle

HTML

<table>
  <tr>
    <td id="block1">
      <i class="fa fa-file-text-o icon"></i>
      <div class="text">文字</div>
    </td>
    <td id="block2">
      <i class="fa fa-link icon"></i>
      <div class="text">網址</div>
    </td>
    <td id="block3">
      <i class="fa fa-list icon"></i>
      <div class="text">選單</div>
    </td>
  </tr>
</table>

<div style="margin-top: 10px">
  <input type="button" id="btn" value="另存圖片"/>
</div>

<div id="img"></div>

CSS

table {
  width: 2500px;
  height: 843px;
  border-collapse: collapse;
  font-family: Microsoft JhengHei;
}

table td {
  text-align: center;
  padding: 0px;
}

.icon {
  color: #ffffff;
  font-size: 280px;
}

.text {
  margin-top: 10px;
  color: #ffffff;
  font-size: 120px;
  font-weight: bold;
}

#block1 {
  background-color: #00D084;
  width: 33.33%;
}

#block2 {
  background-color: #2D8665;
  width: 33.33%;
}

#block3 {
  background-color: #00D084;
  width: 33.33%;
}

JS

$(function() { 
    $("#btn").click(function() { 
        html2canvas($("table"), {
            onrendered: function(canvas) {
                $("#img").append(canvas);
                $('#img canvas').css('max-width', '600px');
            }
        });
    });
}); 

色碼

JSFiddle


官方資源下載專區

官方也有許多不錯的資源供大家下載,可以進去挖寶。

https://events.line.me/tw/lineat/minisite/wp-content/themes/line/download.php


動態圖文選單

最後要介紹的是動態選單,什麼是動態選單?

這裡的動態是指,利用 設定的個別用戶選單 這個 API,讓 Line Bot 可以個別切換某位使用者的選單,用途如下。

  • 製作階層選單
  • 擴充圖文選單按紐 (可以超過6個)
  • 為特定族群或使用者客制選單

接下來會實作一個兩層的選單,使用者可以透過上下頁按紐切換。

切換邏輯會利用 API 的優先順序特性,例如: 按下一頁時,程式會將 個別用戶選單 設定為 選單2,因為 個別優先於預設 選單就會切換,而按上一頁時,程式將 個別用戶選單 移除,選單就會切換回去,這裡也可以不用移除,將 個別用戶選單 設定為 選單1 也可以。

圖文選單顯示的優先順序(高到低):

  1. 使用 Messaging API 設定的個別用戶選單
  2. 使用 Messaging API 設定的預設選單
  3. 使用 LINE Official Account Manager 設定的預設選單

製作選單

照上面介紹的方法製作兩個選單。

選單1

"action": {
  "type": "postback",
  "label": "下一頁",
  "data": "action=next"
}

https://ithelp.ithome.com.tw/upload/images/20191216/20106865EH68Efbcho.jpg

選單2

"action": {
  "type": "postback",
  "label": "上一頁",
  "data": "action=prev"
}

https://ithelp.ithome.com.tw/upload/images/20191216/20106865n9xZF7YQ6H.jpg

Postback

可以看到按鈕的 action 我使用了 postback 類型,這個類型會在使用者點擊按紐時,透過 Webhook 呼叫後端的程式,且不會有文字出現在聊天視窗上

另外還可以使用像 QueryString 一樣的方式附帶參數,例如上方我使用 next 和 prev 分別代表兩個按鈕動作,後端收到後就可以以此去執行各自的程式。

不過電腦版的 LINE 看不到圖文選單,這時就只能用文字控制 line Bot 功能,因此各有其優缺點,但如果單看圖文選單,比起文字類型會更推薦使用 Postback。

使用 LineMessagingApi 切換圖文選單

開啟 LineBotApp.cs 加入下面程式。

protected override async Task OnPostbackAsync(PostbackEvent ev)
{
    var query = HttpUtility.ParseQueryString(ev.Postback.Data);

    //頻道Id
    var channelId = ev.Source.Id;
    //使用者Id
    var userId = ev.Source.UserId;

    switch (query["action"])
    {
        //下一頁
        case "next":
            {
                //設定個別用戶選單
                await _messagingClient.LinkRichMenuToUserAsync(userId, "選單2 的Id");
            }
            break;
        //上一頁
        case "prev":
            {
                //移除個別用戶選單
                await _messagingClient.UnLinkRichMenuFromUserAsync(userId);
            }
            break;
    }
}

完整 LineBotApp.cs 可以參考:
[Day02] 使用 .NET Core 3.0 + LineMessagingApi 串接 Line Bot

結果

預設選單

https://ithelp.ithome.com.tw/upload/images/20191216/20106865A81Z42MYz3.jpg

點下一頁會跳到選單2,點上一頁又會返回

https://ithelp.ithome.com.tw/upload/images/20191216/20106865fKyFi7hkXP.jpg


[C#] 建立圖文選單 - LineMessagingApi 用法

這邊是筆記,將上面使用 Postman 的地方改成 C#。

  • 建立圖文選單
var richMenu = new RichMenu()
{
    Size = new ImagemapSize(2500, 843),
    Selected = false,
    Name = "richmenu-1",
    ChatBarText = "選單1",
    Areas = new List<ActionArea>()
    {
        new ActionArea()
        {
            Bounds = new ImagemapArea(0, 0 ,833, 843),
            Action = new MessageTemplateAction("文字", "Hello, iBot!")
        },
        new ActionArea()
        {
            Bounds = new ImagemapArea(833, 0 ,833, 843),
            Action = new UriTemplateAction("網址", "https://ithelp.ithome.com.tw/users/20106865/ironman/2732")
        },
        new ActionArea()
        {
            Bounds = new ImagemapArea(1666, 0 ,833, 843),
            Action = new PostbackTemplateAction("選單2", "action=changeMenu2")
        }
    }
};
var richMenuId = await _messagingClient.CreateRichMenuAsyn(richMenu);
  • 上傳圖文選單的圖片
var image = new MemoryStream(File.ReadAllBytes(@"richmenu.png"));
await _messagingClient.UploadRichMenuPngImageAsync(image, richMenuId);
  • 設定預設的圖文選單
await _messagingClient.SetDefaultRichMenuAsync(richMenuId);

其他相關 API

詳細內容可參考 官方文件

  • 查詢所有圖文選單
GET https://api.line.me/v2/bot/richmenu/list

[Request headers]
Authorization: Bearer {channel access token}

[Response]
JSON 格式的列表清單
  • 刪除圖文選單
DELETE https://api.line.me/v2/bot/richmenu/{rich menu id}

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}
  • 取得預設的圖文選單
GET https://api.line.me/v2/bot/user/all/richmenu

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{
    "richMenuId": "{rich menu id}"
}
  • 取消預設的圖文選單
DELETE https://api.line.me/v2/bot/user/all/richmenu

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

結語

這篇本來沒準備寫這麼長,沒想到資料越找越多,還意外發現動態選單的用法,手癢就自己實做了一次。最後的切換選單功能,用起來其實有點卡卡的,會延遲個1~2秒,在可以接受的範圍拉,選單功能如果不需要頻繁切換,總體來說還是不錯的。

在過程中還看到一位大大的鐵人文 LINE bot 好好玩 30 天玩轉 LINE API
這位大大把 LINE 可以玩的 API 都試過了一次,我這才知道原來 LINE API 可以玩的東西這麼多,LINE 真是越來越強大了,有興趣的朋友可以去看他的鐵人文。

下一篇要將 Line Bot 結合資料庫,內容會介紹如何在 Azure 的 App Service 開啟 MySql 資料庫,並且會搭配 Entity Framework 使用,會教大家建立 Model 並透過 Fluent API 設定資料表的屬性和關聯。

最後會實做出一個完整的功能,目前規劃是可以透過 Line Bot 訂閱某人 it 邦的首頁,程式會透過爬蟲每天去取得文章的觀看數,接著可以透過 Line Bot 查詢每日、每周、每月,前5名,點閱數增加最多的文章。

今天就到這,感謝大家觀看~~~

參考文章

用LINE bot api建立line@圖文選單
如何建立LineBot圖文選單
Linebot-Demo-DynamicRichMenu
Messaging API reference
Using rich menus


上一篇
[Day05] 在 LINE Bot 加入 LUIS 語意分析服務
下一篇
[Day07] 使用 EF Core 讀取 Azure 上的 MySQL 資料庫
系列文
Line Bot 心得分享 LineMessagingApi + LUIS + BotFramework27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3
cathywen14
iT邦新手 4 級 ‧ 2019-12-18 15:28:56

居然連選單功能都做了!! 推推~

一定要的啊 〜( ̄▽ ̄〜) (〜 ̄▽ ̄)〜

1
eric19740521
iT邦新手 1 級 ‧ 2020-01-06 13:40:30

讚喔!!!用得上,很棒的文章

謝謝 ╰( ̄▽ ̄)╭

感謝你提供的工具
http://ezpos.info/linebot/%E4%B8%8B%E8%BC%89%20(4).png

/images/emoticon/emoticon12.gif

0
yicheng0615
iT邦新手 5 級 ‧ 2020-07-16 15:29:14

請問可以做postman製作子選單的詳細教學嗎?遇到瓶頸了看不懂

看更多先前的回應...收起先前的回應...

首先使用文中介紹的方式建立兩個圖文選單
接著將第一個選單設為預設選單

POST https://api.line.me/v2/bot/user/all/richmenu/{richMenuId_1}

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

然後就可以使用下面的 API 切換選單

下一頁:

設定 User 的 Rich Menu

POST 
https://api.line.me/v2/bot/user/{userId}/richmenu/{richMenuId_2}

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

上一頁:

取消 User 的 Rich Menu

DELETE https://api.line.me/v2/bot/user/{userId}/richmenu

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

這個是不是不能用python呀?

user id是line developers裡面的user id嗎?
我製作好2個選單,下一頁跟上一頁也都弄好了
但我不是很明白 "然後就可以使用下面的 API 切換選單"這一句
不好意思我第一次學習,很多地方不懂

Python 我使用這個 SDK。
https://github.com/line/line-bot-sdk-python

@handler.add(PostbackEvent)
def handle_postback(event):
    # postback 資料
    data = event.postback.data
    # 使用者Id
    userId = event.source.user_id
    
    # 下一頁
    if data == "action=next":
        # 設定個別用戶選單
        line_bot_api.link_rich_menu_to_user(userId, <rich_menu_id>)
    # 上一頁
    elif data == "action=prev":
        # 移除個別用戶選單
        line_bot_api.unlink_rich_menu_from_user(userId)

1.user id是line developers裡面的user id嗎?

不是喔,是 Message API 傳給我們的使用者Id

2.但我不是很明白 "然後就可以使用下面的 API 切換選單"這一句

下面兩個 API 可以讓不同使用者看到不同的選單
切換選單就是運用這兩個 API 達成的
不過一般不會直接拿來使用
會向上面的程式一樣
使用官方包裝好的 SDK

所以我是要在我的程式碼加上上面那一段嗎?
然後postman不用更動的意思嗎?
那上面的程式碼哪些是我要改的呀

恩恩,Postman 只要做 建立選單設定預設選單 就好
子選單切換需要用程式

那上面的程式碼哪些是我要改的呀

不知道你目前的寫法,無法給建議

所以上一頁跟下一頁那個也做出來就好不用動對嗎?
https://ithelp.ithome.com.tw/upload/images/20200721/20128656A8XZTALcov.png
目前只有最基本的東西,將程式與linebot做結合而已

將上面的程式直接加入 callback 下方就可以
<rich_menu_id> 的部分替換成第二選單的 id
不過我沒有測過,你要試試看

加進去了,但還是沒反應,不知道為什麼...

user id 是這邊個嗎
https://ithelp.ithome.com.tw/upload/images/20200723/20128656H8M51CGpwv.png

可以了,感謝你

用程式取得的 userId 才能符合所有使用者喔

# 使用者Id
userId = event.source.user_id
0
KLXTaro
iT邦新手 5 級 ‧ 2020-10-01 00:20:13

博主您好,想請問我的postman設定是不是有問題?,一直報cors error的錯orzhttps://ithelp.ithome.com.tw/upload/images/20201001/20117685v0oTQvZuE1.jpg

網頁版的 Postman 有跨域限制 (這是瀏覽器本身的安全機制)
可以改用桌面板或 Chrome 擴充版
/images/emoticon/emoticon12.gif

KLXTaro iT邦新手 5 級 ‧ 2020-10-02 20:14:11 檢舉

謝謝你的教學,我成功了✧*。٩(ˊᗜˋ*)و✧*

/images/emoticon/emoticon12.gif

0
cloudyang
iT邦新手 5 級 ‧ 2021-07-06 22:27:53

想請問,我的line bot後端是架在heroku,若我想做出動態圖文選單,那麼LineBotApp.cs要怎麼加上去執行呢?
https://ithelp.ithome.com.tw/upload/images/20210706/20139237HvF45iK9gY.png

看更多先前的回應...收起先前的回應...

原程式是 Python 的話,感覺改成 Python 比較快 ?

SDK:
https://github.com/line/line-bot-sdk-python

@handler.add(PostbackEvent)
def handle_postback(event):
    # postback 資料
    data = event.postback.data
    # 使用者Id
    userId = event.source.user_id
    
    # 下一頁
    if data == "action=next":
        # 設定個別用戶選單
        line_bot_api.link_rich_menu_to_user(userId, <rich_menu_id>)
    # 上一頁
    elif data == "action=prev":
        # 移除個別用戶選單
        line_bot_api.unlink_rich_menu_from_user(userId)
cloudyang iT邦新手 5 級 ‧ 2021-07-07 11:34:10 檢舉

哇!太感謝啦/images/emoticon/emoticon02.gif

cloudyang iT邦新手 5 級 ‧ 2021-07-07 12:30:14 檢舉

有成功了,在改改圖片就好,真的非常謝謝您

/images/emoticon/emoticon12.gif /images/emoticon/emoticon12.gif /images/emoticon/emoticon12.gif

0
arguskao
iT邦新手 4 級 ‧ 2022-06-09 21:27:30

官方資源下載專區

連結好像失效?

恩失效了,不過時間太久,我也忘記內容是什麼了

我要留言

立即登入留言