文档已更新。
中文(简体) 译文尚未完成。
英语更新时间:4月16日

授权预览

概览

授权预览可以让您的内容预览正确显示在 Workplace 上。这需要为采用 Workplace 预期格式的授权预览元数据提供支持,使 Workplace 可以在用户分享您的内容网址时获取对应元数据并创建预览。此过程通常被称为链接预览

虽然 Facebook 能够通过开放图谱协议和 Facebook 网络爬虫获取元数据来预览公共网址,但是此流程不适用于专用网址,通常情况下,用户与 Workplace 分享的多为专用网址。与公共网址不同,在有用户将专用网址分享到 Workplace 时,系统会向您定义的回调网址发送 Webhooks,然后您就可以在响应中为这位分享专用网址的用户提供描述该网址的元数据有效负载,以便显示链接预览。

此流程会针对在 Workplace 上查看该分享网址的每位用户重复执行,使您可以控制每位用户的预览可见性。

授权在 Workplace 平台分享使用户能够在符合资料来源隐私设置的情况下,安全、轻松地在 Workplace 上分享信息。通过支持授权预览,您可以确保自己的内容预览以安全而又符合隐私设置的方式正确显示在 Workplace 上。

分享专用网址

在 Workplace 上,用户通常分享公司内部资源的链接,这些链接应该只有某些用户才可以查看。Facebook 与其相反。在 Facebook 上,用户通常分享的是公共内容,如新闻报道或博文。

Workplace 上的公共网址和专用网址

如需让 Workplace 生成公司专用内容的预览,需要提供一些元数据。作为提供方,您可以根据当前 Workplace 上的浏览者是否有权查看元数据,来选择是否为其提供此内容。

本文内容

本文概述了启用授权预览所涉及的不同部分,其中包括:

配置

如要启用授权预览,您需要为您的应用配置以下内容:

  • 在 Workplace 社群上或一个或多个小组中安装您的应用
  • 链接预览权限
  • 一个网域或一组网域,包含将由您的集成预览的网址
  • Webhooks 主题链接的订阅(用于字段预览)和一个回调网址(用于提供元数据)

Webhooks

接收 Webhooks

在以下情况下,我们会向提供方发送请求:

  1. 分享的新网址我们从未见过(总是来自编辑器)。
  2. 新用户看到了一项内容,而我们不知道此用户是否有查看的权限(总是来自动态)。
  3. 现有的一项内容被重新分享或已过期(来自编辑器或动态)。

Webhooks 请求格式

在上述任何一种情况下,系统都会以 POST 请求的形式发送 Webhooks,格式如下:

{
  "object": "link",
  "entry": [
    {
      "time": int,
      "changes": [
        {
          "field": "preview",
          "value": {
            "community": {
              "id": string,
            },
            "user": {
              "id": string,
            },
            "link": string,
          }
        }
      ]
    }
  ]
}
    

有效负载将包含以下字段:

字段名称描述

object

Webhooks 主题。在本文中,该主题始终是 link

entry

一份请求清单,始终只能有一份。

entry.time

请求发送的时间。

entry.changes

请求中的一份变更清单,始终只能有一份。

entry.changes.field

Webhooks 字段,始终是 preview

entry.changes.value

包含请求背景的实际对象。

entry.changes.value.field.community

触发请求的用户所在的社群。

entry.changes.value.field.user

触发请求的用户。

entry.changes.value.field.link

Workplace 试图显示的链接,应与应用所配置的网域和正则表达式一致。

示例

POST /callback HTTP/1.1
Host: third-party.com
Accept: application/json
Content-Type: application/json
User-Agent: Webhooks/1.0 (https://fb.me/webhooks)
X-Hub-Signature: sha1=bf3102e52efd0fd4bd26277030aa180d7b5cf587
...

{
    "object": "link",
    "entry": [{
        "time": 1501515097793,
        "changes": [{
            "field": "preview",
            "value": {
                "community": {
                    "id": "138169208138649"
                },
                "user": {
                    "id": "88575656148087"
                }
                "link": "https://company.third-party.com/document-about-this"
            }
        }]
    }]
}
    

Webhooks 响应格式

收到 Webhooks 请求时,您将需要以特定响应格式提供元数据有效负载:

{
  "data": [
    {
      "link": string,
      ?"canonical_link": string,
      ?"title": string,
      ?"description": string,
      ?"icon": string,
      ?"download_url": string,
      "privacy": 'organization' | 'accessible' | 'inaccessible',
      ?"type": 'document' | 'folder' | 'task' | 'link',
      ?"additional_data": [
        {
          "title" => string,
          "format" => 'text' | 'date' | 'datetime' | 'user',
          "value" => string | number,
          ?"color" => 'blue' | 'green' | 'yellow' | 'orange' | 'red',
        },
      ],
    }
  ],
  ?"linked_user": boolean
}

有效负载预计将包含以下字段:

字段名称描述

data

用户可获取的数据项集合。如果应用选择不为此用户预览链接,此字段可留空。

linked_user

一个布尔值字段,指示第三方是否知道相关用户。如果此字段设为 false,我们将显示一个链接对话框。

data.link

此数据项的唯一识别链接,必须与请求中的链接一致。

data.canonical_link

内容的一种权威网址表示形式。如果与识别链接不同,内容将与权威内容关联,以便更轻松地查询相关分享。

data.title

数据项的标题,是必要项(隐私设为不可访问的数据项除外)。

data.description

对将在图文预览中显示的数据项的简短描述。

data.icon

内容的一个素材,将放在 Workplace 显示内容图标的位置。必须是一个可公开访问的网址。为获得最佳效果,素材应为 16px 的正方形。

data.download_url

一个网址,可供 Workplace 下载 PDF、JPEG 或 PNG 版本的数据项,以将其转换为图片帖子。除了 documentlink,任何对象类型都可忽略此字段。

data.privacy

表示对象的隐私设置。值可以是 organizationaccessibleinaccessible。如果值是 organization,Workplace 会认为该项目可以向社群中的任何用户显示(即使在未绑定账户的情况下);accessible 表示已登录用户可以获取数据项,但其他任何用户不一定可以获取;inaccessible 表示当前用户无法获取此文档。

data.type

值可以是 documentfoldertasklink。文件夹是多个其他文件夹或文档的集合。是必要项(privacy 设为 inaccessible 的数据项除外)。

data.additional_data

将在图文预览中显示的元数据的集合。对于 documentfolder 将被忽略。仅会使用前三个元素。有关这些字段格式的详情,请参阅更多数据部分。

完整响应示例

HTTP/1.1 200 OK
Content-Type: application/json
X-Hub-Signature: sha1=b5a6f32f084100ae5b355174b9bb8398f5fbe983
...

{
  "data": [
    {
      "link": "https://taaskly.herokuapp.com/task/4",
      "title": "Launch Workplace Integration for F8",
      "privacy": "organization",
      "type": "task",
      "additional_data": [
        {
          "title": "Owner",
          "format": "user",
          "value": "319922278498384"
        },
        {
          "title": "Created",
          "format": "datetime",
          "value": "2018-02-28T03:35:40.827Z"
        },
        {
          "title": "Priority",
          "format": "text",
          "value": "high",
          "color": "red"
        }
      ]
    }
  ],
  "linked_user": true
}
    

隐私模式

隐私模式决定了可见性以及我们是否需要对当前和后续用户进行用户授权。

  1. organization:对用户可见、无需用户授权
    如果某项内容对用户可见,我们可以直接显示此内容。适用于以下情况:某项内容应该对某网域(公司)中的任何用户可见。每次新用户看到该新内容时,我们都不会发送 Webhooks。
  2. accessible:对当前用户可见;对于其他用户,可能需要进行用户身份映射
    提供方知道此特定用户有权查看这项内容,但这并不表示任何其他用户都能看到此内容。我们会显示预览,但对任何其他用户,则会继续发送 Webhooks。
  3. inaccessible:对用户不可见
    提供方知道当前用户以及该用户无权查看这项内容。我们会显示一项隐私声明(表示内容无法访问、是隐私内容等)。

更多数据

如要在链接预览上添加更多信息,最多可再发送个数据项。附加数据项由一组键值元素组成。但是,值可以采用不同的格式。

目前支持四种不同格式:

  • text:将按原样显示值,此值必须是一个字符串。对于这种格式,附加数据还可以包含一个属性 color,该属性必须使用以下值之一:bluegreenyelloworangered。如果提供此属性,显示值时会以指定颜色为背景。
  • date:将该值解析为不含时间的 ISO-8601 日期格式,并在不含时间指示的情况下显示值。
  • datetime:将值解析为含时间和时区的 ISO-8601 日期格式,并在含时间指示(在用户所在时区中)的情况下显示值。
  • user:将值解析为用户编号,并显示用户的姓名。

如果设置了更多数据,download_url 参数将被忽略。

显示文件预览(可选)

如果您文档的隐私模式标记为 organizationaccessible,且提供了下载网址,我们会再发送一个请求,以下载数据。

GET /download/super-fancy-document HTTP/1.1
Host: provider.com
Accept: <some mime types>
User-Agent: Webhooks/1.0 (https://fb.me/webhooks)
X-Hub-Signature: sha1=bf3102e52efd0fd4bd26277030aa180d7b5cf587

然后,Workplace 会获取此文件,并将其转换为多张照片,以创作一个多照片帖子。

身份映射

如上所示,提供授权预览需要一定的身份映射。身份映射可控制 Workplace 用户是否有权查看内容预览,并确保在 Workplace 上遵守您内容的访问规则。

全组织映射

最简单的身份映射形式是全组织映射。在这种映射中,具有一个 Workplace 社群的成员资格就足以允许向 Workplace 上的用户显示预览。这在以下情况中很常见:在预览全公司内部网络的链接时,或预览所有对象(或至少其元数据)对整个公司可见的任何服务时。

在将您的集成安装到 Workplace 社群后,您可以使用安装时检索到的访问口令通过 /community 端点查看社群编号。您可以将此社群编号与口令一起存储,并将此编号映射到您服务中的租户或组织标识符。这会在 Workplace 社群与您服务中的组织之间创建映射。

然后,在响应授权预览 Webhooks 请求时,您可以检查 Webhooks 有效负载的社群编号是否与该组织绑定的社群编号一致,然后确定返回元数据有效负载是否安全。将此有效负载的隐私标记为“ORGANIZATION”,可确保我们无需为该 Workplace 社群中的每个用户都额外发送 Webhooks。

单个用户映射

如需深度细化权限,您可以提供单个用户映射支持,确保您可以选择是否单独向 Workplace 上的每个浏览者都显示元数据。对于授权预览,Workplace 在每个 Webhooks 有效负载中都会发送一个用户编号。如要支持单个用户映射,您需要知道自己系统中的哪份用户记录与 Webhooks 有效负载中发送的某个 Workplace 用户编号匹配。

如果您是第一次为某个指定 Workplace 用户编号寻找匹配的用户记录,可在响应中提供布尔值字段 linked_user,并将其设为 false。这会指示 Workplace 显示启用预览按钮,用于提示用户绑定其账户。

用户按下此按钮后,Workplace 会打开一个对话框。该对话框用于前往您定义的一个账户绑定端点,您可以在此端点处验证服务中的用户会话。Workplace 将通过 POST 请求打开此网址,并传递一个已签名请求参数,其中包含当前用户编号和社群编号。

POST https://www.example.com/account_linking?redirect_uri=https%3A%2F%2Ffoxfabrics.facebook.com%2Flink_complete HTTP/1.1
Host: foxfabrics.third-party.com
Origin: http://www.facebook.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/57.0
...

signed_request=238fsdfsd.oijdoifjsidf899
    

有效负载中有一个参数 signed_request,其中包含此用户的相关信息。可按以下方式解码请求:

  1. 使用“.”字符将请求内容分为两个部分。
  2. 解码经过 base64url 编码的第一部分,即签名
  3. 解码经过 base64url 编码的第二部分,即有效负载,然后解码所得的 JSON 对象。
  4. 根据您的应用密钥,确认签名与已编码有效负载的 HMAC 一致。

有效负载将包含以下字段:

{
  "algorithm": "HMAC-SHA256",
  "user_id": "88575656148087",
  "community_id": "138169208138649"
}
    

这时,您将获得一个 Workplace 用户编号和社群编号,以及您服务中一个经过验证的用户会话。您可以在此用户在您服务中的编号旁边记录此用户的 Workplace 编号。完成后,您应该会跳转到原始请求中作为查询参数 redirect_uri 提供的网址。

GET {$redirect_uri} HTTP/1.1
Host: foxfabrics.facebook.com
User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/57.0
Referer: https://www.example.com/account_linking
...
    

然后,Workplace 将了解到身份映射已完成,从而尝试再次请求获取授权预览元数据。这次,您将能够在响应中提供 linked_user(设为 true),并提供所需的元数据。

备注:

整个往返过程应该仅在每次有陌生用户首次尝试预览一项内容时,才发生一次。身份映射完成后,后续预览应该能跳过这一过程。

常见问题

No, Workplace Authenticated Previews do not have the same performance requirements or unsubscribe behavior as Messenger Platform webhooks.

So that people using Workplace have a good experience, the full HTTP roundtrip should take less than 5 seconds as measured from the Workplace side (i.e., the HTTP client side).

For estimating / expectation standpoint you can plan around this behavior. You may observe some differences in practice due to retries or race conditions.

I. When a Person Views Organization-Privacy Content

  1. Workplace sends a webhook request when first person views this content
  2. Generally, no further webhooks requests will be sent for this same content until 30-60 minutes has elapsed

II. When a Person Views Restricted- or Inaccessible-Privacy Content

  1. Workplace sends a webhook request every time a person views that content for the first time
  2. Generally, no further webhook requests will be sent for this same person+content combination until 30-60 minutes has elapsed

III. When a Person Creates a Post That Links to Content

  1. Every time a person creates a new post Workplace will always query for metadata about linked content.

No, Workplace will not automatically disable a link webhooks subscription.