/fb-messenger-sdk

Facebook Messenger Bot php sdk

Primary LanguagePHPMIT LicenseMIT

Facebook Messenger Bot PHP

Implementation of the Facebook Messenger Platform API.

Scrutinizer Code Quality Code Coverage Build Status

Still under development...

## Install:

Via composer:

$ composer require tgallice/fb-messenger-sdk

Usage:

Create a Messenger instance

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Client;
use Tgallice\FBMessenger\Messenger;

$client = new Client('<PAGE_TOKEN>');
$messenger = new Messenger($client);

// Or quick factory
$messenger = Messenger::create('<PAGE_TOKEN>');

Send a simple text message to a user:

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;

$messenger = Messenger::create('<PAGE_TOKEN>');

// Simple Text message
$response = $messenger->sendMessage('<USER_ID>', 'My Message');

Send a message with quick replies

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;
use Tgallice\FBMessenger\Model\Message;
use Tgallice\FBMessenger\Model\QuickReply\Text;

$messenger = Messenger::create('<PAGE_TOKEN>');

$message = new Message('What do you like ?');
$message->setQuickReplies([
    new Text('Apple', 'LIKE_APPLE_PAYLOAD'),
    new Text('Peach', 'LIKE_PEACH_PAYLOAD')
]);

$response = $messenger->sendMessage('<USER_ID>', $message);

Send a more complex message with a Generic template

Horizontal scrollable carousel of items

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;
use Tgallice\FBMessenger\Model\DefaultAction;
use Tgallice\FBMessenger\Model\Button\Share;
use Tgallice\FBMessenger\Model\Button\WebUrl;
use Tgallice\FBMessenger\Model\Button\Postback;
use Tgallice\FBMessenger\Model\Attachment\Template\Generic;
use Tgallice\FBMessenger\Model\Attachment\Template\Generic\Element;

$messenger = Messenger::create('<PAGE_TOKEN>');

$elements = [
    new Element(
        'My first Item',
        'My first subtitle',
        'http://www.site.com/image.jpg',
        [ 
            new WebUrl('Button 1 label', 'https://www.site.com'),
            new Share()
        ],
        new DefaultAction('https://www.site.com/')
    ),
    new Element(
        'My second Item',
        'My second subtitle',
        'http://www.site.com/image.jpg',
        [ 
            new Postback('Button 2 label', 'MY_PAYLOAD'),
            new Share()
        ],
        new DefaultAction('https://www.domain.com/')
    )
];

$template = new Generic($elements);

$response = $messenger->sendMessage('<USER_ID>', $template);

Send a more complex message with a Receipt template

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;
use Tgallice\FBMessenger\Model\Attachment\Template\Receipt;
use Tgallice\FBMessenger\Model\Attachment\Template\Receipt\Element;
use Tgallice\FBMessenger\Model\Attachment\Template\Receipt\Summary;

$messenger = Messenger::create('<PAGE_TOKEN>');

$elements = [
    new Element('My first Item', <price>),
    new Element('My Second Item', <price>),
];

$summary = new Summary(<total_cost>);
$receipt = new Receipt('My Receipt', '123456789', 'EUR', 'Visa', $elements, $summary);

$response = $messenger->sendMessage('<USER_ID>', $receipt);

Send a more complex message with a List template

Note: See the Facebook Messenger Platform List Template limitations.

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;
use Tgallice\FBMessenger\Model\DefaultAction;
use Tgallice\FBMessenger\Model\Button\Share;
use Tgallice\FBMessenger\Model\Attachment\Template\ElementList;
use Tgallice\FBMessenger\Model\Attachment\Template\ElementList\Element;

$messenger = Messenger::create('<PAGE_TOKEN>');

$elements = [
    new Element(
        'My first Item',
        'My first subtitle',
        'http://www.site.com/image.jpg',
        new Share(),
        new DefaultAction('https://www.site.com/', DefaultAction::HEIGHT_RATIO_FULL)
    ),
    new Element(
        'My second Item',
        'My second subtitle',
        'http://www.site.com/image.jpg',
        new Share(),
        new DefaultAction('https://www.domain.com/', DefaultAction::HEIGHT_RATIO_COMPACT)
    )
];

// $elements = insert logic to meet List Template limitations (e.g. at least 2 elements and at most 4 elements)

$list = new ElementList($elements);

$response = $messenger->sendMessage('<USER_ID>', $list);

Buttons message

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Model\Attachment\Template\Button;
use Tgallice\FBMessenger\Model\Button\WebUrl;
use Tgallice\FBMessenger\Model\Button\Postback;

$messenger = Messenger::create('<PAGE_TOKEN>');

$elements = [
    new WebUrl('Button1', 'http://google.com'),
    new Postback('Button2', 'EVENT_NAME'),
];

$template = new Button('My template', $elements);

$response = $messenger->sendMessage('<USER_ID>', $template);

Image Message

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;
use Tgallice\FBMessenger\Model\Attachment\Image;

$messenger = Messenger::create('<PAGE_TOKEN>');

// Local file
$image = new Image('./image.jpg');
$response = $messenger->sendMessage('<USER_ID>', $image);

// Remote file
$image = new Image('http://www.site.com/image.jpg');
$response = $messenger->sendMessage('<USER_ID>', $image);

Get user profile

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Client;
use Tgallice\FBMessenger\Messenger;

$messenger = Messenger::create('<PAGE_TOKEN>');

// $event may be PostbackEvent or MessageEvent
$profile = $messenger->getUserProfile($event->getSenderId());

echo $profile->getFirstName();
echo $profile->getLastName();
echo $profile->getGender();
echo $profile->getLocale();
...

// Result:
//
// John
// Doe
// male
// en_US

Set typing indicators or send read receipts

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Client;
use Tgallice\FBMessenger\Messenger;

$messenger = Messenger::create('<PAGE_TOKEN>');

// Send read receipt indicating the user message has been received and "seen"
$messenger->setTypingStatus('<USER_ID>', \Tgallice\FBMessenger\TypingIndicator::MARK_SEEN);

// Turn on typing indicator to let users know you are processing their request
$messenger->setTypingStatus('<USER_ID>', \Tgallice\FBMessenger\TypingIndicator::TYPING_ON);

// Turn off typing indicator, e.g. after the user request has been finished processing
// and your response has been sent with $messenger->sendMessage()
$messenger->setTypingStatus('<USER_ID>', \Tgallice\FBMessenger\TypingIndicator::TYPING_OFF);

Webhook setup

When you setup a Callback URL in your app, Facebook need to validate this entry point. In this process you must define a Verify Token Your job is to compare the received verify token and the one you setup them return the challenge given. Here is how to easily handle the whole process:

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\WebhookRequestHandler;

$webookHandler = new WebhookRequestHandler('app_secret', 'verify_token');
// The Request is internally retrieve but you can set your own if you have already a Request object.
// $webookHandler = new WebhookRequestHandler('app_secret', 'verify_token', $request);


if (!$webookHandler->isValidVerifyTokenRequest()) {
    ...error
}

// you must return a 200 OK HTTP response 
header("HTTP/1.1 200 OK");

echo $webookHandler->getChallenge();

Webhook listening

We assume that we receive this payload from Facebook:

{
  "object": "page",
  "entry": [
    {
      "id": "PAGE_ID",
      "time": 1473204787206,
      "messaging": [
        {
          "sender":{
            "id":"USER_ID"
          },
          "recipient":{
            "id":"PAGE_ID"
          },
          "timestamp":1458692752478,
          "message":{
            "mid":"mid.1457764197618:41d102a3e1ae206a38",
            "seq":73,
            "text":"hello, world!",
            "quick_reply": {
              "payload": "DEVELOPER_DEFINED_PAYLOAD"
            }
          }
        }
      ]
    }
  ]
}

Basic usage

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\WebhookRequestHandler;

$webookHandler = new WebhookRequestHandler('app_secret', 'verify_token');
// The Request is internally retrieve but you can set your own if you have already a Request object.
// $webookHandler = new WebhookRequestHandler('app_secret', 'verify_token', $request);

if (!$webookHandler->isValidCallbackRequest()) {
    ...error
}

// @see https://developers.facebook.com/docs/messenger-platform/webhook-reference
// @var CallbackEvent[] $events
$events = $webookHandler->getAllCallbackEvents();

foreach($events as $event) {
    if ($event instanceof MessageEvent) {
          echo $event->getMessageText()."\n";
          echo $event->getQuickReplyPayload()."\n";
    }
}

// Result:
//
// hello, world!
// DEVELOPER_DEFINED_PAYLOAD

// you must return a 200 OK HTTP response 

Advanced usage

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\WebhookRequestHandler;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Tgallice\FBMessenger\Callback\MessageEvent;

// We use the symfony/event-dispatcher package
// @see https://github.com/symfony/event-dispatcher for more details
// Create custom event listener
class MessageEventListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            MessageEvent::NAME => 'onMessageEvent', // may also handle quick replies by checking with isQuickReply()
            PostbackEvent::NAME => 'onPostbackEvent',
            'DEVELOPER_DEFINED_PAYLOAD_1' => 'onQuickReply' // optional: quick reply specific payload
        ];
    }

    public function onMessageEvent(MessageEvent $event)
    {
        if( $event->isQuickReply() ) { // if a quick reply callback, pass it to our onQuickReply method
            $this->onQuickReply($event);
            return;
        }
		
        print(__METHOD__."\n");
    }

    public function onPostbackEvent(PostbackEvent $event)
    {
        print(__METHOD__."\n");
    }

    public function onQuickReply(MessageEvent $event)
    {
        switch( $event->getQuickReplyPayload() ) {
            case 'DEVELOPER_DEFINED_PAYLOAD_2':
                print(__METHOD__."\n");
                break;
        }
    }
}

$webhookHandler = new WebhookRequestHandler('<APP_SECRET>', '<VERIFY_TOKEN>');

// Register the listener
$webhook->addEventSubscriber(new MessageEventListener());

if (!$webookHandler->isValidCallbackRequest()) {
    ...error
}

$webhook->dispatchCallbackEvents();

// Result:
//
// MessageEventListener::onMessageEvent
// MessageEventListener::onPostbackEvent
// MessageEventListener::onQuickReply


// you must return a 200 OK HTTP response 

Thread Settings

Set greeting text

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;

$messenger = Messenger::create('<PAGE_TOKEN>');
$messenger->setGreetingText('Tell me what you want.');

Set started button

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;

$messenger = Messenger::create('<PAGE_TOKEN>');
$messenger->setStartedButton('MY_PLAYLOAD_TO_TRIGGER');

Set a Persistent Menu

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;
use Tgallice\FBMessenger\Model\ThreadSetting\PostBack;
use Tgallice\FBMessenger\Model\ThreadSetting\WebUrl;

$messenger = Messenger::create('<PAGE_TOKEN>');

$buttons = [
    new PostBack('Button Title 1', 'MY_PAYLOAD'),      
    new WebUrl('Button Title 2', 'http://my-url.com'),      
];

$messenger->setPersistentMenu($buttons);

Page action

Subscribe bot to a page

require_once __DIR__.'/vendor/autoload.php';

use Tgallice\FBMessenger\Messenger;

$messenger = Messenger::create('<PAGE_TOKEN>');
$messenger->subscribe();

And more other cool things...

Todo

  • Improve document
  • Add Airline template