LoginSignup
3
2

Node.jsとMessagingAPIでLINEの応答ボットを作る

Posted at

はじめに

業務でLINEのMessagingAPIを使ったサービスの開発をすることになりました。
練習のためLINEの応答ボットを作ってみたので、その手順を説明します。
なお、本記事は以下2点が前提となっています。

  • JavaScript、Node.jsの知識があること
  • GitHubのアカウントを持っていること

LINE関連の設定

LINE Business IDの作成

Messaging APIの機能を使用するためにはLINE Business IDが必要です。
以下のURLにアクセスします。
https://manager.line.biz/

「アカウントを作成」をクリックします。

「メールアドレスで登録」を押下します。

使用するメールアドレスを入力し、「登録用のリンクを送信」を押下してください。

入力したメールアドレス宛に、以下のようなメールが届きます。
「登録画面に進む」を押下します。

名前とパスワードを入力し、「登録」を押下します。

登録内容を確認し、問題なければ「登録」を押下します。

これでBusiness IDの登録は完了です。
「サービスに移動」を押下します。

開発者アカウントの登録

LINE Business IDを登録した後、初回ログイン時のみ開発者アカウントの登録を求められます。
開発者名、メールアドレスを入力し、同意のチェックを入れて「アカウントを作成」を押下してください。

開発者アカウントが登録できました。

プロバイダーの作成

画面下部の「新規プロバイダー作成」を押下します。

任意のプロバイダー名を入力し、「作成」を押下します。

チャネルの作成

チャネルはLINEが提供する機能をプロバイダーが使うための窓口になります。
また、チャネルを作成すると、チャネルと同名の公式アカウントも作成されます。
「Messaging API」をクリックしてください。

それぞれ必要な項目を入力します。任意項目については入力は不要です。
一通り入力できたら「作成」を押下します。

内容を確認し、問題なければ「OK」を押下します。

権利利用と情報提供について同意を求められるので同意しておきます。
(いずれも規約を最後までスクロールしないと「同意する」が活性化しません。)

以上でチャネルの作成は完了です。

後ほどMessaginAPIの設定を行います。

Renderでボットをホストするサーバを作成

Renderは簡単に静的サイトやWebサービスなどをデプロイできるサービスです。
最低限のものであれば無料で利用することができるので、ちょっと試すのに適しています。
ボット作成のためにはサーバが必要なので、今回はこちらを使っていきます。

リポジトリをフォークする

Renderではサービスを簡単に作成することができるよう、様々な言語や環境に対応したテンプレートをGitHubに用意しています。
今回はNode.jsのフレームワークであるExpressを使用して開発をするため、Express用のリポジトリを使用します。

以下のリポジトリをフォークします。
https://github.com/render-examples/express-hello-world

アカウントを作成する

以下のURLからアカウントを作ります。
https://dashboard.render.com/register

メールアドレスのほか、GitHub、GitLab、Googleのアカウントと連携できます。
私はGoogleのアカウントと連携させました。

アカウントの作成が完了すると、以下のようなダッシュボードの画面に遷移します。

新しくWebサービスを作りたいので「New Web Service」を押下します。

初期状態(Build and deploy from a Git repository)のままで「Next」を押下します。

GitHubの「Connect account」を押下します。

GitHubアカウントの連携を済ませた後、Renderをどのリポジトリにインストールするかを聞かれるので、「Only select repositories」を選択し、冒頭でフォークしたリポジトリを選びます。
画面下部の「Install」を押下します。

Renderのサイトに戻ってくると、先ほど選択したリポジトリが表示されているので、「Connect」を押下します。

Webサービスを作成するための設定を入力します。
変更する箇所は2箇所、あとは初期状態のままでよいです。
・Name
任意の名前。ここで指定した名前が、WebサービスにアクセスするためのURLに使われる。

・Instance Type
Freeを選択。無料で使える。クレジットカード情報の入力も不要

入力が完了したら、画面下部の「Create Web Service」を押下

Webサービスのデプロイが始まります。しばらくは「Building」となっています。
image.png

ビルドが終わると、「Live」に変わります。これでWebサービスのデプロイが完了です。
左上にある「https://~」のリンクを押下してください。

「Hello from Render!」が表示されます。
image.png

このようにして、ほんの数クリックで簡易なWebサービスのデプロイをできるのがRenderのいいところです。

応答ボットの処理を実装

アカウントの作成、サーバの作成が完了したので、実際に処理を実装していきます。

JavaScriptで処理を書く

処理を記述するため、まずは自分のGitHubアカウントにフォークしてきたリポジトリを、ローカルで編集できるよう、任意のフォルダにクローンしてください。

以下のようにいくつかファイルがありますが、このうちapp.jsを編集していきます。

既存の記載はすべて消して、ボットの処理を実装します。

モジュールのインポート

const https = require("https");
const express = require("express");

httpsモジュール、expressモジュールを使用します。

環境変数の取得

// ポート番号
const PORT = process.env.PORT || 3000;
// Messaging APIを呼び出すためのトークン
const TOKEN = process.env.LINE_ACCESS_TOKEN;

ポート番号とトークンを取得します。
ポート番号は未設定の場合には3000が割り当てられるようにしています。
トークンについてはRender側で後ほど環境変数を設定します。

Expressアプリケーションオブジェクトの生成

const app = express();

ミドルウェアやルーティングの設定を行うために使用します。

ミドルウェアの設定

app.use(express.json());
app.use(express.urlencoded({ extended: true, }));

use関数を使い、リクエストとレスポンスの間で行われる処理を定義します。
今回はJSONデータとフォームデータを扱えるよう設定しています。
(フォームデータは今回使いませんが、この2つを設定するのが一般的なようです。)

ルーティングの設定-ドメインのルート

app.get("/", (_, res) => {
  res.sendStatus(200);
});

URLの検証の失敗などを防ぐため、ドメインのルート(/)へのHTTP GETリクエストに対して、ステータス200を返すようにします。

ルーティングの設定-MessaginAPI

app.post("/webhook", (req, _) => {
  res.send("HTTP POST request sent to the webhook URL!");
  if (req.body.events[0].type === "message") {
    const headers = {
      "Content-Type": "application/json",
      Authorization: "Bearer " + TOKEN,
    };
    const dataString = JSON.stringify({
      replyToken: req.body.events[0].replyToken,
      messages: [
        {
          type: "text",
          text: "Hello, user",
        },
        {
          type: "text",
          text: "May I help you?"
        },
      ],
    });
    const webhookOptions = {
      hostname: "api.line.me",
      path: "/v2/bot/message/reply",
      method: "POST",
      headers: headers,
      body: dataString,
    }
    const request = https.request(webhookOptions, res => {
      res.on("data", d => {
        process.stdout.write(d);
      });
    });
    request.on("error", err => {
      console.error(err);
    });

    request.write(dataString);
    request.end();
  }
});

Messaging APIでは/webhookに対してHTTP POSTリクエストが送られるため、それに対しての処理を実装します。

res.send(...

httpレスポンスを返す処理です。
今回は「"HTTP POST request sent to the webhook URL!"」という文字列をレスポンスボディに設定しています。

if (req.body.events...

ユーザがボットにメッセージを送ったときに処理をするよう、分岐を入れています。
以降の処理はすべてif文のブロック内に記述します。

headers

MessagingAPIの応答メッセージに必要はリクエストヘッダを設定しています。
Content-Typeapplication/jsonで固定です。
AuthorizationBear にMessagingAPIを呼び出すためのトークンを設定します。

dataString

MessagingAPIの応答メッセージに必要なリクエストボディを設定しています。
replyTokenはWebhookイベントオブジェクトに含まれています。
messagesはユーザーに送信されるメッセージです。オブジェクトで受け渡します。
今回はテキストタイプのメッセージオブジェクトを設定しています。

webhookOptions

httpsモジュールのrequest関数に必要な情報をオブジェクトとして設定しています。
hostnameはMessagingAPIのエンドポイントのドメイン名であるapi.line.meを設定しています。
pathは応答メッセージのAPIのエンドポイントである/v2/bot/message/replyを設定しています。
methodPOSTです。
headersbodyにはそれぞれ先ほど設定したリクエストヘッダ情報であるheaders、リクエストボディ情報であるdataStringを設定しています。

const request = https.request...からrequest.end()まで

httpsリクエストを生成し、エラー時の挙動を設定しています。
また、httopsリクエストの生成だけではリクエストボディが確定していないので、write関数に再度リクエストボディを設定しています。
最後のend関数でリクエストを送信して/webhookに対する処理は完了です。

リスナーの設定

app.listen(PORT, () => {
  console.log(`Example app listening at http://localhost:${PORT}`);
});

最後に冒頭で取得したポート番号をリッスンします。
これですべての実装が完了しました。

ソースコード全文を表示
// モジュールのインポート
const https = require("https");
const express = require("express");

// 環境変数の取得
// ポート番号
const PORT = process.env.PORT || 3000;
// Messaging APIを呼び出すためのトークン
const TOKEN = process.env.LINE_ACCESS_TOKEN;

// Expressアプリケーションオブジェクトの生成
const app = express();

// ミドルウェアの設定
app.use(express.json());
app.use(express.urlencoded({ extended: true, }));

// ルーティングの設定-ドメインのルート
app.get("/", (_, res) => {
  res.sendStatus(200);
});

//ルーティングの設定-MessaginAPI
app.post("/webhook", (req, _) => {
  if (req.body.events[0].type === "message") {
    res.send("HTTP POST request sent to the webhook URL!");
    const headers = {
      "Content-Type": "application/json",
      Authorization: "Bearer " + TOKEN,
    };
    const dataString = JSON.stringify({
      replyToken: req.body.events[0].replyToken,
      messages: [
        {
          type: "text",
          text: "Hello, user",
        },
        {
          type: "text",
          text: "May I help you?"
        },
      ],
    });
    const webhookOptions = {
      hostname: "api.line.me",
      path: "/v2/bot/message/reply",
      method: "POST",
      headers: headers,
      body: dataString,
    }
    const request = https.request(webhookOptions, res => {
      res.on("data", d => {
        process.stdout.write(d);
      });
    });
    request.on("error", err => {
      console.error(err);
    });

    request.write(dataString);
    request.end();
  }
});

// リスナーの設定
app.listen(PORT, () => {
  console.log(`Example app listening at http://localhost:${PORT}`);
});

ここまでの内容をコミット、プッシュします。
GitHubにプッシュすると、Renderにデプロイしたサービスが、自動で再度デプロイされます。

デプロイ完了後、Renderで作成したWebサービスへアクセスすると、先ほどの「Hello from Render」ではなく「ok」だけが表示されていることが確認できます。

MessagingAPI関連の設定

Webhook設定

まずは作成したチャネルに、デプロイしたサービスを紐づけます。
チャネルの画面から「Messaging API」タブをクリックします。

Webhook URLの「編集」を押下します。

RenderでデプロイしたサービスのURLの末尾に「/webhook」付け加えたものを入力し、「更新」を押下します。
※末尾に「/webhook」がないと正しく動きません

「検証」を押下します。

ここまで正しく設定できていれば、「成功」が表示されます。

うまくいかない場合の対処を表示

以下のようにタイムアウトが発生している場合、サーバーがスリープ状態になっている可能性があります。
少し待ってからやり直すか、Renderのダッシュボードから、サービスを再起動してください。
※Renderの無料枠では、一定時間Webサービスが使われない状態にあると、自動的にスリープになります。
Webサービスへのリクエストを受け取ると、起動状態になります。

Renderのダッシュボードから再起動する方法はこちらです。
ダッシュボード右側の「Manual Deploy」を押下し、「Restart service」を選択します。

また、以下のように「200以外のHTTPステータスコードが返されました。」となっている場合は、今までの何らかの設定を誤っている可能性があります。
設定しているURLや、実装の内容を確認してください。

次に「Webhookの利用」をオンにします。

LINE公式アカウント機能の設定

応答メッセージ、あいさつメッセージを無効にします。
編集をクリックして、編集画面へ遷移します。

応答メッセージ、あいさつメッセージをオフにしてください。

チャネルアクセストークン発行

チャネルアクセストークンはMessagingAPIの機能を使うために必要です。
「発行」を押下します。

発行されたトークンは外部へ公開しないようにしてください。
こちらをコピーしておきます。

チャネルアクセストークンの設定

Renderのダッシュボードに戻ります。
左側のペインから「Environment」を選択します。

後で設定すると言っていた環境変数を設定します。
「Key」にはソースコードで取得対象にした変数名(LINE_ACCESS_TOKEN)
「Value」には先ほどコピーしたチャネルアクセストークンを設定します。
設定が完了したら「Save Changes」を押下します。

友だち追加

ここまできたらほぼ全ての設定は完了です。
LINE Develpersに戻り、Messaging API設定の上部にあるQRコードを読み込んで、今回作成したボットをLINEの友達に追加します。

任意のメッセージを送ると、自動でメッセージが返ってきます。

まとめ

かなり長くなってしまいましたが、LINEのアカウント周りの設定から、Renderによるサービスの作成、処理の実装と一気に進めました。
一度作ってしまえば、そんなに難しくなくボットを作れることがわかりました。

今回は自動応答の処理でしたが、公式アカウント側からプッシュメッセージを送ったり、ユーザ情報の取得をしたりすることもできるようです。

いろいろなAPIの挙動を覚え、実務に生かせるようにしたいです。

参考にしたサイト

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2