使用 Microsoft Graph 获取 Teams 频道和聊天中消息的更改通知

更改通知使你能够订阅频道或聊天中消息的更改(创建、更新和删除)。 更改通知允许你维护订阅,从而提供低延迟模式。 你还可以在通知中获取资源数据,因此避免调用 API 来获取有效负载。

继续阅读本文,了解频道聊天上下文中 chatMessage 资源的方案。 或者,了解 其他 Microsoft Teams 资源的更改通知

注意

如果请求的订阅 expirationDateTime 在未来超过 1 小时,则必须通过在订阅请求中包含 lifecycleNotificationUrl 属性来订阅生命周期通知。 否则,订阅请求将失败并显示以下错误消息: 当 expirationDateTime 值设置为大于 1 小时时,lifecycleNotificationUrl 是在此资源上创建订阅所需的属性

订阅租户级别的更改

若要跟踪租户中与消息相关的所有更改,可以在租户级别对频道和聊天消息使用订阅,创建两个订阅:一个订阅用于跟踪跨 通道的所有消息,一个用于跟踪 跨聊天的所有消息。

跨频道订阅消息

若要在租户中跨频道获取所有消息和答复的更改通知,请订阅 /teams/getAllMessages。 此资源支持在通知中包括资源数据

注意:此 API 具有许可和付款要求。 它支持 model=Amodel=B查询参数。 如果未指定模型,将使用评估模式

权限

权限类型 权限(从最低特权到最高特权)
委派(工作或学校帐户) 不支持。
委派(个人 Microsoft 帐户) 不支持。
应用程序 ChannelMessage.Read.All

示例

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/getAllMessages",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

跨聊天订阅消息

若要跨租户中的聊天获取所有消息的更改通知,请订阅 /chats/getAllMessages。 此资源支持在通知中包括资源数据

注意:此 API 具有许可和付款要求。 它支持 model=Amodel=B查询参数。 如果未指定模型,将使用评估模式

权限

权限类型 权限(从最低特权到最高特权)
委派(工作或学校帐户) 不支持。
委派(个人 Microsoft 帐户) 不支持。
应用程序 Chat.Read.All

示例

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated,deleted",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/chats/getAllMessages",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

订阅频道中的消息

若要跟踪频道中的消息和答复,可以通过订阅 /teams/{team-id}/channels/{channel-id}/messages在频道级别创建更改通知订阅。 不管是在委派模式还是仅应用程序模式下,此资源都支持在通知中包含资源数据

频道级别订阅还支持通过 $search 查询参数进行基于关键字的搜索。

权限

权限类型 权限(从最低特权到最高特权)
委派(工作或学校帐户) ChannelMessage.Read.All
委派(个人 Microsoft 帐户) 不支持。
应用程序 ChannelMessage.Read.Group*、ChannelMessage.Read.All

注意: 带有 * 标记的权限作为 资源特定的许可 的一部分受到支持。

示例 1:订阅频道中的所有消息(和回复)

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/{team-id}/channels/{channel-id}/messages",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

示例 2:订阅频道中包含特定文本的消息(和回复)

以下请求将包含 Hello 的消息发送到订阅服务器。

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/{team-id}/channels/{channel-id}/messages?$search=Hello",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

示例 3:订阅频道中的消息(和回复),不含资源数据

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/{team-id}/channels/{channel-id}/messages",
  "includeResourceData": false,
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

示例 4:订阅频道中提到特定用户的消息(和回复)

要仅获得提到特定用户的消息,你可以在查询中指定用户的 ID(在此示例中为 9a6eb4d1-826b-48b1-9627-b50836c8fee9)。

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/{team-id}/channels/{channel-id}/messages?$filter=mentions/any(u: u/mentioned/user/id eq '9a6eb4d1-826b-48b1-9627-b50836c8fee9')",
  "includeResourceData": false,
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

订阅聊天中的消息

若要跟踪聊天中的消息,可以通过订阅 /chats/{chat-id}/messages在聊天级别创建更改通知订阅。 不管是在委派模式还是仅应用程序模式下,此资源都支持在通知中包含资源数据

聊天级别订阅还支持通过 $search 查询参数进行基于关键字的搜索。

权限

权限类型 权限(从最低特权到最高特权)
委派(工作或学校帐户) Chat.Read
委派(个人 Microsoft 帐户) 不支持。
应用程序 ChatMessage.Read.Chat*、Chat.Read.All

注意: 带有标记 * 的权限当前仅作为 beta 版本的特定于 资源的许可 的一部分受到支持。

示例 1:订阅聊天中的消息

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/chats/{chat-id}/messages",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

示例 2:订阅聊天中包含特定文本的消息

以下请求将包含 Hello 的消息发送到订阅服务器。

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/chats/{chat-id}/messages?$search=Hello",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

示例 3:订阅聊天中的消息(和回复),不含资源数据

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json
{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/chats/{chat-id}/messages",
  "includeResourceData": false,
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

示例 4:订阅聊天中提到特定用户的消息

要仅获得提到特定用户的消息,你可以在查询中指定用户的 ID(在此示例中为 9a6eb4d1-826b-48b1-9627-b50836c8fee9)。

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/chats/{chat-id}/messages?$filter=mentions/any(u: u/mentioned/user/id eq '9a6eb4d1-826b-48b1-9627-b50836c8fee9')",
  "includeResourceData": false,
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

订阅用户级别的更改

若要跟踪特定用户所属的所有聊天中的消息,可以通过订阅 /users/{user-id}/chats/getAllMessages在用户级别创建更改通知订阅。 不管是在委派模式还是仅应用程序模式下,此资源都支持在通知中包含资源数据

用户级别聊天的消息传递订阅还支持通过 $search 查询参数进行基于关键字的搜索。

注意:此 API 具有许可和付款要求。 它支持 model=B 查询参数。 如果未指定模型,将使用评估模式

权限

权限类型 权限(从最低特权到最高特权)
委派(工作或学校帐户) Chat.Read、Chat.ReadWrite
委派(个人 Microsoft 帐户) 不支持。
应用程序 Chat.Read.All、Chat.ReadWrite.All

示例:订阅特定用户参与的所有聊天中的消息

POST https://graph.microsoft.com/beta/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated,deleted",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/users/{user-id}/chats/getAllMessages",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

订阅安装了特定 Teams 应用的租户中任何聊天的消息

若要在安装了特定 Teams 应用的租户中跨聊天获取所有消息的更改通知,请 /appCatalogs/teamsApps/{teams-app-id}/installedToChats/getAllMessages订阅 。 此资源支持在通知中包括资源数据

注意:此 API 具有许可和付款要求。 它支持 model=B 查询参数。 如果未指定模型,将使用评估模式

权限

权限类型 权限(从最低特权到最高特权)
委派(工作或学校帐户) 不支持。
委派(个人 Microsoft 帐户) 不支持。
应用程序 Chat.Read.WhereInstalled、Chat.ReadWrite.WhereInstalled

示例

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/appCatalogs/teamsApps/386bbcdb-1e1c-4f3f-b7d0-ad7b9ea6cf7c/installedToChats/getAllMessages",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

通知负载

根据你的订阅,你可以获取包含或不含资源数据的通知。 通过订阅资源数据,你将在收到通知的同时获得消息负载,而无需回调并获取内容。

包含资源数据的通知

对于包含资源数据的通知,负载如下所示。 此负载适用于在聊天中发送的消息。

{
    "value": [{
        "subscriptionId": "10493aa0-4d29-4df5-bc0c-ef742cc6cd7f",
        "changeType": "created",
        "clientState": "<<--SpecifiedClientState-->>",
        "subscriptionExpirationDateTime": "2021-02-02T10:30:34.9097561-08:00",
        "resource": "chats('19:8ea0e38b-efb3-4757-924a-5f94061cf8c2_97f62344-57dc-409c-88ad-c4af14158ff5@unq.gbl.spaces')/messages('1612289765949')",
        "resourceData": {
            "id": "1612289765949",
            "@odata.type": "#Microsoft.Graph.chatMessage",
            "@odata.id": "chats('19:8ea0e38b-efb3-4757-924a-5f94061cf8c2_97f62344-57dc-409c-88ad-c4af14158ff5@unq.gbl.spaces')/messages('1612289765949')"
        },
        "encryptedContent": {
            "data": "<<--EncryptedContent-->",
            "dataKey": "<<--EnryptedDataKeyUsedForEncryptingContent-->>",
            "encryptionCertificateId": "<<--IdOfTheCertificateUsedForEncryptingDataKey-->>",
            "encryptionCertificateThumbprint": "<<--ThumbprintOfTheCertificateUsedForEncryptingDataKey-->>"
        },
        "tenantId": "<<--TenantForWhichNotificationWasSent-->>"
    }],
    "validationTokens": ["<<--ValidationTokens-->>"]
}

有关如何验证令牌和解密负载的详细信息,请参阅设置包含资源数据的更改通知

解密的通知负载如下所示。 该负载符合 chatMessage 架构。 该负载类似于 GET 操作返回的负载。

{
  "id": "1612289992105",
  "replyToId": null,
  "etag": "1612289992105",
  "messageType": "message",
  "createdDateTime": "2021-02-02T18:19:52Z",
  "lastModifiedDateTime": "2021-02-02T18:19:52.105Z",
  "lastEditedDateTime": null,
  "deletedDateTime": null,
  "subject": null,
  "summary": null,
  "chatId": "19:8ea0e38b-efb3-4757-924a-5f94061cf8c2_97f62344-57dc-409c-88ad-c4af14158ff5@unq.gbl.spaces",
  "importance": "normal",
  "locale": "en-us",
  "webUrl": null,
  "from": {
    "application": null,
    "device": null,
    "user": {
      "id": "8ea0e38b-efb3-4757-924a-5f94061cf8c2",
      "displayName": "Ramjot Singh",
      "userIdentityType": "aadUser"
    },
    "conversation": null
  },
  "body": {
    "contentType": "text",
    "content": "test"
  },
  "channelIdentity": null,
  "attachments": [],
  "mentions": [],
  "policyViolation": null,
  "reactions": [],
  "replies": [],
  "hostedContents": []
}

不含资源数据的通知

不含资源数据的通知为你提供了足够的信息来进行 GET 调用以获取消息内容。 没有资源数据的通知订阅不需要加密证书 (,因为实际资源数据不会通过) 发送。

该负载如下所示。 此负载适用于在频道中发送的消息。

 {
  "subscriptionId": "9f9d1ed0-c9cc-42e7-8d80-a7fc4b0cda3c",
  "changeType": "created",
  "tenantId": "<<--TenantForWhichNotificationWasSent-->>",
  "clientState": "<<--SpecifiedClientState-->>",
  "subscriptionExpirationDateTime": "2021-02-02T11:26:41.0537895-08:00",
  "resource": "teams('fbe2bf47-16c8-47cf-b4a5-4b9b187c508b')/channels('19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2')/messages('1612293113399')",
  "resourceData": {
    "id": "1612293113399",
    "@odata.type": "#Microsoft.Graph.chatMessage",
    "@odata.id": "teams('fbe2bf47-16c8-47cf-b4a5-4b9b187c508b')/channels('19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2')/messages('1612293113399')"
  }
}

resource@odata.id 属性可用于对 Microsoft Graph 进行调用以获取消息负载。 GET 调用始终返回消息的当前状态。 如果在发送通知和检索消息之间更改了消息,则操作将返回更新的消息。