【2022年改訂版】AizuHack LINEBot勉強会 Vol.2

# AizuHack LINEBot勉強会 Vol.2

## 資料一覧

- [LINEBotとは](https://docs.google.com/presentation/d/1U1vl67gJNOdO5in7H__jPXWieT3Lv0cFmv350AmAKHA/edit?usp=sharing)
- [AizuHack LINEBot勉強会 Vol.1](https://qiita.com/shinbunbun_/items/7efef6db31514831143d)
- AizuHack LINEBot勉強会 Vol.2(本記事)
- [AizuHack LINEBot勉強会 Vol.3](https://qiita.com/shinbunbun_/items/0dfc42584518dc60e3e7)
- [AizuHack LINEBot勉強会 Vol.4](https://qiita.com/shinbunbun_/items/43e2c486ac8839a6d32e)

## はじめに

こんにちは、会津大学学部二年のしんぶんぶんです。

本記事はAizuHackのLINEBot勉強会 Vol.2の資料になります。

前回の勉強会ではLINEBotの基本的な使い方を学習しました。今回の勉強会では、ちょっと発展的な内容として

- 前回演習問題の解説
- LINE Bot Designerの使い方
- Flex Message Simulatorの使い方
- リッチメニューの作り方
- PUSHメッセージ

について解説していきます。

## 前回演習問題の解説

前回は以下のような演習問題を出しました。

自分のQ2の時間割を確認するbotを作ってみましょう。要件は以下のとおりです。

- 「時間割」と送信すると、曜日を選択するボタンが出てくる（クイックリプライなどでも可）
- ボタンを押すと、その曜日の時間割が送られてくる

実装は2つのフェーズにわかれます。
まず1つ目はクイックリプライで月から金曜日を選択するボタンを作る、2つ目はそれぞれのボタンを押した時のメッセージに応じて時間割を返す処理を実装するフェーズです。

まずクイックリプライは`message.js`の`textEvent`関数のswitch文に以下のようなコードを追記することで実装できます。

```javascript
case '時間割': {
  // 返信するメッセージを作成
  message = {
    type: 'text',
    text: '時間割を知りたい曜日を選んでください',
    quickReply: {
      items: [
        {
          type: 'action',
          action: {
            type: 'message',
            text: '月曜日の時間割',
            label: '月曜日',
          },
        },
        {
          type: 'action',
          action: {
            type: 'message',
            text: '火曜日の時間割',
            label: '火曜日',
          },
        },
        {
          type: 'action',
          action: {
            type: 'message',
            text: '水曜日の時間割',
            label: '水曜日',
          },
        },
        {
          type: 'action',
          action: {
            type: 'message',
            text: '木曜日の時間割',
            label: '木曜日',
          },
        },
        {
          type: 'action',
          action: {
            type: 'message',
            text: '金曜日の時間割',
            label: '金曜日',
          },
        },
      ],
    },
  };
  break;
}
```

次に、それぞれのメッセージに対して返信するコードを追記します。

```javascript
case '月曜日の時間割': {
  // 返信するメッセージを作成
  message = {
    type: 'text',
    text: '1. 力学\n2. 力学\n3. 力学\n4. 力学\n5. 微積分\n6. 微積分',
  };
  break;
}
case '火曜日の時間割': {
  // 返信するメッセージを作成
  message = {
    type: 'text',
    text: '3. プログ0\n4. プログ0\n5. プログ0\n6. プログ0\n7. Eng2\n8. プログ0\n9. 経済学\n10. 経済学',
  };
  break;
}
case '水曜日の時間割': {
  // 返信するメッセージを作成
  message = {
    type: 'text',
    text: '3. 微積分\n4. 微積分',
  };
  break;
}
case '木曜日の時間割': {
  // 返信するメッセージを作成
  message = {
    type: 'text',
    text: '1. 力学\n2. 力学\n3. 力学\n4. 力学\n5. 微積分\n6. 微積分\n7. 体育実技\n8. 体育実技',
  };
  break;
}
case '金曜日の時間割': {
  // 返信するメッセージを作成
  message = {
    type: 'text',
    text: '3. プログ0\n4. プログ0\n5. プログ0\n6. プログ0\n7. Eng2\n8. プログ0\n9. 経済学\n10. 経済学',
  };
  break;
}
```

これで完成です！

## LINE Bot Designerの使い方

### LINE Bot Designerとは

LINE Bot Designerとは、GUIでポチポチするだけでLINEBotのプロトタイプが作れるツールです。
作ったメッセージはJSON形式で吐き出せるようになっており、Botのソースコードにそのまま貼り付けるだけで動きます。

### LINE Bot Designerを使ってみよう

1. [ダウンロードページ](https://developers.line.biz/ja/services/bot-designer/)からダウンロードしてインストール
2. 開くとトップページが出てくるので、「プロジェクトを作成」を選択する
   1. すでに用意されているテンプレートを使用することもできます
3. Bot名、会社名、カテゴリー名の入力を求められるので、適当な情報を入力する

- 左側のメニューの一番上のアイコンを押すと、返信するメッセージを作成できる
  - 「メッセージ」、「リッチメニュー」、「Webアプリ」から作りたい素材を作成していく
  - 右下にメッセージのJSONが表示されるため、そのままコピペで使える（ただし、画像をローカルから読み込んだ場合はどこかのサーバーに置く必要がある）
- 左側メニューの真ん中のボタンを押すとFlex Messageを作成できる（が、後ほど説明するFlex Message Simulatorの方が使いやすいかも...）
- 左側メニューの一番下のボタンを押すとシナリオを作成できる
  - 自動で返信したりする機能はないので、ユーザーから送信するメッセージとBotから返信するメッセージを両方手動で送信して、シナリオを作るという使い方

### 演習1

では実際に「自分が入っているサークルの紹介をする」シナリオを作ってみましょう

製作例は以下のとおりです

![Videotogif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/d69ed483-8b0c-2109-a2b5-324d39377ab9.gif)

LINE Bot Designerでプロトタイプが完成したら、実際のBotに実装してみましょう。

## Flex Messageについて

### Flex Messageとは

CSS Flexible Boxをベースに設計されているメッセージで、レイアウトを自由にカスタマイズできます。
たとえばヤマト運輸やLINEウォレットで使われている、以下のように自由なレイアウトのメッセージも、FlexMessageを使えば作ることができます。

![IMG_2028.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/fcf4d0d4-7f5d-506d-239a-96d19fa152a1.png)
![IMG_2029.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/ecb2f441-46d9-7975-73b6-419ea5a32587.png)

[公式ドキュメントのFlex Messageに関する章](https://developers.line.biz/ja/docs/messaging-api/using-flex-messages/)にもメッセージ例がいくつか掲載されています。

Flex MessageもJSONを使って作成しますが、[Flex Message Simulator](https://developers.line.biz/flex-simulator/)を使えばGUIぽちぽちで作れます。

### Flex Messageの構造について

※以下の解説は公式ドキュメントをもとに作成しています。

Flex Messageは、コンテナ、ブロック、コンポーネントの3層のデータ構造から構成されます。
一番大枠がコンテナで、コンテナの中に各ブロックがあり、各ブロックの中に各コンポーネント（要素）が入っているといった構造です。
ブロックにはヘッダー、ヒーロー、ボディ、フッターの4種類があります。

![overviewSample.772a618f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/cbb6b51a-569f-be8e-3074-22797e19a60c.png)

※画像は[公式ドキュメント](https://developers.line.biz/ja/docs/messaging-api/flex-message-elements/)より引用

JSONの書き方など詳しい情報は[リファレンス](https://developers.line.biz/ja/reference/messaging-api/#flex-message)に掲載されているので是非ご一読ください。
以下では概要を説明します。

#### コンテナ

コンテナには、バブル、カルーセルの2種類があります。
バブルは1つのメッセージをもので、カルーセルは複数のメッセージを横スクロールできる形で展開するものになります。

#### ブロック

ブロックにはヘッダー、ヒーロー、ボディ、フッターの4種類があります。
各ブロックは同じコンテナ内ではそれぞれ1つずつまでしか使えません（省略することは可能です）。

- ヘッダー
  - メッセージの件名や見出しを表示するブロック
- ヒーロー
  - 画像などの主要なコンテンツを表示するブロック
- ボディ
  - 主要なメッセージコンテンツを表示するブロック
- フッター
  - ボタンや補足情報を表示するブロック

![ダウンロード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/dbc653fc-1e9b-ce8f-1c2b-8705488d3c02.png)

※画像は[公式ドキュメント](https://developers.line.biz/ja/docs/messaging-api/flex-message-elements/)より引用

#### コンポーネント

コンポーネントには以下の種類があります。

- ボックス
  - コンポーネントのレイアウトを定義するコンポーネント
  - ボックスの中に複数の子要素を内包でき、それらの子要素のレイアウトを定義できます（水平に配置するか垂直に配置するかなど）。
  - Flex Messageのレイアウトについては、公式ドキュメントの[Flex Messageのレイアウト](https://developers.line.biz/ja/docs/messaging-api/flex-message-layout/)で確認できます。
- ボタン
- 画像
- アイコン
- テキスト
  - 1行の文字列を描画するコンポーネント。色、サイズ、および太さを指定できる。
- スパン
  - 1行に、デザインが異なる複数の文字列を描画するコンポーネント。それぞれの色、サイズ、太さ、および装飾を指定できる。
- セパレータ
  - 分割線を描画するコンポーネント
- フィラー
  - スペースを作るためのコンポーネント
  - これを使うことで、コンポーネントの間などにスペースを作ることができる

### 演習2 Flex Message Simulatorを使ってみよう

Flex Message Simulatorとは、GUIぽちぽちでFlex Messageのレイアウトを作成することができるツールです。
公式ドキュメントで[デジタル名刺を作るチュートリアル](https://developers.line.biz/ja/docs/messaging-api/using-flex-message-simulator/)が公開されているので、こちらを参考にデジタル名刺を作ってみましょう。

作り終わったらBotに実装してみましょう。

ただし、Flex Message Simulatorで生成されるコードはFlex Messageのcontents部分だけのコードになるため、実装する際は以下ようにする必要があります。

```javascript
case 'Flex Message Profile': {
  // 返信するメッセージを作成
  message = {
    type: 'flex',
    altText: 'Flex Message',
    contents: {}, //ここの{}をFlexMessage Simulatorで生成されたコードに置き換える
  };
  break;
}
```

制作例は以下のとおりです。

![IMG_E1A9A475D122-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/43049ed5-8c69-7b33-9b3c-2d2a18f677a5.jpeg)

## リッチメニューについて

### リッチメニューとは

リッチメニューとは、トーク画面の下部に表示されるメニュー画面のことです。
画像とタップ領域、タップした際のアクションを設定することで自由なレイアウトのメニューを作成できます。
使用できるアクションは、メッセージアクション、URIアクション、ポストバックアクション、日時選択アクション、リッチメニュー切替アクションです。

### リッチメニューを作ってみよう

【追記（2022/06/04）】

[いーちゃん](https://e-chan.cf/)が作ってくれた[リッチメニューエディタ](https://richmenu.app.e-chan.cf/)を使えばGUIぽちぽちで作ることもできます。
興味ある方は是非使ってみてくださいー。

それではリッチメニューを作ってみましょう。
まずはリッチメニュー用の画像を用意します。
今回は作成済みの画像を用意しているため、そちらを利用して作っていきましょう。
画像は以下のリンクからダウンロードしてください。

- [リッチメニュー1](https://raw.githubusercontent.com/shinbunbun/aizuhack-bot/master/material/richmenu1.jpg)
- [リッチメニュー2](https://raw.githubusercontent.com/shinbunbun/aizuhack-bot/master/material/richmenu2.jpg)

作成の流れは以下のとおりです。

1. リッチメニュー1を作成する
2. リッチメニュー1の画像をアップロードする
3. リッチメニュー2を作成する
4. リッチメニュー2の画像をアップロードする
5. リッチメニュー1をデフォルトのリッチメニューに設定する
6. リッチメニュー1のエイリアスを作成する
7. リッチメニュー2のエイリアスを作成する

リッチメニューの作り方は[こちらの公式ドキュメント](https://developers.line.biz/ja/docs/messaging-api/using-rich-menus/)をベースに解説します。

#### リッチメニュー1を作成しよう

まずはリッチメニューAPIを使ってリッチメニューを作成して行きましょう。

以下のコマンドをterminalで実行します（Windowsでcmdを使っている人はcurl.exeで実行できるらしいです）。

※`{AccessToken}`を自分のチャネルアクセストークンに変更してください。

```terminal
curl -v -X POST https://api.line.me/v2/bot/richmenu \
-H 'Authorization: Bearer {AccessToken}' \
-H 'Content-Type: application/json' \
-d \
'{
  "size": {
    "width": 2500,
    "height": 1686
  },
  "selected": true,
  "name": "richmenu-1",
  "chatBarText": "メニュー1",
  "areas": [
    {
      "bounds": {
        "x": 1250,
        "y": 0,
        "width": 1250,
        "height": 200
      },
      "action": {
        "type": "richmenuswitch",
        "richMenuAliasId": "richmenu-alias-2",
        "data": "richmenu-changed-to-2"
      }
    },
    {
      "bounds": {
        "x": 0,
        "y": 200,
        "width": 833,
        "height": 1486
      },
      "action": {
        "type": "message",
        "text": "richmenu-1-message"
      }
    },
    {
      "bounds": {
        "x": 833,
        "y": 200,
        "width": 833,
        "height": 1486
      },
      "action": {
        "type": "postback",
        "data": "richmenu-1-postback"
      }
    },
    {
      "bounds": {
        "x": 1666,
        "y": 200,
        "width": 833,
        "height": 1486
      },
      "action": {
        "type": "uri",
        "uri": "https://shinbunbun.info/"
      }
    }
  ]
}'
```

実行すると`{"richMenuId":"richmenu-XXXXXXXXXXXXXXXXX"}`というレスポンスが返ってきます。このIDはあとで使うのでメモしておいてください。

#### リッチメニュー1の画像をアップロードしよう

リッチメニュー1の作成が完了したので、画像をアップロードします。
以下のコマンドを実行してください。

※`{richMenuId}`に先ほど作成したリッチメニューID（`richmenu-XXXXXXXXXXXXXXXXX`）を、`{AccessToken}`に自分のチャネルアクセストークンを、`{imagePath}`にリッチメニュー1の画像のパス（`material/richmenu1.jpg`）を指定してください。

```terminal
curl -v -X POST https://api-data.line.me/v2/bot/richmenu/{richMenuId}/content \
-H 'Authorization: Bearer {AccessToken}' \
-H "Content-Type: image/png" \
-T {imagePath}
```

ステータスコード200で空のレスポンス（`{}`）が帰ってきたら成功です。

#### リッチメニュー2を作成しよう

続いてリッチメメニュー2を作成します。
基本的な手順はリッチメニュー1と同じです。

まずは以下のコマンドを実行します。

※`{AccessToken}`を自分のチャネルアクセストークンに変更してください。

```terminal
curl -v -X POST https://api.line.me/v2/bot/richmenu \
-H 'Authorization: Bearer {AccessToken}' \
-H 'Content-Type: application/json' \
-d \
'{
  "size": {
    "width": 2500,
    "height": 1686
  },
  "selected": true,
  "name": "richmenu-2",
  "chatBarText": "メニュー2",
  "areas": [
    {
      "bounds": {
        "x": 0,
        "y": 0,
        "width": 1250,
        "height": 200
      },
      "action": {
        "type": "richmenuswitch",
        "richMenuAliasId": "richmenu-alias-1",
        "data": "richmenu-changed-to-1"
      }
    },
    {
      "bounds": {
        "x": 0,
        "y": 200,
        "width": 833,
        "height": 1486
      },
      "action": {
        "type": "message",
        "text": "richmenu-2-message"
      }
    },
    {
      "bounds": {
        "x": 833,
        "y": 200,
        "width": 833,
        "height": 1486
      },
      "action": {
        "type": "postback",
        "data": "richmenu-2-postback"
      }
    },
    {
      "bounds": {
        "x": 1666,
        "y": 200,
        "width": 833,
        "height": 1486
      },
      "action": {
        "type": "uri",
        "uri": "https://shinbunbun.info/"
      }
    }
  ]
}'
```

実行すると`{"richMenuId":"richmenu-XXXXXXXXXXXXXXXXX"}`というレスポンスが返ってきます。このIDはあとで使うのでメモしておいてください。

#### リッチメニュー2の画像をアップロードしよう

リッチメニュー2の作成が完了したので、画像をアップロードします。
以下のコマンドを実行してください。

※`{richMenuId}`に先ほど作成したリッチメニューID（`richmenu-XXXXXXXXXXXXXXXXX`）を、`{AccessToken}`に自分のチャネルアクセストークンを、`{imagePath}`にリッチメニュー2の画像のパス（`material/richmenu2.jpg`）を指定してください。

```terminal
curl -v -X POST https://api-data.line.me/v2/bot/richmenu/{richMenuId}/content \
-H 'Authorization: Bearer {AccessToken}' \
-H "Content-Type: image/png" \
-T {imagePath}
```

ステータスコード200で空のレスポンス（`{}`）が帰ってきたら成功です。

#### リッチメニュー1をデフォルトのリッチメニューに設定しよう

リッチメニューは作っただけではユーザーに表示されず、各ユーザーごとに紐付けをしてあげる必要があります（詳しくは[こちら](https://developers.line.biz/ja/reference/messaging-api/#link-rich-menu-to-user)）。
しかしながら、友達追加したユーザー全員にいちいち紐付けを行うのは非常に手間がかかります。
デフォルトに設定されたリッチメニューは友達追加したユーザーに自動で表示されるため、いちいち紐付けせずに済んでとても便利です。

今回はリッチメニュー1をデフォルトのリッチメニューに指定します。
以下のコマンドを実行してください。

※`{richMenuId}`にリッチメニュー1のID（`richmenu-XXXXXXXXXXXXXXXXX`）を、`{AccessToken}`に自分のチャネルアクセストークンを指定してください。

```terminal
curl -v -X POST https://api.line.me/v2/bot/user/all/richmenu/{richMenuId} \
-H 'Authorization: Bearer {AccessToken}'
```

ステータスコード200で空のレスポンス（`{}`）が帰ってきたら成功です。

botとのトーク画面を開くと以下のようなメニューが表示されているかと思います。

![IMG_2027.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/a3b7417a-2746-bd2f-684c-f0cf113e8898.png)

#### リッチメニュー1のエイリアスを作成しよう

今の状態でもリッチメニューのボタンは機能するかと思いますが、エイリアスを作成していないためリッチメニューの切り替えがまだできません。
まずはリッチメニュー1からエイリアスを作成します。
以下のコマンドを実行してください。

※`{richMenuId}`にリッチメニュー1のID（`richmenu-XXXXXXXXXXXXXXXXX`）を、`{AccessToken}`に自分のチャネルアクセストークンを指定してください。

```terminal
curl -v -X POST https://api.line.me/v2/bot/richmenu/alias \
-H 'Authorization: Bearer {AccessToken}' \
-H 'Content-Type: application/json' \
-d \
'{
    "richMenuAliasId": "richmenu-alias-1",
    "richMenuId": "{richMenuId}"
}'
```

ステータスコード200で空のレスポンス（`{}`）が帰ってきたら成功です。

#### リッチメニュー2のエイリアスを作成しよう

続いてリッチメニュー2のエイリアスを作成します。
以下のコマンドを実行してください。

※`{richMenuId}`にリッチメニュー2のID（`richmenu-XXXXXXXXXXXXXXXXX`）を、`{AccessToken}`に自分のチャネルアクセストークンを指定してください。

```terminal
curl -v -X POST https://api.line.me/v2/bot/richmenu/alias \
-H 'Authorization: Bearer {AccessToken}' \
-H 'Content-Type: application/json' \
-d \
'{
    "richMenuAliasId": "richmenu-alias-2",
    "richMenuId": "{richMenuId}"
}'
```

ステータスコード200で空のレスポンス（`{}`）が帰ってきたら成功です。

ここまで設定できたらリッチメニューが切り替えられるようになっているはずです。

#### リッチメニュー切り替えアクションについて

リッチメニュー切り替えアクションは日時選択アクションと同じくポストバックアクションに分類されるため、切り替えるたびにサーバへ以下のようなポストバックデータが飛んできます。

```javascript
[
  {
    type: 'postback',
    postback: { data: 'richmenu-changed-to-1', params: { newRichMenuAliasId: "richmenu-alias-1", status: "SUCCESS" } },
    timestamp: 1624523044456,
    source: { type: 'user', userId: 'U6b53f4ad79a23f5427119cb44f08dbd7' },
    replyToken: '2ced0e0290b4405e8764e92388a31e1a',
    mode: 'active'
  }
]
```

今回のサンプルコードはparamsが含まれているものをすべて日時選択アクションとして認識しているため、「日時データが送られてきました」と返ってくると思います。
ここも実装をきちんとすればハンドリングができるため、興味がある方は是非試してみてください。

#### リッチメニューに関するtips

今回はこちらで画像を用意しましたが、自分でBotを作る際には画像の作成や座標の指定を全て自分でする必要があります。
その際に便利に使えるツールなどをいくつか紹介します。

- Adobe Illustrator
  - 言わずと知れた最強ツール
  - しかし高い
  - 僕はこれを使っている
- Figma
  - UIデザインなどを作成するツール
  - 無料で使える
  - AizuHackのデザイン勉強会ではこれを使ったUIデザインを教えている
  - これを使ってリッチメニューのデザインを作っている人もいるらしい
- Microsoft PowerPoint
  - シンプルにつらい
  - 特に座標の指定がめっちゃ辛い
  - おすすめはできない

また、今回はcurlコマンドを使って作りましたが、[SGG](https://qiita.com/organizations/sgg)メンバーの[いーちゃん](https://qiita.com/e_chan1007)が[リッチメニューエディタ](https://richmenu.app.e-chan.cf/)というものを作ってくれています。
これを使えばGUIでぽちぽちするだけでリッチメニューが作れるのでおすすめです。

### PUSHメッセージについて

LINE Messaging APIで送れるメッセージには、以下の種類があります。

- 応答メッセージ
  - イベントに対して返信できるメッセージです
  - これまで解説したメッセージはすべてこの応答メッセージです
- プッシュメッセージ
  - こちら側から任意のタイミングで単体ユーザーに送信できるメッセージです
- マルチキャストメッセージ
  - こちら側から任意のタイミングで複数ユーザーに送信できるメッセージです
- ナローキャストメッセージ
  - 性別や年齢、OSの種類、地域などをターゲッティングしてマルチキャストできるメッセージです。
- ブロードキャストメッセージ
  - 友達追加されている全ユーザー（ブロックされているユーザーをのぞく）に一斉送信できるメッセージです。

※応答メッセージ以外は、無料版のLINE公式アカウントでは月1000件までしか送信できません。

今回はこのPUSHメッセージの送り方を解説します。

#### curlでの送り方

まずはcurlでプッシュメッセージを送ってみましょう。

terminalで以下のコマンドを実行してください。

※`{AccessToken}`を自分のチャネルアクセストークンに、`{userId}`を自分のuserIdに変えてください。

自分のuserIdはLINE Developersのチャネルページの`チャネル基本設定`→`基本情報`→`あなたのユーザーID`から確認できます。

```terminal
curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {AccessToken}' \
-d '{
    "to": "{userId}",
    "messages":[
        {
            "type":"text",
            "text":"Hello, world"
        }
    ]
}'
```

ステータスコード200で空のレスポンス（`{}`）が返ってきて、`Hello World`というメッセージが送られてきたら成功です。

#### Node.jsのSDKでの使い方

※`{accessToken}`を自分のチャネルアクセストークンに、`{userId}`を自分のuserIdに変えてください。

Node.jsのSDKでは以下のようなコードで実行できます。

```javascript
const require('@line/bot-sdk')

const client = new line.Client({
  channelAccessToken: '{accessToken}'
});

const message = {
  type: 'text',
  text: 'Hello World'
};

client.pushMessage('{userId}', message)
```

## おわりに

皆さんお疲れ様でした。第3回では以下の内容について学びます。

- node-json-dbを使った簡易データベース
- 外部APIとの通信
- LINE Front-end Framework（LIFF）の使い方

第3回は[こちら](https://qiita.com/shinbunbun_/items/0dfc42584518dc60e3e7)