このチュートリアルでは、初めてMessengerエクスペリエンスを構築する際に知っておくべきことがすべて網羅されています。始める前に、スタータープロジェクトにあるオプションの中から1つを選んで開始するために必要なコードを入手した後、スタートガイドに示されている手順を実行して設定してください。
完成したコードを見たいだけの場合は、どうしたらいいですか?問題ありません!GitHubで見ることができます。このクイックスタートを開始する前に、以下のいずれかを実行して、必要になるスターターコードを入手してください。スターターコードは、Messengerエクスペリエンスの基礎として使うことになる基本的なWebhookを提供します。
当社のWebhook設定ガイドでは、このクイックスタートで使うことのできる最初のWebhookをビルドする作業が、最初から最後まで説明されています。
WebhookをビルドするWebhookスターターコードをGitHubからダウンロードし、自分のサーバーにデプロイします。
コードをダウンロードするWebhookをデプロイするサーバーがない場合は、Glitch上でMetaのスターターWebhookプロジェクトをリミックスできます。そうすることで、Webhook用のHTTPSのパブリックURLが提供されます。
Glitch上で独自のWebhookを作成する手順は、次のとおりです。
/webhook
を追加したものです。
https://
初めてMessengerエクスペリエンスをビルドする前に、まずアプリの資格情報を設定します。
アプリ設定ガイドに従って、Messengerプラットフォームで使えるようにFacebookアプリを設定します(まだしていない場合)。
アプリがMessengerで一般公開されるように申請して承認されるまでは、ページトークンがページに許可するのは、アプリの管理者、開発者、テスト担当者のいずれかの役割を付与されているFacebookアカウントとのやり取りだけです。
それらの役割を他のFacebookアカウントに付与するには、アプリ設定で[役割]タブにアクセスしてください。
MessengerプラットフォームAPIに対するすべてのリクエストは、クエリ文字列のaccess_token
パラメーターにページレベルのアクセストークンを含めることにより認証されます。
Facebookアプリ設定時にしていなかった場合は、以下を実行してページアクセストークンを生成ます。
ページアクセストークンなどの機密情報は、Webhookにハードコーディングしないことにより、安全に保管してください。
そのためには、環境変数に下記のものを追加します。ここで、<PAGE_ACCESS_TOKEN>
は先ほど生成したアクセストークン、<VERIFY_TOKEN>
はWebhookを確認するために設定したランダムな文字列です。
PAGE_ACCESS_TOKEN="
Glitchを使っている場合は、提供されている.env
ファイルで環境変数を設定することにより、それが他のGlitchユーザーから見られないようにしてください。
あとは、app.js
ファイルの先頭にページアクセストークンを追加し、トークンを認証するだけです。こうすると、自分のWebhookロジックで使えるようになります。
const PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
const VERIFY_TOKEN = process.env.VERIFY_TOKEN;
このチュートリアルでは、以下のことをするシンプルなMessengerエクスペリエンスを構築します。
受信Webhookイベントから、メッセージと送信者のPage-scoped IDを解析します。
messages
とmessaging_postbacks
のWebhookイベントを処理します。
送信APIでメッセージを送信します。
テキストメッセージにテキストメッセージで返信します。
添付画像に対して、受信した画像を使った汎用テンプレートで返信します。
ポストバックペイロードに対して、条件に応じて返信します。
まず、送信APIで返信するだけでなく、サポートする受信Webhookイベントタイプを処理する3つの関数をスタブします。そのためには、app.js
ファイルに以下を付加します。
// Handles messages events
function handleMessage(sender_psid, received_message) {
}
// Handles messaging_postbacks events
function handlePostback(sender_psid, received_postback) {
}
// Sends response messages via the Send API
function callSendAPI(sender_psid, response) {
}
Messengerで返信するために最初にする必要があるのは、相手がだれかを知ることです。Messengerでは、受信Webhookイベントからメッセージ送信者のPage-scoped ID (PSID)を取得することにより、それができます。
ユーザーが開始するスレッドの相手となるFacebookページごとに一意のPage-scoped ID (PSID)がユーザーに割り当てられます。このPSIDは、メッセージ送信時にユーザーを識別するために使われます。
前述のスタータープロジェクトに示されているいずれかのオプションを実行したなら、次のような基本的な/webhook
エンドポイントができているはずです。このエンドポイントは、POST
リクエストを受け入れ、受信したWebhookイベントの本文をログ記録します。
app.post('/webhook', (req, res) => {
// Parse the request body from the POST
let body = req.body;
// Check the webhook event is from a Page subscription
if (body.object === 'page') {
// Iterate over each entry - there may be multiple if batched
body.entry.forEach(function(entry) {
// Get the webhook event. entry.messaging is an array, but
// will only ever contain one event, so we get index 0
let webhook_event = entry.messaging[0];
console.log(webhook_event);
});
// Return a '200 OK' response to all events
res.status(200).send('EVENT_RECEIVED');
} else {
// Return a '404 Not Found' if event is not from a page subscription
res.sendStatus(404);
}
});
送信者のPSIDを入手するには、以下のコードを入れてbody.entry.forEach
ブロックをアップデートし、イベントのsender.id
プロパティからPSIDを抽出します。
body.entry.forEach(function(entry) {
// Gets the body of the webhook event
let webhook_event = entry.messaging[0];
console.log(webhook_event);
// Get the sender PSID
let sender_psid = webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
});
Sender PSID: 1254938275682919
ここでは、messages
とmessaging_postback
の2つのタイプのWebhookイベントを処理できるエクスペリエンスにします。イベントタイプの名前はイベント本文に含まれませんが、特定のオブジェクトプロパティをチェックすることにより判別できます。
Messengerで発生するアクションについて通知するWebhookイベントがMessengerプラットフォームから送信されます。POST
リクエストがWebhookに実行され、イベントはJSON形式で送信されます。詳しくは、Webhookイベントをご覧ください。
そのためには、Webhookのbody.entry.forEach
ブロックを更新して、受信したイベントにmessage
またはpostback
のプロパティが含まれているかどうかをチェックする条件を含めます。また、前にスタブしたhandleMessage()
関数とhandlePostback()
関数への呼び出しを追加します。
body.entry.forEach(function(entry) {
// Gets the body of the webhook event
let webhook_event = entry.messaging[0];
console.log(webhook_event);
// Get the sender PSID
let sender_psid = webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
// Check if the event is a message or postback and
// pass the event to the appropriate handler function
if (webhook_event.message) {
handleMessage(sender_psid, webhook_event.message);
} else if (webhook_event.postback) {
handlePostback(sender_psid, webhook_event.postback);
}
});
これで、受信メッセージが適切なハンドラー関数にルーティングされるようになったので、handleMessage()
を更新して、基本的なテキストメッセージを処理し、それに返信するようにします。そのためには、コードを更新して返信のメッセージペイロードを定義し、それからそのペイロードをcallSendAPI()
に渡します。基本的なテキストメッセージで返信するには、"text"
プロパティを使ってJSONオブジェクトを定義します。
function handleMessage(sender_psid, received_message) {
let response;
// Check if the message contains text
if (received_message.text) {
// Create the payload for a basic text message
response = {
"text": `You sent the message: "${received_message.text}". Now send me an image!`
}
}
// Sends the response message
callSendAPI(sender_psid, response);
}
いよいよMessengerプラットフォームの送信APIを使って最初のメッセージを送信します!
現在、handleMessage()
でcallSendAPI()
を呼び出しています。これを更新して、リクエストの全本文を構成し、それをMessengerプラットフォームに送信する必要があります。送信APIへのリクエストには、2つのプロパティがあります。
recipient
: 意図されたメッセージ受信者を設定します。ここでは、PSIDにより受信者を識別します。message
: 送信するメッセージの詳細を設定します。ここではそれを、handleMessage()
関数から渡したメッセージオブジェクトに設定します。リクエスト本文を構成するため、callSendAPI()
のスタブを次のように更新します。
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
}
あとは、https://graph.facebook.com/v2.6/me/messages
でPOST
リクエストを送信APIに対して送信すれば、メッセージが送られます。
URLクエリ文字列のaccess_token
パラメーターにPAGE_ACCESS_TOKEN
を付加する必要があることに注意してください。
このクイックスタートでは、HTTPリクエストをMessengerプラットフォームに返すため、Node.jsリクエストモジュールを使っています。しかし任意のHTTPクライアントを使うことができます。
リクエストモジュールをインストールするには、コマンドラインからnpm install request --save
を実行し、app.js
の先頭に以下を追加してインポートします。
const request = require('request');
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
// Send the HTTP request to the Messenger Platform
request({
"uri": "https://graph.facebook.com/v2.6/me/messages",
"qs": { "access_token": process.env.PAGE_ACCESS_TOKEN },
"method": "POST",
"json": request_body
}, (err, res, body) => {
if (!err) {
console.log('message sent!')
} else {
console.error("Unable to send message:" + err);
}
});
}
返信プロンプトはメッセージ受信者に画像を送信するように促しているため、次のステップとして、添付を処理するようにコードを更新します。送信された添付ファイルはMessengerプラットフォームにより自動的に保存されて、配列attachments
の各インデックスのpayload.url
プロパティにあるURLから入手できます。それで、イベントからそのURLも抽出します。
メッセージが添付かどうかを調べるには、handleMessage()
関数の条件を更新して、received_message
にattachments
プロパティがあるかどうかをチェックし、そのURLを抽出します。現実世界のボットでは、その配列を反復処理することにより、複数の添付の存在をチェックすることになりますが、このクイックスタートでは最初の添付だけを取得することにします。
function handleMessage(sender_psid, received_message) {
let response;
// Checks if the message contains text
if (received_message.text) {
// Creates the payload for a basic text message, which
// will be added to the body of our request to the Send API
response = {
"text": `You sent the message: "${received_message.text}". Now send me an attachment!`
}
} else if (received_message.attachments) {
// Gets the URL of the message attachment
let attachment_url = received_message.attachments[0].payload.url;
}
// Sends the response message
callSendAPI(sender_psid, response);
}
次に、汎用テンプレートメッセージを使って画像に返信します。汎用テンプレートは、最も広く使われるフォーマット済みメッセージタイプであり、それにより画像、テキスト、ボタンを1つのメッセージで送信することができます。
はい!Messengerプラットフォームには、一連の便利なメッセージテンプレートが用意されています。リスト、領収書、ボタンなど、よく使われる各種のメッセージフォーマットをサポートしています。詳しくは、テンプレートをご覧ください。
メッセージテンプレートは、メッセージのattachment
プロパティで定義されます。それには、type
プロパティとpayload
プロパティが含まれています。ここでは汎用テンプレートの詳細を、payload
の以下のプロパティで設定しました。
template_type
: メッセージに使われているテンプレートのタイプを設定します。ここでは汎用テンプレートを使っているので、値は「generic」です。elements
: テンプレートのカスタムプロパティを設定します。この汎用テンプレートでは、タイトル、サブタイトル、画像、そして2つのポストバックボタンを指定します。このフォーマット済みメッセージでは、送られてきたattachment_url
をimage_url
として使用し、テンプレートで表示します。さらに、メッセージ受信者が返信できるようにするため、2つのポストバックボタンを含めます。メッセージペイロードを構成し、汎用テンプレートを送信するため、handleMessage()
を次のように更新します。
function handleMessage(sender_psid, received_message) {
let response;
// Checks if the message contains text
if (received_message.text) {
// Create the payload for a basic text message, which
// will be added to the body of our request to the Send API
response = {
"text": `You sent the message: "${received_message.text}". Now send me an attachment!`
}
} else if (received_message.attachments) {
// Get the URL of the message attachment
let attachment_url = received_message.attachments[0].payload.url;
response = {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": [{
"title": "Is this the right picture?",
"subtitle": "Tap a button to answer.",
"image_url": attachment_url,
"buttons": [
{
"type": "postback",
"title": "Yes!",
"payload": "yes",
},
{
"type": "postback",
"title": "No!",
"payload": "no",
}
],
}]
}
}
}
}
// Send the response message
callSendAPI(sender_psid, response);
}
最後のステップは、messaging_postbacks
Webhookイベントを処理することです。このイベントは、メッセージ受信者が汎用テンプレートのいずれかのポストバックボタンをタップすると送信されます。
ポストバックボタンは、messaging_postbacks
WebhookイベントをWebhookに送信します。そのpayload
プロパティには、1,000文字以下のカスタム文字列が含まれます。これにより、さまざまなポストバックペイロードを簡単に実装できます。それらを解析して特定の動作を行う返信ができます。
この汎用テンプレートでは、メッセージ受信者が2つのポストバックボタンのいずれかを選ぶことができるため、ポストバックイベントのpayload
プロパティの値に基づいて返信します。そのためには、handlePostback()
スタブを次のように更新します。
function handlePostback(sender_psid, received_postback) {
let response;
// Get the payload for the postback
let payload = received_postback.payload;
// Set the response based on the postback payload
if (payload === 'yes') {
response = { "text": "Thanks!" }
} else if (payload === 'no') {
response = { "text": "Oops, try sending another image." }
}
// Send the message to acknowledge the postback
callSendAPI(sender_psid, response);
}