この記事のゴール
LINE の友達追加やメッセージ受信など LINE Messaging API でのイベントを Supabase Edge Functions で受け取るための Webhook を受け取るまでをゴールとします。
前提と注意事項
この記事では以下を前提としています。
- LINE Developers アカウントを作成済みであること。
- Supabase アカウントを作成済みで Supabase CLI を使える環境であること。
Supabase Edge Functions を作成する
LINE Messaging API のイベントを受け取るための Supabase の Edge Function を Supabase CLI を使って作成します。
ここでは、linebot
という名前の Edge Function を作成します。
$ supabase functions new linebot
実行結果
$ supabase functions new linebot
Created new Function at supabase/functions/linebot
supabase/functions/linebot
を以下のようにします。
console.log('Hello from LINE bot Functions!');
// 署名検証用のチャネルシークレット
const LINE_MESSAGING_API_CHANNEL_SECRET = Deno.env.get(
'LINE_MESSAGING_API_CHANNEL_SECRET',
);
// LINE Messaging APIのチャネルトークン
// メッセージを受信して返信する場合などに使用する
const LINE_MESSAGING_API_CHANNEL_TOKEN = Deno.env.get(
'LINE_MESSAGING_API_CHANNEL_TOKEN',
);
// HMAC-SHA256の署名を作成する関数
async function createHMAC(secret: string, message: string): Promise<string> {
const encoder = new TextEncoder();
const keyData = encoder.encode(secret);
const msgUint8 = encoder.encode(message);
const key = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign'],
);
const signature = await crypto.subtle.sign('HMAC', key, msgUint8);
return btoa(String.fromCharCode(...new Uint8Array(signature)));
}
Deno.serve(async (req) => {
// リクエストヘッダーに含まれる署名を取得
const _headerSignature = req.headers.get('x-line-signature');
const _body = await req.text();
const _data = JSON.parse(_body);
// リクエストボディの署名を作成
const _bodySignature = await createHMAC(
LINE_MESSAGING_API_CHANNEL_SECRET,
_body,
);
// 署名が一致するかを確認してリクエスト元がLINEであるかを検証する
// 署名失敗時は401エラーを返す
if (_headerSignature !== _bodySignature) {
console.log('Unauthorized');
return new Response('Unauthorized', { status: 401 });
}
// LINEからのイベントは複数含まれる場合があるため、
// それぞれのイベントに対して処理を行う
for (const event of _data.events) {
// メッセージイベント
if (event.type == 'message') {
console.log('Message event');
// テキストメッセージ
if (event.message.type == 'text') {
console.log('Text Message event');
} else {
console.log('Not Text Message event');
}
// 友だち追加イベント
} else if (event.type === 'follow') {
console.log('Follow event');
// 友だちブロックイベント
} else if (event.type === 'unfollow') {
console.log('Unfollow event');
// その他のイベント
// https://developers.line.biz/ja/reference/messaging-api/#webhook-event-objects
} else {
console.log('event here');
console.log(event.type);
}
}
return new Response('OK');
});
上記は、リクエスト元が本当に LINE からであるかの検証を行い、検証成功時にはイベント毎にconsole.log
を実行するだけのものです。
実際には、各イベントに応じてメッセージに返信したり、Supabase のデータベースにデータを書き込んだりします。
リクエスト元の検証方法については、以下の LINE Messaging API の公式リファレンスにある通り、HMAC-SHA256 を使った検証を行っています。
署名を検証する
リクエストがLINEプラットフォームから送られたことを確認するために、ボットサーバーでリクエストヘッダーのx-line-signatureに含まれる署名を検証します。
developers.line.biz
上記の Edge Functions では、createHMAC
という関数を作ってそれを使って署名を生成しています。Deno での署名生成については別途以下にまとめましたので必要な方は見てみてください。
🦖 DenoでHMAC-SHA256を使ってリクエストの署名を検証する
DenoでWeb APIなどリクエスト元の検証のためにHMAC-SHA256を使ってリクエストの署名を検証する方法を解説します。
ritaiz.com
なお、LINE Messaging API で受け取るイベントの仕様については以下の公式ドキュメントに記載されています。
チャネルシークレットを環境変数に設定する
前述したようにリクエスト元の検証のために、HMAC-SHA256 を使った検証を行っています。
この検証に使用するシークレットは、LINE Developers の Messaging API のチャネル基本設定
タブの中にあります。
チャネル基本設定
タブページの下の方にスクロールすると以下のように
チャネルシークレット
という項目があります。
この値をコピーして、以下を実行することで Supabase Edge Functions 内で使用できるシークレットとして設定します。
$ supabase secrets set LINE_MESSAGING_API_CHANNEL_SECRET=1928019j8k192aa19d60cea0ea9d6199at
実行結果
$ supabase secrets set LINE_MESSAGING_API_CHANNEL_SECRET=1928019j8k192aa19d60cea0ea9d6199at
Finished supabase secrets set.
デプロイする
以下を実行してデプロイします。
$ supabase functions deploy linebot --no-verify-jwt
Version 1.30.3 is already installed
Bundling linebot
Deploying linebot (script size: 101kB)
Deployed Function linebot on project iqjduehnshcuentoie
You can inspect your deployment in the Dashboard: https://supabase.com/dashboard/project/iqjduehnshcuentoie/functions/linebot/details
Webhook を登録、検証する
LINE Developers で Webhook に、デプロイした Supabase Edge Functions の URL を登録し、検証します。
まず、以下のようにMessaging API設定
の中にあるWebhook設定
の編集
ボタンをクリックします。
編集
ボタンをクリックすると以下のように Webhook URL の入力フォームが表示されるので、ここに前述した Supabase Edge Functions の URL を入力し、更新
ボタンをクリックします。
以下のように Webhook URL が設定されます。ここで検証
ボタンをクリックします。
以下のように成功
というダイアログが表示されれば正常に Webhook がデプロイされてかつ LINE 側からもアクセスできる状態です。
もし、検証
をクリックして以下のような内容が表示される場合は、エラーが発生しているため、Supabase Edge Functions のログを確認してみてください。
なお、上記の画像は500 Internal Server Error
ですが、これが401 Unauthorized
の場合は署名の検証に失敗しているか、検証のための処理に問題がある可能性が高いです。
動作確認する
あとは適当な LINE アカウントから友達追加を行って動作確認を行います。友達追加するには、通常の LINE の友だち追加と同じように、以下のようにMessaging API設定
の中にあるQRコード
を LINE アプリで読み込んで友だち追加すれば OK です。
友だち追加やメッセージを送信した後、以下のようにSupabase Edge Functions
ページにある LINE Messaging API 用に作成した Edge Function (画像内のlinebot
)をクリックします。
以下のようにLogs
タブにイベントのログが出力されるていることを確認できるはずです。
まとめ
LINE Messaging API 用の Webhook を Supabase Edge Functions で実装しました。この記事では各イベントに応じた処理はしていませんが、ユーザーからのメッセージ内容やイベントに応じて Supabase と連携していろいろなことができます。