kakts-log

programming について調べたことを整理していきます

aws lambdaとapi gatewayで linebotを作成する

概要

AWSAPI Gateway、lambdaを利用し、ユーザからのメッセージが来たときにlambda関数を呼び出し、ユーザへレスポンスを返すline botを作ります。

行った作業手順を一通りまとめます。

Linebotアカウントの作成

まず、line messaging api用のbotアカウントの作成を行うため、line business centerへログインします。
business.line.me 「アカウントリスト」タブを選択し、「アカウント作成」→「Messaging APIを始める」で、アカウントを作成する事ができます。

作成後、line@MANAGERページにて作成したアカウントの設定を行っていきます。

アカウント設定開始するとBot設定画面に遷移します。 Bot設定項目の中で「Webhook送信」項目を「利用する」に設定することで、messaging apiを利用できます。
f:id:kakts:20170622224241p:plain

またline business centerへもどり、「アカウントリスト」→作成したアカウントの「LINE Developers」から、botアカウント用のapiアクセストークンを確認することができます。

f:id:kakts:20170622224604p:plain 「ISSUE」ボタンを押すことでアクセストークンを確認できます。 このアクセストークンは後ほど使います。

API Gateway で新しいAPIの作成

awsコンソールから「サービス」→「Amazon API Gateway」を選択し、新しいAPIの作成します。
「新しい API」にチェックを入れ、適当なAPI名を入力します。
f:id:kakts:20170622234300p:plain

いったんおいておき、lambda関数の作成を行います。

aws lambdaの記述

早速aws lambdaを使ってユーザからのメッセージを受け取り、messaging apiを使ってレスポンスするための関数を書いていきます。

「Lambda関数の作成」ボタンから 「設計図の選択」画面に遷移し、そこで、lambdaで使うランタイムと、関数のサンプルを選ぶことができます。
ランタイムはNode.js と pythonから選ぶことができ、本稿では Node.js 6.10を選択します。
関数のサンプルは、「Blank Function」を選択します。 f:id:kakts:20170622231032p:plain

続いて、「トリガーの設定」画面に遷移し、lambdaを実行するためのトリガーを選択します。
本稿では、lambda関数へのエンドポイントとして、 AWS API Gatewayを利用しますので、「API Gateway」を選択します。
作成時に下記の3つの入力項目を設定します。 - API名 任意の名前 - デプロイされるステージ prod - セキュリティ AWS IAM

line botに対してユーザから送られるメッセージは、下記のreply APIの仕様に基づいて送信されます。 ユーザから受け取ったリクエストから、replyToken, textを取得し、reply api を利用することでユーザに対して返信することができます。
LINE API Reference

ここでは、ユーザから来たメッセージをシンプルにそのまま返すようにします。

lambda関数は、awsのlambda関数の設定画面で入力できるため、今回はそのまま入力していきます

const https = require('https');

exports.handler = (event, context, callback) => {
    // メッセージデータ取得
    const messageData = event.events && event.events[0];

    
    const replyToken = messageData.replyToken;
    const message = messageData.message;
    const text = message.text;
    
    const data = JSON.stringify({
       replyToken: replyToken,
       messages: [{type: "text", text: text}]
    });
    
    // line messaggin apiのアクセストークンを環境変数ACCESS_TOKENに設定する 
    const Authorization = 'Bearer ' + process.env.ACCESS_TOKEN;
    opts = {
        hostname: 'api.line.me',
        path: '/v2/bot/message/reply',
        headers: {
            "Content-type": "application/json; charset=UTF-8",
            "Authorization": Authorization
        },
        method: 'POST',
    };

    const 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();
};

lambda関数が毎回実行されるたびに、デフォルトでexports.handler メソッドが呼ばれます。 引数は3つあり、 event.events内に、lineユーザからのメッセージのリクエストデータが格納されます。

line reply APIのリクエスト時に、先程「LINE Developers」管理画面で取得した アクセストークンが必要で、 リクエストヘッダーの Authorization に 追加します。

コードの中に直接アクセストークンを埋め込むと、管理上面倒なため、lambdaの環境変数を利用します。
f:id:kakts:20170622232955p:plain

上記のように、キーと値を入力することで、lambda関数内部で process.env.ACCESS_TOKENとして呼び出して使うことができます。

他にもいろいろ設定する項目があり、代表的なものをあげますが それ以外の項目はデフォルトのままでよいかと思います。

関数の設定
名前:  任意

Lambda 関数ハンドラおよびロール
・ハンドラ   index.handler
・ ロール     「テンプレートから新しいロールを選択」
・ロール名   任意のロール名

詳細設定
メモリ:128MB

api gatewayとlambda関数を紐付ける

ここで、作成した API GatewayによるAPIと lambda関数を紐付けます。
lambdaの設定画面より「トリガー」タブを選択→「トリガーを追加」を選択 → 「API Gatway」を選択し、先程作成したAPIAPI名、デプロイされるステージ、セキュリティ項目を入力します。

f:id:kakts:20170622234715p:plain

「メソッドの作成」→「POST」を選択しチェックボタンを押し、下記のように作成したlambda関数の設定を入れます。
f:id:kakts:20170622235021p:plain

これで、API Gatewayによって作った apiに対して POSTでリクエストを送ると lambda関数を呼び出すといって一連の設定ができました。

line managerで作成したapiの登録を行う

最後に、 LINE Developer管理画面で、Webhook URLを設定していきます。
先程のlambdaの設定画面の「トリガー」タブに、連携したAPIのURLが表示されています。

これを LINE Developer管理画面 に登録します。
登録後、Webhook URL 項目に「verify」ボタンができるので、これを押すとapiとの疎通確認を行います。
これでsuccessが出たら設定完了です。

verify時に下記の文言がでてエラーが出た場合は、再度api gateway と lambdaの設定を見直す必要があります

A http status of the response was '502 Bad Gateway'.

verify時にlambdaのcloud watchログを見ると reply apiで下記のエラーが出ていますが、api gatewayと lambdaの設定自体が正しければ successになっているので、特に問題は無いかと思います。

{"message":"Invalid reply token"}

linebotにメッセージを送る

これで一通りの設定が完了したので、実際にbotに対してメッセージを送ってみます。
成功すると以下の通りにメッセージを返してくれるようになります。 f:id:kakts:20170623001606j:plain

うまくいかない場合は lambdaのcloudwatchのログを見て、lambda関数内でエラーが出ているか確認することと、API Gatewayの設定が正しいか再度確認することが大事です。