はじめに
業務で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」をクリックしてください。
それぞれ必要な項目を入力します。任意項目については入力は不要です。
一通り入力できたら「作成」を押下します。
権利利用と情報提供について同意を求められるので同意しておきます。
(いずれも規約を最後までスクロールしないと「同意する」が活性化しません。)
以上でチャネルの作成は完了です。
後ほど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」となっています。
ビルドが終わると、「Live」に変わります。これでWebサービスのデプロイが完了です。
左上にある「https://~」のリンクを押下してください。
このようにして、ほんの数クリックで簡易な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-Type
はapplication/json
で固定です。
Authorization
はBear
にMessagingAPIを呼び出すためのトークンを設定します。
dataString
MessagingAPIの応答メッセージに必要なリクエストボディを設定しています。
replyToken
はWebhookイベントオブジェクトに含まれています。
messages
はユーザーに送信されるメッセージです。オブジェクトで受け渡します。
今回はテキストタイプのメッセージオブジェクトを設定しています。
webhookOptions
httpsモジュールのrequest関数に必要な情報をオブジェクトとして設定しています。
hostname
はMessagingAPIのエンドポイントのドメイン名であるapi.line.me
を設定しています。
path
は応答メッセージのAPIのエンドポイントである/v2/bot/message/reply
を設定しています。
method
はPOST
です。
headers
、body
にはそれぞれ先ほど設定したリクエストヘッダ情報である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」タブをクリックします。
RenderでデプロイしたサービスのURLの末尾に「/webhook」付け加えたものを入力し、「更新」を押下します。
※末尾に「/webhook」がないと正しく動きません
うまくいかない場合の対処を表示
以下のようにタイムアウトが発生している場合、サーバーがスリープ状態になっている可能性があります。
少し待ってからやり直すか、Renderのダッシュボードから、サービスを再起動してください。
※Renderの無料枠では、一定時間Webサービスが使われない状態にあると、自動的にスリープになります。
Webサービスへのリクエストを受け取ると、起動状態になります。
Renderのダッシュボードから再起動する方法はこちらです。
ダッシュボード右側の「Manual Deploy」を押下し、「Restart service」を選択します。
また、以下のように「200以外のHTTPステータスコードが返されました。」となっている場合は、今までの何らかの設定を誤っている可能性があります。
設定しているURLや、実装の内容を確認してください。
LINE公式アカウント機能の設定
応答メッセージ、あいさつメッセージを無効にします。
編集をクリックして、編集画面へ遷移します。
チャネルアクセストークン発行
チャネルアクセストークンはMessagingAPIの機能を使うために必要です。
「発行」を押下します。
発行されたトークンは外部へ公開しないようにしてください。
こちらをコピーしておきます。
チャネルアクセストークンの設定
Renderのダッシュボードに戻ります。
左側のペインから「Environment」を選択します。
後で設定すると言っていた環境変数を設定します。
「Key」にはソースコードで取得対象にした変数名(LINE_ACCESS_TOKEN)
「Value」には先ほどコピーしたチャネルアクセストークンを設定します。
設定が完了したら「Save Changes」を押下します。
友だち追加
ここまできたらほぼ全ての設定は完了です。
LINE Develpersに戻り、Messaging API設定の上部にあるQRコードを読み込んで、今回作成したボットをLINEの友達に追加します。
まとめ
かなり長くなってしまいましたが、LINEのアカウント周りの設定から、Renderによるサービスの作成、処理の実装と一気に進めました。
一度作ってしまえば、そんなに難しくなくボットを作れることがわかりました。
今回は自動応答の処理でしたが、公式アカウント側からプッシュメッセージを送ったり、ユーザ情報の取得をしたりすることもできるようです。
いろいろなAPIの挙動を覚え、実務に生かせるようにしたいです。