【LINE Messaging API, GAS】ボタン形式の応答メッセージを実装（Flex Message）

## 確認
+ LINE Developers アカウント、プロバイダー、チャンネル作成済み
+ Google アカウント作成済み
+ 特定のメッセージに対する返信を実装したい
+ ボタンを送信したい

## 実行例
「テスト」と送信すると、「クリック」と書かれたボタンが送られてくる。ボタンを押すと「クリックした！」と送信される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/9d21f569-9fb1-be1e-e956-2dce7a40524e.png)

## 手順
### 1. Channel access token の取得
[LINE Developers Console](https://developers.line.biz/console/)の「Messaging API」タブを開く。「Channel access token (long-lived)」の「Issue」をクリックし、キーをコピーする。

### 2. Flex Message の実装
[Flex Message Simulator](https://developers.line.biz/flex-simulator/)でシミュレーションしながら実装できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/6ef7e5bc-45ee-a5b8-a3e0-91eccf9cdc32.png)

```json:JSON
{
  "type": "bubble",
  "body": {
    "type": "box",
    "layout": "vertical",
    "contents": [
      {
        "type": "button",
        "action": {
          "type": "message",
          "label": "クリック",
          "text": "クリックした！"
        }
      }
    ],
    "paddingAll": "0px"
  }
}
```
### 3. Google Apps Scriptの作成
[Google Drive](https://drive.google.com/drive/my-drive)のマイドライブ上で右クリック → その他 → Google Apps Script を選択
![スクリーンショット (242).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/3ea5e93d-01a8-11b8-d63f-feb63a194d65.png)

### 4. gsファイルの作成
[GitHub](https://github.com/probabilityhill/line-1btn-msg-gas)

```js:main.gs
// 環境変数を設定
const SCRIPT_PROPERTIES = PropertiesService.getScriptProperties();             // スクリプトプロパティを取得
SCRIPT_PROPERTIES.setProperty("ACCESS_TOKEN", "ここにアクセストークンを入力");   // 1度実行したら削除する
// アクセストークンの取得
const ACCESS_TOKEN = SCRIPT_PROPERTIES.getProperty("ACCESS_TOKEN");

// Flex Message Simulatorで作成したJSONコード
const CLICK_BTN = {
  "type": "bubble",
  "body": {
    "type": "box",
    "layout": "vertical",
    "contents": [
      {
        "type": "button",
        "action": {
          "type": "message",
          "label": "クリック",
          "text": "クリックした！"
        }
      }
    ],
    "paddingAll": "0px"
  }
};

// Flex Messageを取得
function getFlexMsg(label, content){
  return {
    "type": "flex",
    "altText": label,
    "contents": content
  };
}

// イベントを受け取って実行する
function doPost(e){
  const EVENTS = JSON.parse(e.postData.contents).events;
  for (const event of EVENTS){
    execute(event);
  }
}

// イベントを実行する
function execute(event){
  const EVENT_TYPE = event.type;          // イベントのタイプ
  const REPLY_TOKEN = event.replyToken;   // 応答メッセージを送る際に使用する応答トークン
  
  if(EVENT_TYPE === "message"){           // メッセージイベントの場合
    let messages;                         // 送信するメッセージオブジェクト
    if(event.message.type === "text"){    // テキストメッセージの場合
      let text = event.message.text;      // 受け取ったテキスト
      switch(text){
        case "テスト":
          messages = [getFlexMsg("ボタン", CLICK_BTN)];
          break;
      }
    }
    sendReplyMessage(REPLY_TOKEN, messages);
  }
}

// メッセージを送信
function sendReplyMessage(replyToken, messages){
  const URL = "https://api.line.me/v2/bot/message/reply";
  const RES = UrlFetchApp.fetch(URL, {
    "headers": {
      "Content-Type": "application/json; charset=UTF-8",
      "Authorization": "Bearer " + ACCESS_TOKEN,
    },
    "method": "post",
    "payload": JSON.stringify({
      "replyToken": replyToken,
      "messages": messages 
    }),
  });
  return RES;
}
```

<details><summary>メッセージイベントのJSONコード例</summary><div>

```json:JSON
{
  "destination": "xxxxxxxxxx",
  "events": [
    {
      "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
      "type": "message",
      "mode": "active",
      "timestamp": 1462629479859,
      "source": {
        "type": "user",
        "userId": "U4af4980629..."
      },
      "message": {
        "id": "325708",
        "type": "text",
        "text": "@example Hello, world! (love)",
        "emojis": [
          {
            "index": 14,
            "length": 6,
            "productId": "5ac1bfd5040ab15980c9b435",
            "emojiId": "001"
          }
        ],
        "mention": {
          "mentionees": [
            {
              "index": 0,
              "length": 8,
              "userId": "U850014438e..."
            }
          ]
        }
      }
    }
  ]
}
```
</div></details>



### 5. デプロイ
「デプロイ → 新しいデプロイ」を選択
![スクリーンショット (243).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/28e94615-fa6f-23ac-29fc-c522181cd038.png)

種類は「ウェブアプリ」を選択
![スクリーンショット (244).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/1e4ba5dc-b83c-6c63-faab-547a78a86be4.png)

アクセスできるユーザーを「全員」にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/e8a6123f-a564-0e55-6f1c-ba2357ca3bd4.png)

URLをコピーしておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/6319bc7f-b5dd-b431-8d40-fe074d97f631.png)

:::note warn
コードを修正するたびに「デプロイ → デプロイの管理 → 編集（鉛筆アイコン）」でバージョンを「新バージョン」にし、デプロイする必要がある。
:::

### 6. Webhook URL の設定
[LINE Developers Console](https://developers.line.biz/console/)の「Messaging API」タブを開く。コピーした URL を Webhook URL に設定し **「Use webhook」をON** にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/1533e026-e8a8-06d5-28fb-b2ad528470b1.png)


## 参考
https://developers.line.biz/ja/reference/messaging-api/#flex-message

https://developers.line.biz/ja/docs/messaging-api/flex-message-layout/

https://developers.line.biz/ja/docs/messaging-api/flex-message-elements/#component

https://auto-worker.com/blog/?p=5141#toc_id_4

https://qiita.com/nakaaza/items/5558880c58cd1efcf8e5