Facebook Messenger开发,这一篇文章就够了

4,856 阅读6分钟

一篇很基础入门的Messenger开发文档,开发语言基于node.js,初学者建议你认真阅读这篇文章,一篇文章学会Messenger开发

messenger

Messenger简介


Messenger是Facebook的聊天软件,类似于微信,基于Messenger的开发就相当于公众号的开发,了解更多,请点击 官方文档

开发准备


1.新建项目

mkdir messenger-webhook         // Creates a project directory
cd messenger-webhook            // Navigates to the new directory
touch index.js                  // Creates empty index.js file.
npm init                        // Creates package.json. Accept default for all questions.
npm install express body-parser --save // Installs the express.js http server framework module, 
                                               // and then adds them to the dependencies section of package.json file

比较简单,新建完,项目目录如下:

index.js	
node_modules
package.json

2.创建HTTP服务器,监听服务

'use strict';

// Imports dependencies and set up http server
const
  express = require('express'),
  bodyParser = require('body-parser'),
  app = express().use(bodyParser.json()); // creates express http server
  require('dotenv').config();

// Sets server port and logs message on success
app.listen(process.env.PORT, () => console.log('webhook is listening'));

此代码用于监听服务器请求,本次项目开发,用的node.js的express框架,其中require('dotenv').config() 作用是加载环境变量.env

3.创建webhook,接收用户事件

app.post('/webhook', (req, res) => {
    let body = req.body;
    // Checks this is an event from a page subscription
    if (body.object === 'page') {
        // Iterates over each entry - there may be multiple if batched
        body.entry.forEach(function(entry) {
            entry.messaging.forEach(messagingEvent => {
                if (messagingEvent.message) {
                    //message为用户向平台发送消息事件
                } else if (messagingEvent.postback) {
                    //postback为用户点击开始按钮,点击固定菜单等回调事件
                } else if (messagingEvent.referral) {
                    //m.me链接,广告,印章等
                } else {
                    console.log("Webhook received unknown messagingEvent: ", messagingEvent);
                }
            })

        });
        // Returns a '200 OK' response to all requests
        res.status(200).send('EVENT_RECEIVED');
    } else {
        // Returns a '404 Not Found' if event is not from a page subscription
        res.sendStatus(404);
    }
});

此代码将创建一个 /webhook 端点,用于接收 POST 请求,验证请求是否为 webhook 事件,然后解析消息。Messenger 平台会通过该端点发送所有 webhook 事件。 用户在messenger发消息,监听到的body.object是'page',entry为包含事件数据的阵列,我这里开发了entry.messaging的三种用户基本事件

4.添加webhook验证,验证口令一致

// Adds support for GET requests to our webhook
app.get('/webhook', (req, res) => {

    // Your verify token. Should be a random string.
    let VERIFY_TOKEN = PAGE_ACCESS_TOKEN;

    // Parse the query params
    let mode = req.query['hub.mode'];
    let token = req.query['hub.verify_token'];
    let challenge = req.query['hub.challenge'];

    // Checks if a token and mode is in the query string of the request
    if (mode && token) {

        // Checks the mode and token sent is correct
        if (mode === 'subscribe' && token === VERIFY_TOKEN) {

            // Responds with the challenge token from the request
            console.log('WEBHOOK_VERIFIED');
            res.status(200).send(challenge);

        } else {
            // Responds with '403 Forbidden' if verify tokens do not match
            res.sendStatus(403);
        }
    }
});

5.测试webhook

1 本地主机上启动 webhook:

node index.js

2 测试 webhook 验证:

curl -X GET "localhost:1337/webhook?hub.verify_token=<YOUR_VERIFY_TOKEN>&hub.challenge=CHALLENGE_ACCEPTED&hub.mode=subscribe"

3 测试 webhook请求:

curl -H "Content-Type: application/json" -X POST "localhost:1337/webhook" -d '{"object": "page", "entry": [{"messaging": [{"message": "TEST_MESSAGE"}]}]}'

6. 部署webhook

为了能接收通过 HTTPS 发送的请求,必须将 webhook 部署到拥有有效 SSL 证书的服务器中

7. 将 webhook 订阅到 Facebook 应用

到现在,准备工作已经完成,但是还没有app接收webhook事件,最后一步,要将webhook订阅到facebook应用,官方文档很详细,这里不再做教程,官方文档入口

消息模板


捕捉到用户的事件,用于自动回复预定义信息,消息模板的作用是结构化消息,呈现用户更好更丰富的体验。消息模板的使用是开发Messenger的基础,也是Messenger开发中应用最多的。Messenger预定义支持以下模板:

  • 常规模板
  • 列表模板
  • 按钮模板
  • 开放图谱模板
  • 回执模板
  • 航班信息模板
  • 媒体模板

模板的标准格式如下,其中 message.attachment.payload 属性包含针对各类具体模板的类型和内容详情

{
  "recipient":{
    "id":"<PSID>" // 发消息用户的psid
  },
  "message":{
    "attachment":{
      "type":"template",
      "payload":{
        "template_type":"<TEMPLATE_TYPE>",
        ...
      }
    }
  }
}

1. 常规模板

常规模板是一种简单的结构化消息,其中包含标题、副标题、图片和最多三个按钮:您还可以指定 default_action 对象(可选),设置用户轻触模板后将在 Messenger 网页视图中打开的网址。重点介绍常规模板,其他模板的内容大同小异,不同就在于,不一样的模板设置的属性不一样。

messenger
常规模板格式如下:

"payload": {
  "template_type":"generic",
  "elements":[
     {
      "title":"<TITLE_TEXT>",//消息title
      "image_url":"<IMAGE_URL_TO_DISPLAY>",//消息图片
      "subtitle":"<SUBTITLE_TEXT>",//消息内容
      "default_action": {//默认点击消息跳转,type只能是web_url
        "type": "web_url",
        "url": "<DEFAULT_URL_TO_OPEN>",
        "messenger_extensions": <TRUE | FALSE>,
        "webview_height_ratio": "<COMPACT | TALL | FULL>"
      },
      "buttons":[<BUTTON_OBJECT>, ...]  //按钮    
    },
    ...
  ]
}

发送模板轮播

"payload": {
  "template_type":"generic",
  "elements":[
    <GENERIC_TEMPLATE>,
    <GENERIC_TEMPLATE>,
    ...
  ]
}

即发送模板轮播,要在 payload 的 elements 数组中添加最多 10 个常规模板,注意最多10个常规模板 。

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient":{
    "id":"<PSID>"
  },
  "message":{
    "attachment":{
      "type":"template",
      "payload":{
        "template_type":"generic",
        "elements":[
           {
            "title":"Welcome!",
            "image_url":"https://petersfancybrownhats.com/company_image.png",
            "subtitle":"We have the right hat for everyone.",
            "default_action": {
              "type": "web_url",
              "url": "https://petersfancybrownhats.com/view?item=103",
              "messenger_extensions": false,
              "webview_height_ratio": "tall",
              "fallback_url": "https://petersfancybrownhats.com/"
            },
            "buttons":[
              {
                "type":"web_url",
                "url":"https://petersfancybrownhats.com",
                "title":"View Website"
              },{
                "type":"postback",
                "title":"Start Chatting",
                "payload":"DEVELOPER_DEFINED_PAYLOAD"
              }              
            ]      
          }
        ]
      }
    }
  }
}' "https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>"

回传示例

{
  "recipient_id": "1254477777772919",
  "message_id": "m_AG5Hz2Uq7tuwNEhXfYYKj8mJEM_QPpz5jdCK48PnKAjSdjfipqxqMvK8ma6AC8fplwlqLP_5cgXIbu7I3rBN0P"
}  

在此介绍一下按钮的模板

网址按钮

{
 "type": "web_url",
 "url": "<URL_TO_OPEN_IN_WEBVIEW>",
 "title": "<BUTTON_TEXT>",
}

回传按钮

{
 "type": "postback",
 "title": "<BUTTON_TEXT>",
 "payload": "<STRING_SENT_TO_WEBHOOK>"
}

分享按钮

{
 "type": "element_share",
 "share_contents": { 
   "attachment": {
     "type": "template",
     "payload": {//对于使用 element_share 功能的分享按钮,仅支持包含一个网址按钮的常规模板,即分享的内容中,button的type只能是web_url
       <GENERIC_TEMPLATE_OBJECT>
     }
   }
 }
}

购买按钮(仅向美国用户开放)

{
 "type":"payment",
 "title":"<BUTTON_TEXT>",
 "payload":"<STRING_SENT_TO_WEBHOOK>",
 "payment_summary":{
   "currency":"<CURRENCY_ABBREVIATION>",
   "payment_type":"<FIXED_AMOUNT | FLEXIBLE_AMOUNT>",
   "is_test_payment" : <TRUE | FALSE >, 
   "merchant_name":"<YOUR_BUSINESS_NAME>",
   "requested_user_info":[
     "shipping_address",
     "contact_name",
     "contact_phone",
     "contact_email"
   ],
   "price_list":[
     {
       "label":"<ITEM_NAME>",
       "amount":"<ITEM_PRICE>"
     },
     ...
   ]
 }
}

呼叫按钮

{
 "type":"phone_number",
 "title":"<BUTTON_TEXT>",
 "payload":"<PHONE_NUMBER>"
}

登陆按钮

{
 "type": "account_link",
 "url": "<YOUR_LOGIN_URL>"
}

退出按钮

{
 "type": "account_unlink"
}

玩游戏按钮

{
 "type":"game_play",
 "title":"Play",
 "payload":"{<SERIALIZED_JSON_PAYLOAD>}",
 "game_metadata": { // Only one of the below
   "player_id": "<PLAYER_ID>",
   "context_id": "<CONTEXT_ID>"
 }
}

2. 列表模板

列表模板是 2-4 个结构化项目组成的列表,可在底部选择性地显示全局按钮。每个项目可包含一个缩略图、标题、副标题和一个按钮。同样也可以指定 default_action 对象,设置用户轻触项目后将在 Messenger 网页视图中打开的网址。

messenger
列表模板格式:

"payload": {
  "template_type": "list",
  "top_element_style": "<LARGE | COMPACT>",
  "elements": [
    {
      "title": "<TITLE_TEXT>",
      "subtitle": "<SUBTITLE_TEXT>",
      "image_url": "<IMAGE_URL_FOR_THUMBNAIL>",          
      "buttons": [<BUTTON_OBJECT>],
      "default_action": {
        "type": "web_url",
        "url": "<URL_TO_OPEN_WHEN_ITEM_IS_TAPPED>",
        "messenger_extensions": <TRUE | FALSE>,
        "webview_height_ratio": "<COMPACT | TALL | FULL>"
      }
    },
    ...
  ],
   "buttons": [<BUTTON_OBJECT>]  
}

这里指的注意的是默认情况下,列表中的第一个项目将作为包含叠加文本的封面图片显示。可以通过设置 "top_element_style": "compact",将第一个项目显示为标准的列表项目。

请求示例

请求示例大同小异,见常规模板

回传示例

回传示例也一样,见常规模板

3. 按钮模板

按钮模板可发送最多能包含三个按钮的文本消息。这种模板适用于为消息接收人提供可选择的选项,如预定义的问题回复或可以采取的操作。

messenger
按钮模板格式

"payload": {
  "template_type":"button",
  "text":"<MESSAGE_TEXT>",
  "buttons":[
    <BUTTON_OBJECT>, 
    <BUTTON_OBJECT>, 
    ...
  ]
}

按钮模板比较简单

因为请求示例和回传示例都相似,下文将不再做介绍,可以直接参考官方文档

4. 开放图谱模板

开放图谱模板可以发送结构化消息,并在其中添加开放图谱网址和可选按钮。目前,这种模板仅支持分享歌曲。歌曲会以聊天气泡的方式显示,消息接收人可以在这个气泡中看到专辑封面和歌曲预览。

messenger
开放图谱模板格式:

"payload": {
  "template_type":"open_graph",
  "elements":[
     {
      "url":"<OPEN_GRAPH_URL>",
      "buttons":[<BUTTON_OBJECT>]             
    }
  ]
}

媒体模板,回执模板,航班信息模板开发中用的比较少,再次就不再赘述,想要深入了解请参考官方文档


未完待续