LINEのMessagingAPI使って受信したメッセージをS3に保存する

# はじめに
LINE@で提供されているMessageingAPIを使ってLINEbotを作り、発話内容をDBに入れておきたいと思ったので、送られてきたメッセージをAPIGatewayで受けてS3に突っ込んでみました。（そこから先のDBへのインサートは割愛）

# 準備
- AWSにアカウントが存在する
- LINE@のMessagingAPIを有効にしたアカウントが存在する
 - LINE@でMessagingAPIを有効にすると下記のような制約があるので注意
 ![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3134353031332f65306337393037382d626666302d646538302d333133392d6361626131346263663063612e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/200812/1e98dc2b-2f93-9d68-6ef6-c6b66c32b358.png)

# S3でメッセージを入れておくバケットを作成
![スクリーンショット 2017-11-11 12.57.59.png](https://qiita-image-store.s3.amazonaws.com/0/200812/837cc057-e50e-6277-11d2-ac879da436bf.png)
わかりやすいバケット名を入れて作成。
必要に応じて各種設定は変更すればOKだけど基本的にデフォルトでいいと思います。

# 受け取ったメッセージをS3に保存するためのlambda関数を作る
![スクリーンショット 2017-11-11 13.03.02.png](https://qiita-image-store.s3.amazonaws.com/0/200812/70a5488d-530d-e552-8d14-d1832809ed9b.png)
ロールはlambdaとS3へのアクセスができるものを新規で作成するか既存の中から選択して付与します。
今回はNode.js 6.10で作りました。

```php
'use strict';
var AWS = require('aws-sdk');
AWS.config.region = {S3のバケットのregion};
var bucketName = {S３のバケット名};

var s3 = new AWS.S3({apiVersion: '2006-03-01'});

exports.handler = function(event, context, callback) {

  if (event.headers) {

    // line からのリクエストか判定
    const crypto = require('crypto');
    const channelSecret = {LINEの管理画面上から取得するチャンネルシークレット};
    const body = event.body;
    const signature = crypto.createHmac('SHA256', channelSecret).update(body).digest('base64');
    
    if (signature == event.headers['X-Line-Signature']) {
      var date = new Date();
      var fileName = date.getTime() + '-' + signature.replace( /\//g , "" ) + '.txt';
      var params = {
        Bucket: bucketName,
        Key: fileName,
        Body: event.body
      };

      // 内容をS3に保存
      s3.upload(params, function(err, data) {
        if (err) {
          console.log("Error uploading data: ", err);
        } else {
          console.log("Successfully uploaded data to " + bucketName + "/" + fileName);
        }
    
        callback(null, response_success);  // SUCCESS with message
        context.done(null, 'Finished UploadObjectOnS3');

      });
    }
  }
};

const response_success = {
  'isBase64Encoded': false,
  'statusCode': 200,
  'headers': {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: 'ok'
  }),
};
```
# エンドポイントとなるAPIGatewayを作成
![スクリーンショット 2017-11-11 13.14.11.png](https://qiita-image-store.s3.amazonaws.com/0/200812/e59e122a-64e9-f861-cd2c-2cb378846143.png)
アクション→メソッドの作成でPOSTメソッドを作成します。
※私はここをGETで作ってしまっていてLINEの管理画面からWebhookAPIの登録をし、疎通テストを行うとテストが通らずハマりました…

![スクリーンショット 2017-11-11 13.17.37.png](https://qiita-image-store.s3.amazonaws.com/0/200812/ed48289a-5d64-fe39-d14d-2cf219f8d6fc.png)

そしてメソッドのセットアップを行います。
Lamdaリージョンと関数名は先ほど作ったものを入れます。
セットアップが完了したら、アクションからこのAPIのデプロイを行います。

![スクリーンショット 2017-11-11 13.21.42.png](https://qiita-image-store.s3.amazonaws.com/0/200812/f045995b-d780-7223-9c32-2ce0efc89323.png)

デプロイができるとURLが発行されるのでそのURLをLINE@の管理画面からWebhookURLとして登録します。

# 動かしてみた
LINE上で話しかけると

![スクリーンショット 2017-11-11 13.39.48.png](https://qiita-image-store.s3.amazonaws.com/0/200812/ca5b60d5-cc69-4c85-b12b-0a359f776dac.png)

入った！