API Gateway + Lambda + nodejsでLINE BOT (Messaging API版）

# Messaging APIへの移行
BOT API Trialが終了し、Messaging APIに移行する、ということで
APIGateway + Lambda + nodeでMessaging API使ったオウム返しLINE BOTを作ってみました。

# LINE BOT用アカウントの作成

* [LINE BUSINESS CENTER](https://business.line.me/ja/) へアクセス
* タブから「サービス」-> 「Messaging API」を選択
* 「Messaging APIを始める」を選択
  * 「会社/事業者未選択」が出たら「会社/事業者を選択」を選択
  * 既に作成済みであれば選択、なければ「会社/事業者を追加する」を選択
  * 項目を適当に埋めて会社/事業者を登録する。基本個人でOK
* アカウント名・アイコン・業種を設定
  * ここでのアカウント・アイコンがLINE上で表示される
  * 業種は何に使われるのか不明。とりあえず個人の何かにしておく
* LINE@ MANAGER -> LINE Developersの順にとりあえず有効化していく

## LINE@ MANAGERの設定
* もしかしたらミスっただけでこれの設定はしなくてもいいのかもしれないが、やらないと動かなかったのでメモ
* LINE@の「アカウント設定」->「Bot設定」を開く
* Webhook送信を「利用する」に変更
* 自動応答メッセージを「利用しない」に変更
* これをやらないとBotに話しかけても「このアカウントは個別での返信ができないのです」的な自動応答メッセージが来る

# API Gatewayの作成
* AWSマネジメントコンソールを開く
* サービスから「API Gateway」を選択
* 「APIの作成」を選択
* ラジオボタンは「新しいAPI」を選択し、API名と説明を適当に入力して「APIの作成」を選択

# AWS Lambdaの設定
* AWSマネジメントコンソールを開く
* サービスから「Lambda」を選択
* 「Create a Lambda function」を選択
* 左側のメニューから「Configure function」を選択
* Configure functionが開くので、botの設定をここに入れていく
  * Name：メソッド名
  * Description：任意
  * Runtime：今回はnodeで書くので「Node.js 4.3」を選択
  * Code entry type：Edit code inline
  * コードは後述
  * Handler：exports.handler
  * Role：Create a custom role -> ロール作成画面が開くのでロール名（lambda_line_botなど）を入れて「許可」を選択  
    「Choose an existing role」に切り替えることで、いま作成したロールが選択できるようになる
  * Memory：128MB（オウム返しなら最少でOK）
  * Timeout：任意の時間
  * VPC：No VPC
  * ↓のコードを入れたら「Next」を選択（コードはあとからでもOK）
* 確認画面が表示されるので、問題なければ「Create function」を選択

## オウム返しのコード

BOT Trialと比べて変わったところ

* LINEからリクエストを受けたときのJSONフォーマットが変わった
  * 詳しくは[こちら](https://devdocs.line.me/ja/)
* 「eventType」を指定する必要がなくなった
* 「to」や「toChannel」ではなくreplyTokenで送信先指定するようになった
  * ただしTokenが有効なのは30秒以内のみなので、返信は早く送るようにすること
* メッセージのtypeを指定する必要が増えた
* ChannelIDやChannelSecretではなく、トークン指定になった

``` JavaScript
var https = require('https');

exports.handler = (event, context, callback) => {
    console.log(event.events);
    data = event.events[0];
    var replyToken = data.replyToken;
    var message = data.message;
    var text = message.text;

    var data = JSON.stringify({
       replyToken: replyToken,
       messages: [{type: "text", text: text}]
    });
    opts = {
        hostname: 'api.line.me',
        path: '/v2/bot/message/reply',
        headers: {
            "Content-type": "application/json; charset=UTF-8",
            "Authorization": "Bearer {ENTER_ACCESS_TOKEN}" // LINE Developersの「Channel Access Token」を使用
        },
        method: 'POST',
    };

    var req = https.request(opts, function(res) {
        res.on('data', function(res) {
            console.log(res.toString());
        }).on('error', function(e) {
            console.log('ERROR: ' + e.stack);
        });
    });
    req.write(data);
    req.end();
};
```

# API GatewayとLambdaの紐付け

* Lambdaのfunction管理画面にてタブから「Triggers」を選択
* 「Add Trigger」を選択
  * Lambdaアイコンの左側に点線の四角があるのでクリックし、API Gatewayを選択
  * API name：先程API Gatewayで作成したものを選択
  * Deployment stage：prod
  * Security：Open
  * すべて設定したら「Submit」を選択
* サービスからAPI Gatewayを選択
* 先ほど作成したAPIを選択
  * リソース内にLambdaで作成したメソッドが存在しているはずなので、こちらを選択
  * 「アクション▼」から「メソッドの作成」を選択
  * プルダウンが表示されるので「POST」を選択し、確定ボタンを選択
  * POST -セットアップ画面が開くのでLambdaリージョンをap-northeast-1に設定  
    ※リージョンが東京ならこれのはず。念のためLambdaのTriggersにて追加したAPI GatewayのURLを確認すること
  * Lambda関数入力ボックスが出てくるので、Lambdaで作成したFunctionの名前を指定する
  * 「保存」ボタンを選択

# APIエンドポイントとLINE BOTの紐付け

* Lambdaのfunction管理画面にてタブから「Triggers」を選択
* API Gatewayの欄にURLが記載されているのでコピー
* LINE Developers管理画面を開く
* 「EDIT」を選択してWebhook URLに先程コピーしたURLを設定
* 「Save」で変更を確定する
* Webhook URLのところにある「VERIFY」を選択。Successと表示されればOK。エラーになる場合は設定を見直すこと。

# やってみよう

* LINE Developers管理画面のQRコードから自身のLINEにて友だち追加を行う
* 適当にメッセージを飛ばす
* 返事が来るのを待つ
* AWSのCloud Watch -> ログと選択していくことで、Lambdaへのアクセスやconsole.logで吐き出した内容のログが確認できる  
* エラーになってる場合もあるので要注意


※あとで画像を貼るかも