Messenger 开放平台专用 Meta Webhooks

Meta Webhooks 可帮助您接收 Meta 社交关系图谱中特定对象变更的实时 HTTP 通知。例如,当用户向您的 Facebook 公共主页或 Instagram 专业账户发送消息时,我们可以向您发送通知。Webhooks 通知可帮助您追踪传入消息和消息状态更新。为追踪这些变更而查询 Messenger 开放平台端点时,该通知还可帮助您避免受到流量限制

为成功集成 Messenger 或 Instagram 对话的专用 Webhooks,您需要执行以下操作:

  1. 在您的服务器上创建端点,用于接收和处理 Webhooks 通知、JSON 对象
  2. 在应用面板中配置 Meta Webhooks 产品
  3. 订阅想要接收的 Meta Webhooks 通知
  4. 在与您的业务账户或 Instagram 专业账户绑定的 Facebook 公共主页上安装消息应用

准备工作

在开始前,假设您已完成以下事项:

配置 Node.JS 服务器

您的服务器必须能够处理 2 类 HTTPS 请求:验证请求事件通知。由于这两类请求都使用 HTTP,所以必须为您的服务器正确配置和安装有效的 TLS 或 SSL 证书。不支持自签名证书。

以下部分将介绍各类请求的内容,以及如何响应这些请求。

此处显示的代码示例来源于 GitHub 中的应用示例 。请浏览 GitHub,查看完整示例及进一步了解如何设置 Webhooks 服务器。

创建端点

如要创建端点以用于接收 Messenger 开放平台发送的 Webhooks 通知,app.js 文件可能如下所示:

// Create the endpoint for your webhook

app.post("/webhook", (req, res) => {
  let body = req.body;

  console.log(`\u{1F7EA} Received webhook:`);
  console.dir(body, { depth: null });
    
...
   

此代码将创建 /webhook 端点,该端点用于接受 POST 请求,检查此请求是否为 Webhooks 通知。

返回 200 OK 响应

端点必须返回 200 OK 响应,告知 Messenger 开放平台已收到事件,无需再次发送。通常需要在通知处理完毕后发送这一响应。

响应事件通知

端点响应所有通知时均应遵循以下规则:

  • 使用 200 OK HTTPS 响应
  • 响应时间不超过 5 秒

以下代码将位于 app.post 文件的 app.js 中,可能如下所示:

...
  // Send a 200 OK response if this is a page webhook

  if (body.object === "page") {
    // Returns a '200 OK' response to all requests
    res.status(200).send("EVENT_RECEIVED");
...
    // Determine which webhooks were triggered and get sender PSIDs and locale, message content and more.
...
  } else {
    // Return a '404 Not Found' if event is not from a page subscription
    res.sendStatus(404);
  }
}); 

验证请求

每当您在应用面板中配置 Webhooks 产品时,我们都会向您的端点网址发送 GET 请求。验证请求包含以下查询字符串参数,并会将其附加到端点网址的末尾。验证请求如下所示:

验证请求示例

GET https://www.your-clever-domain-name.com/webhooks? hub.mode=subscribe& hub.verify_token=mytoken& hub.challenge=1158201444

确认验证请求

每当收到验证请求时,您的端点都必须:

  • 确认 hub.verify_token 值与您在应用面板中配置 Webhooks 产品时,在验证口令字段中设置的字符串一致(您尚未设置此口令字符串)。
  • hub.challenge 值做出响应。

您的 app.js 文件可能如以下所示:

// Add support for GET requests to our webhook
app.get("/messaging-webhook", (req, res) => {
  
// Parse the query params
  let mode = req.query["hub.mode"];
  let token = req.query["hub.verify_token"];
  let challenge = req.query["hub.challenge"];

  // Check if a token and mode is in the query string of the request
  if (mode && token) {
    // Check the mode and token sent is correct
    if (mode === "subscribe" && token === config.verifyToken) {
      // Respond with the challenge token from the request
      console.log("WEBHOOK_VERIFIED");
      res.status(200).send(challenge);
    } else {
      // Respond with '403 Forbidden' if verify tokens do not match
      res.sendStatus(403);
    }
  }
});
参数示例值描述

hub.mode

subscribe

始终将此值设置为 subscribe

hub.challenge

1158201444

您必须传回给我们的 int

hub.verify_token

mytoken

从您应用的应用面板中的验证口令字段获取的字符串。您将在完成 Webhooks 配置设置步骤时设置此字符串。

注意:PHP 会将参数名称中的句点 (.) 转换为下划线 (_)

如果您在应用面板中配置 Webhooks 产品(并因此触发了验证请求),则面板会显示您的端点是否正确验证了请求。如果您使用图谱 API 的 /app/subscriptions 端点配置 Webhooks 产品,则该 API 会在响应中提示配置成功与否。

事件通知

配置 Webhooks 产品时,您将订阅某个 object 类型的特定 fields(例如,page 对象的 messages 字段)。每当其中某个字段有所更改,我们都会向您的端点发送一个 POST 请求,其中包括描述更改的 JSON 负载。

例如,如果您已订阅 page 对象的 message_reactions 字段,并且某客户已对应用发送的消息留下心情,我们会向您发送如下 POST 请求:

{
  "object":"page",
  "entry":[
    {
      "id":"<PAGE_ID>",
      "time":1458692752478,
      "messaging":[
        {
          "sender":{
            "id":"<PSID>"
          },
          "recipient":{
            "id":"<PAGE_ID>"
          },

          ...
        }
      ]
    }
  ]
}

负载内容

负载会包含描述更改的对象。配置 Webhooks 产品时,您可以指明负载应该仅包含已更改字段的名称,还是也应包含新值。

我们使用 JSON 格式化所有负载,因此您可以使用常见的 JSON 解析方法或解析包来解析负载。

我们不会存储发送给您的任何 Webhooks 事件通知数据,所以请务必获取并存储您想保留的任何负载内容。

验证负载

我们使用 SHA256 签名来签署所有事件通知负载,并在请求的 X-Hub-Signature-256 标头中添加签名,接着在前面加上“sha256=”。验证负载并非强制要求,但您应该执行此操作,并且我们强烈建议您这样做。

如要验证负载,请执行以下操作:

  1. 使用负载和您应用的应用密钥生成 SHA256 签名。
  2. 将您的签名与 X-Hub-Signature-256 标头中的签名(sha256= 之后的所有内容)进行对比。如果签名一致,则表示负载真实有效。

请注意,我们会使用负载的转义 Unicode 版本生成签名,并以小写十六进制数字表示。如果您仅根据已解码字节计算,则会产生不同的签名。例如,字符串 äöå 应转义为 \u00e4\u00f6\u00e5

app.js 文件可能如以下所示:

// Import dependencies and set up http server
const express = require("express"),
  bodyParser = require("body-parser"),
  { urlencoded, json } = require("body-parser"),
  app = express().use(bodyParser.json());
    
    ...


// Verify that the callback came from Facebook.
function verifyRequestSignature(req, res, buf) {
  var signature = req.headers["x-hub-signature-256"];

  if (!signature) {
    console.warn(`Couldn't find "x-hub-signature-256" in headers.`);
  } else {
    var elements = signature.split("=");
    var signatureHash = elements[1];
    var expectedHash = crypto
      .createHmac("sha256", config.appSecret)
      .update(buf)
      .digest("hex");
    if (signatureHash != expectedHash) {
      throw new Error("Couldn't validate the request signature.");
    }
  }
}

Webhooks 送达重试

如果向服务器发送的通知失败,我们将立即进行多次尝试。在这类情况下,您的服务器应处理去重操作。如果通知在 15 分钟后仍无法送达,系统会向您的开发者账户发送相关提醒。

如果通知在 1 小时后仍无法送达,您将收到 Webhooks 已禁用提醒,并且系统将取消您的应用对此公共主页或 Instagram 专业账户的 Webhooks 的订阅。在修复这些问题后,您需要重新订阅 Webhooks。

测试 Webhooks

要测试 Webhooks 验证,请使用您的验证口令运行以下 cURL 请求:

curl -X GET "localhost:1337/webhook?hub.verify_token=YOUR-VERIFY-TOKEN&hub.challenge=CHALLENGE_ACCEPTED&hub.mode=subscribe"

如果 Webhooks 验证按预期运行,您应该会看到以下结果:

  • 系统会将 WEBHOOK_VERIFIED 记录到节点进程运行所在的命令行中。
  • 系统会将 CHALLENGE_ACCEPTED 记录到发送 cURL 请求的命令行中。

要测试 Webhooks,请发送以下 cURL 请求:

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

如果 Webhooks 按预期运行,您应该会看到以下结果:

  • 系统会将 TEST_MESSAGE 记录到节点进程运行所在的命令行中。
  • 系统会将 EVENT RECEIVED 记录到发送 cURL 请求的命令行中。

订阅 Meta Webhooks

在您的 Webhooks 服务器端点或示例应用准备就绪后,请前往应用的应用面板 订阅 Meta Webhooks。

在本例中,我们将使用面板配置 Webhooks,并订阅 messages 字段。每当客户向您的应用发送消息时,系统就会向您的 Webhooks 端点发送通知。

  1. 在应用面板中,进入产品 > Messenger > 设置
    • Instagram 消息功能不支持某些 Messenger 开放平台 Webhooks。如果您仅需要集成 Instagram 专用 Webhooks,并且了解适用于 Instagram 消息功能的 Webhooks,可以在此处订阅 Webhooks。如仅需查看和订阅适用于 Instagram 消息功能的 Webhooks,可前往 Instagram 设置
  2. 回调网址字段中输入端点的网址,并在验证口令字段中添加验证口令。我们会在所有验证请求中加入此字符串。如果您使用其中一个示例应用,则此字符串应该与您在应用的 TOKEN 配置变量中使用的字符串相同。

  3. 订阅系统发送通知所针对的相应字段,然后点击保存
  4. 最后一步是订阅各个字段。订阅 messages 字段并发送测试事件通知。

    如果您的端点设置正确,则其应验证负载,并在验证成功后执行您为其设置的任何代码。如果您在使用我们的示例应用,请在网页浏览器中加载应用网址。页面应该会显示负载内容。

您可使用应用面板随时更改 Webhooks 订阅,验证口令或 API 版本。

注意:建议您使用最新版 API 来接收每个 Webhooks 的所有可用信息。

您也可以使用/app/subscriptions 端点 以编程方式执行此操作。

可用的 Messenger 开放平台字段

Webhook 事件说明

messages

订阅消息接收事件

messaging_account_linking

订阅帐户绑定事件

messaging_checkout_updates(公测版)

订阅结账更新事件

message_deliveries

订阅消息送达事件

message_echoes

订阅消息回传事件

messaging_game_plays

订阅小游戏事件

messaging_handovers(公测版)

订阅移交协议事件

messaging_optins

订阅插件选择加入事件

messaging_payments(公测版)

订阅支付事件

messaging_policy_enforcement

订阅政策执行事件

messaging_postbacks

订阅回传接收事件

messaging_pre_checkouts(公测版)

订阅支付预结账事件

message_reads

订阅消息读取事件

messaging_referrals

订阅推荐来源事件

standby(公测版)

订阅移交协议备用通道事件

关联应用

您需要关联 Webhooks 应用与您的公共主页,并为您的公共主页订阅想要接收的 Webhooks 通知。

添加应用

您可以在Meta Business Suite > 所有工具 > 业务应用 中关联应用与公共主页

注意:您需要为企业的所有消息应用订阅消息 Webhooks。

为公共主页订阅 Webhooks 通知

您需要为您的公共主页订阅想要接收的 Webhooks 通知。

要求

若要订阅 Webhooks 字段,请使用公共主页的访问口令向公共主页的 subscribed_apps 连线发送 POST 请求。

curl -i -X POST "https://graph.facebook.com/PAGE-ID/subscribed_apps
  ?subscribed_fields=messages
  &access_token=PAGE-ACCESS-TOKEN"

响应示例

{
  "success": "true"
}

要查看您的公共主页安装了哪款应用,请改为发送 GET 请求:

请求示例

curl -i -X GET "https://graph.facebook.com/PAGE-ID/subscribed_apps
  &access_token=PAGE-ACCESS-TOKEN"

响应示例

{
  "data": [
    {
      "category": "Business",
      "link": "https://my-clever-domain-name.com/app",
      "name": "My Sample App",
      "id": "APP-ID"
      "subscribed_fields": [
        "messages"
      ]
    }
  ]
}

如果您的公共主页未安装任何应用,API 将返回空数据集。

图谱 API 探索工具

您也可以使用图谱 API 探索工具 发送请求,为您的公共主页订阅某个 Webhooks 字段。

  1. 应用程序下拉菜单中选择您的应用。
  2. 点击获取口令下拉菜单,选择获取用户访问口令,然后选择 pages_manage_metadata 权限。此操作会将您的应用口令与授予 pages_manage_metadata 权限的用户访问口令互换。
  3. 再次点击获取口令,然后选择您的公共主页。此操作会将您的用户访问口令换为公共主页访问口令。
  4. 点击 GET 下拉菜单,然后选择 POST,即可更改操作方式。
  5. 将默认 me?fields=id,name 查询替换为公共主页的编号,在此编号之后输入 /subscribed_apps,然后提交查询。

访问要求

如要接收拥有应用身份的用户(如应用管理员、开发者和测试者)发出的通知,您的应用仅需要标准访问权限。如要接收客户(即没有应用身份的用户)发出的通知,您的应用需要高级访问权限

详细了解标准访问级别和高级访问级别 、使用各级别访问权限可以访问的数据,以及实现要求。

后续步骤

  • 发送测试消息 — 了解如何使用该开放平台发送消息。
  • 浏览我们的样本应用 — 下载样本应用的代码,详细了解 Messenger 开放平台提供的各种功能。
  • 另请参阅