- PVSM.RU - https://www.pvsm.ru -
В настоящее время наблюдается, действительно, бум чат-мессенджеров. Один за другим платформы для обмена мгновенными сообщениями объявляют о запуске платформы для разработки ботов.
Не стал и исключением Facebook. 12 апреля на конференции F8 Facebook представила платформу для разработки ботов для своего мессенджера.
В данной статье хочу поделиться опытом разработки чат-бота для Facebook на PHP.
Чат-боты в Facebook построены на основе личных сообщений с публичной страницей от имени пользователя.
Поэтому для создания бота нужно будет создать само приложение для доступа к API, и публичную страницу, с которой будут общаться пользователи.
Не буду подробно останавливаться на этом пункте.
Просто создаем публичную страницу, называем ее так, как хотим видеть в мессенджере нашего бота, и загружаем иконку.
Переходим к регистрации своего приложения в аккаунте разработчика.
Заходим по ссылке developers.facebook.com/apps [1]
Нажимаем на добавление нового приложения, выбираем другой настройку вручную:
Далее заполняем форму:
После создания приложения, в левом меню выбираем вкладку Messenger и кликаем на нее.
Нажимаем «Начать».
В первую очередь выбираем страницу, созданную для бота, и копируем token. Сохраняем его где-нибудь, он нам пригодится дальше.
Дальше мы будем настраивать webhook для обработки входящих сообщений.
На этом шаге, вам нужно закачать следующий скрипт на сервер, где будет размещен бот:
<?php
$verify_token = ""; // Verify token
if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] == 'subscribe' && $_REQUEST['hub_verify_token'] == $verify_token) {
echo $_REQUEST['hub_challenge'];
}
В переменную $verify_token необходимо добавить какой-то текст.
Скрипт загружаем на сервер. Допустим, наш скрипт доступен по адресу: domain.com/fbbot [2]
Возвращаемся ко вкладке Messenger в настройках приложения FB.
Ищем блок «Webhooks» и кнопку «Setup Webhooks». Кликаем на нее.
В поле «Обратный URL-адрес» указываем адрес нашего бота — domain.com/fbbot [2]
SSL — сертификат является обязательным. Самоподписанный сертификат не подойдет.
В поле «Подтвердить маркер» указываем тот текст, который указали в переменной $verify_token в скрипте.
В поле «Поля подписки» выбираем, какие уведомления мы хотим получать на наш webhook:
Выбираем нужные и нажимаем кнопку «Подтвердить и сохранить».
Набираем в консоли:
curl -ik -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=-token-"
-token- заменяем на токен вашей страницы.
Сообщения могут быть либо просто текстовые, либо Structured Text, которые в свою очередь могут быть:
Данный тип предназначен для отправки сообщений, на которые требуется реакция пользователя.
Выглядят они примерно так:
Кнопки могут быть двух типов:
Важный момент: в одном таком сообщении может быть максимум 3 кнопки, при попытке отправить сообщение с бОльшим количеством кнопок — оно просто не дойдет до получателя.
Данный тип предназначен для отправки карточек товаров или других элементов, имеющих похожую структуру.
Каждый элемент может иметь: Заголовок, подзаголовок, описание, изображение и кнопки.
В одном сообщении может содержаться до 10 элементов. При наличии более одного элемента, появляется горизонтальная прокрутка.
Важный момент: в одном таком сообщении может быть максимум 3 кнопки, при попытке отправить сообщение с бОльшим количеством кнопок — оно просто не дойдет до получателя.
Предназначение понятно из названия.
Facebook решил сделать из своего мессенджера полноценный магазин.
Счет на оплату может содержать информацию о товарах, стоимости, оплате, адресе доставки, скидках.
Важный момент: номер счета должен быть уникальным.
На момент написания бота, на GitHub еще не было реализации API на PHP, поэтому пришлось писать PHP SDK самостоятельно.
Устанавливаем PHP SDK для работы с FB Messenger API при помощи composer:
composer require "pimax/fb-messenger-php" "dev-master"
Создаем файл index.php:
<?php
$verify_token = ""; // Verify token
$token = ""; // Page token
if (file_exists(__DIR__.'/config.php')) {
$config = include __DIR__.'/config.php';
$verify_token = $config['verify_token'];
$token = $config['token'];
}
require_once(dirname(__FILE__) . '/vendor/autoload.php');
use pimaxFbBotApp;
use pimaxMessagesMessage;
use pimaxMessagesMessageButton;
use pimaxMessagesStructuredMessage;
use pimaxMessagesMessageElement;
use pimaxMessagesMessageReceiptElement;
use pimaxMessagesAddress;
use pimaxMessagesSummary;
use pimaxMessagesAdjustment;
$bot = new FbBotApp($token);
if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] == 'subscribe' && $_REQUEST['hub_verify_token'] == $verify_token)
{
// Webhook setup request
echo $_REQUEST['hub_challenge'];
} else {
$data = json_decode(file_get_contents("php://input"), true);
if (!empty($data['entry'][0]['messaging']))
{
foreach ($data['entry'][0]['messaging'] as $message)
{
// Получено сообщение
// Основной код будет в этом блоке
// ...
}
}
}
Пробуем отправить сообщение пользователю в ответ при получении любого сообщения от него.
Для этого в блок получения сообщения, добавляем:
$bot->send(new Message($message['sender']['id'], ‘Hi there!'));
Проверяем. Находим в мессенджере нашего бота и пробуем отправить ему любое сообщение.
В ответ мы должны получить от него «Hi there!».
Важно: Пока приложение не прошло модерацию бот будет работать только для автора приложения.
Если все работает как надо, идем дальше.
В блок получения сообщения добавляем:
// Пропускаем обработку отметок о доставке сообщения
if (!empty($message['delivery'])) {
continue;
}
$command = "";
// Получено сообщение от пользователя, записываем как команду
if (!empty($message['message'])) {
$command = $message['message']['text'];
// ИЛИ Зафиксирован переход по кнопке, записываем как команду
} else if (!empty($message['postback'])) {
$command = $message['postback']['payload'];
}
// Обрабатываем команду
switch ($command) {
// When bot receive "text"
case 'text':
$bot->send(new Message($message['sender']['id'], 'This is a simple text message.'));
break;
// When bot receive "button"
case 'button':
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_BUTTON,
[
'text' => 'Choose category',
'buttons' => [
new MessageButton(MessageButton::TYPE_POSTBACK, 'First button'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Second button'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Third button')
]
]
));
break;
// When bot receive "generic"
case 'generic':
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_GENERIC,
[
'elements' => [
new MessageElement("First item", "Item description", "", [
new MessageButton(MessageButton::TYPE_POSTBACK, 'First button'),
new MessageButton(MessageButton::TYPE_WEB, 'Web link', 'http://facebook.com')
]),
new MessageElement("Second item", "Item description", "", [
new MessageButton(MessageButton::TYPE_POSTBACK, 'First button'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Second button')
]),
new MessageElement("Third item", "Item description", "", [
new MessageButton(MessageButton::TYPE_POSTBACK, 'First button'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Second button')
])
]
]
));
break;
// When bot receive "receipt"
case 'receipt':
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_RECEIPT,
[
'recipient_name' => 'Fox Brown',
'order_number' => rand(10000, 99999),
'currency' => 'USD',
'payment_method' => 'VISA',
'order_url' => 'http://facebook.com',
'timestamp' => time(),
'elements' => [
new MessageReceiptElement("First item", "Item description", "", 1, 300, "USD"),
new MessageReceiptElement("Second item", "Item description", "", 2, 200, "USD"),
new MessageReceiptElement("Third item", "Item description", "", 3, 1800, "USD"),
],
'address' => new Address([
'country' => 'US',
'state' => 'CA',
'postal_code' => 94025,
'city' => 'Menlo Park',
'street_1' => '1 Hacker Way',
'street_2' => ''
]),
'summary' => new Summary([
'subtotal' => 2300,
'shipping_cost' => 150,
'total_tax' => 50,
'total_cost' => 2500,
]),
'adjustments' => [
new Adjustment([
'name' => 'New Customer Discount',
'amount' => 20
]),
new Adjustment([
'name' => '$10 Off Coupon',
'amount' => 10
])
]
]
));
break;
// Other message received
default:
$bot->send(new Message($message['sender']['id'], 'Sorry. I don’t understand you.'));
}
Пробуем отправить боту сообщения:
Если все сделано по инструкции, то должны получить в мессенджер сообщения всех типов.
Итак, наша цель, реализовать бота, который по нашему запросу будет выдавать новые проекты в соответствующей категории.
Данные будем получать по RSS, используя picoFeed — github.com/fguillot/picoFeed [3]
Выполняем:
composer require fguillot/picofeed @stable
composer require "pimax/fb-messenger-php" "dev-master"
Создаем файл index.php следующего содержания (комментарии приведены в коде):
<?php
$verify_token = ""; // Verify token
$token = ""; // Page token
$config = []; // config
if (file_exists(__DIR__.'/config.php')) {
$config = include __DIR__.'/config.php';
$verify_token = $config['verify_token'];
$token = $config['token'];
}
require_once(dirname(__FILE__) . '/vendor/autoload.php');
use PicoFeedReaderReader;
use pimaxFbBotApp;
use pimaxMessagesMessage;
use pimaxMessagesMessageButton;
use pimaxMessagesStructuredMessage;
use pimaxMessagesMessageElement;
$bot = new FbBotApp($token);
if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] == 'subscribe' && $_REQUEST['hub_verify_token'] == $verify_token)
{
// Webhook setup request
echo $_REQUEST['hub_challenge'];
} else {
$data = json_decode(file_get_contents("php://input"), true);
if (!empty($data['entry'][0]['messaging']))
{
foreach ($data['entry'][0]['messaging'] as $message)
{
if (!empty($data['entry'][0])) {
if (!empty($data['entry'][0]['messaging']))
{
foreach ($data['entry'][0]['messaging'] as $message)
{
if (!empty($message['delivery'])) {
continue;
}
$command = "";
if (!empty($message['message'])) {
$command = $message['message']['text'];
} else if (!empty($message['postback'])) {
$command = $message['postback']['payload'];
}
if (!empty($config['feeds'][$command]))
{
getFeed($config['feeds'][$command], $bot, $message);
} else {
sendHelpMessage($bot, $message);
}
}
}
}
}
}
}
/**
* Send Help Message
*
* @param $bot Bot instance
* @param array $message Received message
* @return bool
*/
function sendHelpMessage($bot, $message)
{
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_BUTTON,
[
'text' => 'Choose category',
'buttons' => [
new MessageButton(MessageButton::TYPE_POSTBACK, 'All jobs'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Web Development'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Software Development & IT')
]
]
));
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_BUTTON,
[
'text' => ' ',
'buttons' => [
new MessageButton(MessageButton::TYPE_POSTBACK, 'Design & Multimedia'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Mobile Application'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Host & Server Management')
]
]
));
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_BUTTON,
[
'text' => ' ',
'buttons' => [
new MessageButton(MessageButton::TYPE_POSTBACK, 'Writing'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Mobile Application'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Marketing')
]
]
));
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_BUTTON,
[
'text' => ' ',
'buttons' => [
new MessageButton(MessageButton::TYPE_POSTBACK, 'Business Services'),
new MessageButton(MessageButton::TYPE_POSTBACK, 'Translation & Languages')
]
]
));
return true;
}
/**
* Get Feed Data
*
* @param $url Feed url
* @param $bot Bot instance
* @param $message Received message
* @return bool
*/
function getFeed($url, $bot, $message)
{
try {
$reader = new Reader;
$resource = $reader->download($url);
$parser = $reader->getParser(
$resource->getUrl(),
$resource->getContent(),
$resource->getEncoding()
);
$feed = $parser->execute();
$items = array_reverse($feed->getItems());
if (count($items)) {
foreach ($items as $itm)
{
$url = $itm->getUrl();
$message_text = substr(strip_tags($itm->getContent()), 0, 80);
$bot->send(new StructuredMessage($message['sender']['id'],
StructuredMessage::TYPE_GENERIC,
[
'elements' => [
new MessageElement($itm->getTitle(), $message_text, '', [
new MessageButton(MessageButton::TYPE_WEB, 'Read more', $url)
]),
]
]
));
}
} else {
$bot->send(new Message($message['sender']['id'], 'Not found a new projects in this section.'));
}
}
catch (Exception $e) {
writeToLog($e->getMessage(), 'Exception');
}
return true;
}
/**
* Log
*
* @param mixed $data Data
* @param string $title Title
* @return bool
*/
function writeToLog($data, $title = '')
{
$log = "n------------------------n";
$log .= date("Y.m.d G:i:s") . "n";
$log .= (strlen($title) > 0 ? $title : 'DEBUG') . "n";
$log .= print_r($data, 1);
$log .= "n------------------------n";
file_put_contents(__DIR__ . '/imbot.log', $log, FILE_APPEND);
return true;
}
И файл config.php следующего содержания:
<?php
return [
'token' => '', // Токен страницы
'verify_token' => '', // Проверочный токен
'feeds' => [
'All jobs' => 'https://job4joy.com/marketplace/rss/',
'Web Development' => 'https://job4joy.com/marketplace/rss/?id=3',
'Software Development & IT' => 'https://job4joy.com/marketplace/rss/?id=5',
'Design & Multimedia' => 'https://job4joy.com/marketplace/rss/?id=2',
'Mobile Application' => 'https://job4joy.com/marketplace/rss/?id=7',
'Host & Server Management' => 'https://job4joy.com/marketplace/rss/?id=6',
'Writing' => 'https://job4joy.com/marketplace/rss/?id=8',
'Customer Service' => 'https://job4joy.com/marketplace/rss/?id=10',
'Marketing' => 'https://job4joy.com/marketplace/rss/?id=11',
'Business Services' => 'https://job4joy.com/marketplace/rss/?id=12',
'Translation & Languages' => 'https://job4joy.com/marketplace/rss/?id=14',
]
];
Пока бот доступен только для владельца аккаунта. Чтобы бот был доступен для всех, нужно На странице App Review — опубликовать приложение:
После этого нужно запросить модерацию мессенджера. Для этого переходим на вкладку — Messenger.
В блоке «App Review for Messenger» нажимаем кнопку «Request Permissions».
В появившемся окне выбираем «pages_messaging» и нажимаем «Add items».
Теперь остается только дождаться модерации.
На момент написания этой статьи, модерация нашего первого бота не завершена, хотя прошло уже более двух рабочих дней с момента подачи заявки.
В статье мы рассмотрели базовые аспекты создания чат-бота для Facebook.
Если тема окажется популярной, то готов буду рассказать об опыте разработки ботов под другие популярные мессенджеры.
Автор: pimax
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/118203
Ссылки в тексте:
[1] developers.facebook.com/apps: https://developers.facebook.com/apps/
[2] domain.com/fbbot: https://domain.com/fbbot/
[3] github.com/fguillot/picoFeed: https://github.com/fguillot/picoFeed
[4] developers.facebook.com/docs/messenger-platform/quickstart: https://developers.facebook.com/docs/messenger-platform/quickstart
[5] developers.facebook.com/docs/messenger-platform/webhook-reference: https://developers.facebook.com/docs/messenger-platform/webhook-reference
[6] github.com/pimax/fb-messenger-php: https://github.com/pimax/fb-messenger-php
[7] github.com/pimax/fb-messenger-php-example: https://github.com/pimax/fb-messenger-php-example
[8] github.com/pimax/job4joy_fb: https://github.com/pimax/job4joy_fb
[9] Источник: https://habrahabr.ru/post/281559/
Нажмите здесь для печати.