Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie Sie die Microsoft Teams-Umgebung in Ihre Anwendung einbetten. Wenn Sie Teams in Ihre App einbetten, können Ihre Benutzer Teams-Nachrichten direkt aus Ihrer App lesen und senden, ohne zwischen Ihrer App und Teams wechseln zu müssen.
Um die Antwortzeit Ihrer App zu verbessern und die Kosten zu senken, sollten Sie die Anzahl der Lesevorgänge einer Nachricht aus Microsoft Graph minimieren. In diesem Artikel wird erläutert, wie Sie Nachrichten einmal abrufen und zwischenspeichern und dann Änderungsbenachrichtigungen verwenden, um nur die nachfolgenden Nachrichten abzurufen.
Schritt 1: Entwerfen und Einrichten der Architektur
Das folgende Diagramm zeigt die vorgeschlagene allgemeine Architektur für eine App, die in Teams integriert werden kann.
Die Architektur umfasst drei Komponenten:
Eine Chat-Benutzeroberfläche , die Benutzereingaben abruft und Nachrichten anzeigt. Die Chat-Benutzeroberfläche sendet API-Anforderungen (z
POST
/GET
. B. Chats,POST
/GET
Nachrichten) an Teams-APIs. Außerdem werden neue Nachrichten in Echtzeit von der Serverkomponente abgerufen.Eine Serverkomponente , die Änderungsbenachrichtigungen in Echtzeit abonniert, um neue Nachrichten von Teams-APIs zu erhalten. Wenn Teams-APIs Änderungsbenachrichtigungen senden, ist eine Webhook-URL erforderlich, um die Änderungsbenachrichtigungen zu überwachen, und Ihre Benutzeroberfläche, z. B. das Mobiltelefon der Benutzer, enthält möglicherweise keine Webhook-URL. Die Serverkomponente verfügt jedoch über eine stabile Webhook-URL. Die neuen Nachrichten werden dann mithilfe von Kommunikationsmethoden wie ASP.NET SignalR von der Serverkomponente auf die Chat-Benutzeroberfläche gepusht.
Hinweis
Sie können sich auch dafür entscheiden, die Serverkomponente anstelle der Chat-Benutzeroberfläche zu verwenden, alle API-Anforderungen an Teams-APIs zu senden und alle Nachrichten zwischenzuspeichern. Wenn Sie beispielsweise über eine andere Back-End-Systemkomponente verfügen, die ebenfalls API-Anforderungen stellen muss, z. B. für Compliance und Überwachung, können Sie stattdessen die API-Anforderungen und die Zwischenspeicherung für die Serverkomponente zentralisieren.
Ein Cache , der Nachrichten speichert. Um die Antwortzeit für Ihre Anwendung zu verbessern und die Kosten für Sie zu senken, minimieren Sie das mehrfache Lesen derselben Nachricht, indem Sie Nachrichten in diesem Cache speichern. Sie möchten sich später nicht über die Gebühren für den API-Verbrauch wundern. Informationen zum Einrichten eines Caches finden Sie unter Hinzufügen von Zwischenspeicherung zur Verbesserung der Leistung in Azure API Management.
Für einige Teams-APIs gelten Lizenzierungs- und Zahlungsanforderungen. Ausführliche Informationen finden Sie unter Zahlungsmodelle und Lizenzierungsanforderungen .
Nachdem Sie diese Komponenten eingerichtet haben, können Sie mit der Verwendung von Teams-APIs beginnen.
Schritt 2: Erstellen eines neuen Chats
Bevor Sie eine neue chatMessage senden, müssen Sie einen Chat erstellen, indem Sie Mitglieder zuweisen. Das folgende Beispiel zeigt, wie Sie einen Gruppenchat erstellen. Weitere Beispiele zum Erstellen verschiedener Chattypen finden Sie unter Erstellen eines Chats.
Anforderung
POST https://graph.microsoft.com/v1.0/chats
Content-Type: application/json
{
"chatType": "group",
"members": [
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": [
"owner"
],
"user@odata.bind": "https://graph.microsoft.com/v1.0/users('adams@contoso.com')"
},
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": [
"owner"
],
"user@odata.bind": "https://graph.microsoft.com/v1.0/users('gradyA@contoso.com')"
},
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": [
"owner"
],
"user@odata.bind": "https://graph.microsoft.com/v1.0/users('4562bcc8-c436-4f95-b7c0-4f8ce89dca5e')"
}
]
}
Antwort
HTTP/1.1 201 Created
Content-Type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#chats/$entity",
"id": "19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2",
"topic": null,
"createdDateTime": "2023-01-11T01:34:18.929Z",
"lastUpdatedDateTime": "2023-01-11T01:34:18.929Z",
"chatType": "group",
"webUrl": "https://teams.microsoft.com/l/chat/19%3Ab1234aaa12345a123aa12aa12aaaa1a9%40thread.v2/0?tenantId=4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1",
"tenantId": "4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1",
"viewpoint": null,
"onlineMeetingInfo": null
}
Schritt 3: Senden einer Nachricht im Chat
Mitglieder innerhalb des Chats können nachrichten aneinander senden. Das folgende Beispiel zeigt, wie eine einfache Nachricht gesendet wird. Weitere Beispiele, einschließlich des Sendens anderer Medien wie Dateianlagen und adaptive Karten, finden Sie unter Senden von chatMessage.
Anforderung
POST https://graph.microsoft.com/v1.0/chats/19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2/messages
Content-type: application/json
{
"body": {
"content": "Hello World"
}
}
Antwort
HTTP/1.1 201 Created
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#chats('19:b1234aaa12345a123aa12aa12aaaa1a9%40thread.v2')/messages/$entity",
"id": "1673482643198",
"replyToId": null,
"etag": "1673482643198",
"messageType": "message",
"createdDateTime": "2023-01-12T00:17:23.198Z",
"lastModifiedDateTime": "2023-01-12T00:17:23.198Z",
"lastEditedDateTime": null,
"deletedDateTime": null,
"subject": null,
"summary": null,
"chatId": "19:b1234aaa12345a123aa12aa12aaaa1a@thread.v2",
"importance": "normal",
"locale": "en-us",
"webUrl": null,
"channelIdentity": null,
"policyViolation": null,
"eventDetail": null,
"from": {
"application": null,
"device": null,
"user": {
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
"displayName": "John Smith",
"userIdentityType": "aadUser"
}
},
"body": {
"contentType": "text",
"content": "Hello world"
},
"attachments": [],
"mentions": [],
"reactions": []
}
Schritt 4: Abrufen von Nachrichten
Verwenden Sie die GET
HTTP-Methode für die chatMessages-Ressource , um Nachrichten abzurufen.
Um die Antwortzeit für Ihre Anwendung zu verbessern, die Drosselung zu minimieren und die Kosten für Sie zu senken, minimieren Sie das mehrfache Lesen derselben Nachricht. Verwenden Sie die GET
HTTP-Methode als einmaligen Export, oder wenn die Änderungsbenachrichtigungen abgelaufen sind und Sie die Nachrichten erneut synchronisieren möchten. Verlassen Sie sich andernfalls auf Ihren Cache und Ändern von Benachrichtigungen.
Microsoft Graph bietet mehrere Möglichkeiten zum Abrufen von Chatnachrichten:
-
Abrufen aller Nachrichten aus allen Chats (in allen Chats):
GET /users/{user-id | user-principal-name}/chats/getAllMessages
-
Auflisten von Nachrichten in einem Chat (pro Chat):
GET /chats/{chat-id}/messages
Mithilfe von /getAllMessages
können Sie Nachrichten in allen Chats für einen Benutzer abrufen. Diese API ist für Back-End-Anwendungen wie Überwachungs- und Complianceanwendungen konzipiert, die häufig Nachrichten in allen Chats gleichzeitig erhalten. Sie unterstützt nur Anwendungsberechtigungen . Außerdem handelt es sich hierbei um eine getaktete API.
Mithilfe von /messages
können Sie API-Aufrufe über die Benutzeroberfläche mit delegierten Berechtigungen durchführen, wie in Schritt 1 beschrieben.
Unterschiedliche APIs weisen unterschiedliche Drosselungsgrenzwerte auf. Beispielsweise gilt für die Pro-Chat-API /messages
ein Grenzwert von 30 Anforderungen pro Sekunde (rps) pro App und Mandant. Wenn ein Mandant über 50 Benutzer verfügt und jeder Benutzer durchschnittlich 15 Chats hat und Sie Nachrichten für alle Benutzer und alle Chats zu Beginn Ihres Systems abrufen möchten, benötigen Sie mindestens 50 Benutzer x 15 Chatanfragen/Benutzer = 750 Anforderungen. In diesem Fall ist es am besten, die Anforderungen auf mindestens 750 Anforderungen /30 rps = 25 Sekunden zu verteilen. Da es einen Grenzwert (maximal $top=50
) für die Anzahl der Nachrichten gibt, die in einer Antwort zurückgegeben werden, müssen Sie möglicherweise mehrere Anforderungen stellen, um alle Nachrichten abzurufen.
Das folgende Beispiel zeigt, wie Sie die Pro-Chat-API /messages
verwenden. Standardmäßig wird die zurückgegebene Liste der Nachrichten nach lastModifiedDateTime
sortiert. In diesem Beispiel wird nach createdDateTime sortiert. Die Sortierung wird über den orderBy
Abfrageparameter in der Anforderung angegeben.
Typische interaktive Messaging-Apps zeigen standardmäßig nur die neuesten Nachrichten an, und Benutzer können dann ältere Nachrichten laden, indem sie paging, scrollen oder klicken. Um nur die nachrichten abzurufen, die Sie benötigen, unterstützen beide apIs oben auch Filterung (z. B $top=10
. , $filter=lastModifiedDateTime gt 2019-03-17T07:13:28.000z
).
Anforderung
GET https://graph.microsoft.com/v1.0/users/87d349ed-44d7-43e1-9a83-5f2406dee5bd/chats/19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2/messages?$top=2&$filter=lastModifiedDateTime gt 2021-03-17T07:13:28.000z&$orderby=createdDateTime desc
Antwort
HTTP/1.1 200 OK
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('87d349ed-44d7-43e1-9a83-5f2406dee5bd')/chats('19%3Ab1234aaa12345a123aa12aa12aaaa1a9%40thread.v2')/messages",
"@odata.count": 2,
"@odata.nextLink": "https://graph.microsoft.com/v1.0/users/87d349ed-44d7-43e1-9a83-5f2406dee5bd/chats/19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2/messages?$top=2&$filter=lastModifiedDateTime+gt+2021-03-17T07%3a13%3a28.000z&$orderby=createdDateTime+desc&$skiptoken=A111wwAwAA1ww1AwA1wwA1Aww111AA1wAwAAwAAwAAAwA1w1AAAwAAwww1Aww1AwAAwwAAA1AA1wAwAAw111wA11AAAww11Aw1wwww1wAwwwAAwwAwAwAAw1",
"value": [
{
"id": "1673543687527",
"replyToId": null,
"etag": "1673543687527",
"messageType": "message",
"createdDateTime": "2023-01-12T17:14:47.527Z",
"lastModifiedDateTime": "2023-01-12T17:14:47.527Z",
"lastEditedDateTime": null,
"deletedDateTime": null,
"subject": null,
"summary": null,
"chatId": "19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2",
"importance": "normal",
"locale": "en-us",
"webUrl": null,
"channelIdentity": null,
"policyViolation": null,
"eventDetail": null,
"from": {
"application": null,
"device": null,
"user": {
"id": "6789f158-72b1-4a63-9959-1f006381132b",
"displayName": "Adele Vance",
"userIdentityType": "aadUser",
"tenantId": "4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1"
}
},
"body": {
"contentType": "html",
"content": "<p>Good morning, world!</p>"
},
"attachments": [],
"mentions": [],
"reactions": []
},
{
"id": "1673482643198",
"replyToId": null,
"etag": "1673482643198",
"messageType": "message",
"createdDateTime": "2023-01-12T00:17:23.198Z",
"lastModifiedDateTime": "2023-01-12T00:17:23.198Z",
"lastEditedDateTime": null,
"deletedDateTime": null,
"subject": null,
"summary": null,
"chatId": "19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2",
"importance": "normal",
"locale": "en-us",
"webUrl": null,
"channelIdentity": null,
"policyViolation": null,
"eventDetail": null,
"from": {
"application": null,
"device": null,
"user": {
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
"displayName": "John Smith",
"userIdentityType": "aadUser",
"tenantId": "4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1"
}
},
"body": {
"contentType": "text",
"content": "Hello world"
},
"attachments": [],
"mentions": [],
"reactions": []
}
]
}
In diesem Beispiel kann contentType entweder text
oder html
sein. Stellen Sie sicher, dass Ihre Anwendung beide anzeigen kann.
Um bilder zu erhalten, die in die Chatnachricht eingebettet sind, führen Sie einen zweiten Anruf aus, um chatMessageHostedContent abzurufen. Weitere Informationen finden Sie unter Abrufen von chatMessageHostedContent.
Es wird empfohlen, dass Ihre App das Feld chatMessage.policyViolation.dlpAction überwacht, auf Änderungsbenachrichtigungen in diesem Feld überwacht und die Nachrichten gemäß der Verhinderung von Datenverlust (Data Loss Prevention, DLP) oder ähnlichen Regeln ausblendet oder kennzeichnet, die von Ihrem organization definiert werden. Die gültigen Werte sind None
, NotifySender
und BlockAccess
. Teams ignoriert BlockAccessExternal
derzeit . Ausführliche Informationen zu diesen Werten finden Sie unter chatMessagePolicyViolation-Ressourcentyp.
Einige Nachrichten sind Systemnachrichten. Die folgende Systemmeldung zeigt beispielsweise, dass ein neues Mitglied dem Chat beigetreten ist.
{
"id": "1616883610266",
"replyToId": null,
"etag": "1616883610266",
"messageType": "systemEventMessage",
"createdDateTime": "2021-03-28T03:50:10.266Z",
"lastModifiedDateTime": "2021-03-28T03:50:10.266Z",
"lastEditedDateTime": null,
"deletedDateTime": null,
"subject": null,
"summary": null,
"chatId": null,
"importance": "normal",
"locale": "en-us",
"webUrl": "https://teams.microsoft.com/l/message/19%3A4a95f7d8db4c4e7fae857bcebe0623e6%40thread.tacv2/1616883610266?groupId=fbe2bf47-16c8-47cf-b4a5-4b9b187c508b&tenantId=2432b57b-0abd-43db-aa7b-16eadd115d34&createdTime=1616883610266&parentMessageId=1616883610266",
"policyViolation": null,
"from": null,
"body": {
"contentType": "html",
"content": "<systemEventMessage/>"
},
"channelIdentity": {
"teamId": "fbe2bf47-16c8-47cf-b4a5-4b9b187c508b",
"channelId": "19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2"
},
"onBehalfOf": null,
"attachments": [],
"mentions": [],
"reactions": [],
"eventDetail": {
"@odata.type": "#microsoft.graph.membersAddedEventMessageDetail",
"visibleHistoryStartDateTime": "0001-01-01T00:00:00Z",
"members": [{
"id": "06a5b888-ad96-455e-88ef-c059ec4e4cf0",
"displayName": null,
"userIdentityType": "aadUser"
},
{
"id": "1fb8890f-423e-4154-8fbf-db6809bc8756",
"displayName": null,
"userIdentityType": "aadUser"
}
],
"initiator": {
"application": null,
"device": null,
"user": {
"id": "9ee3dc1b-6a70-4582-8bc5-5dd35336b6c3",
"displayName": null,
"userIdentityType": "aadUser"
}
}
}
}
Schritt 5: Zwischenspeichern von Nachrichten
Da für jede Nachricht, die Sie von getAllMessages oder Änderungsbenachrichtigung erhalten, Verbrauchsgebühren anfallen, sollten Sie das mehrfache Lesen derselben Nachricht minimieren. Es wird empfohlen, Nachrichten mindestens einige Stunden zwischenspeichern zu lassen, damit ein Benutzer einen zuletzt verwendeten Chat schnell erneut öffnen kann. Speichern Sie Nachrichten nicht länger zwischen, als gemäß den Aufbewahrungsrichtlinien Ihrer organization zulässig ist.
In Schritt 6 entscheiden Sie, ob der Cache benutzerbezogen ist oder nicht.
Schritt 6: Abonnieren von Änderungsbenachrichtigungen
Microsoft Graph bietet verschiedene Arten von Änderungsbenachrichtigungen für Nachrichten, die durch die entsprechenden Ressourceneigenschaften angegeben werden:
- Pro Chat:
"resource": "/chats/{id}/messages"
- Pro Benutzer, in allen Chats:
"resource": "/users/{id}/chats/getAllMessages"
- Pro Mandant, in allen Chats:
"resource": "/chats/getAllMessages"
- Pro App in allen Chats in einem Mandanten, in dem die App installiert ist:
"resource": "/appCatalogs/teamsApps/{id}/installedToChats/getAllMessages"
Wenn Sie nur bestimmte Chats nachverfolgen möchten, /messages
ist eine Option, aber Sie sollten berücksichtigen, wie viele verschiedene Chats Sie nachverfolgen müssen. Es gibt einen Grenzwert (z. B. 10.000) für die Anzahl von Änderungsbenachrichtigungen pro Chat; Weitere Informationen finden Sie unter Abonnements. Ziehen Sie stattdessen in Betracht, eine der drei /getAllMessages
Optionen zu abonnieren, die Nachrichten in allen Chats eines Benutzers, Mandanten oder einer App erhalten.
Alle vier Optionen werden von Ihrer Back-End-Serverkomponente aufgerufen. Da sie alle Anwendungsberechtigungen unterstützen, achten Sie auf die Zugriffssteuerungslogik, um Chats entsprechend ein- und auszublenden, wenn Benutzer teilnehmen oder diese verlassen. Die Option pro Benutzer, die auch delegierte Berechtigungen unterstützt, ist möglicherweise einfacher zu implementieren, da die Änderungsbenachrichtigungen bereits benutzerspezifisch sind. Dies kann jedoch auf lange Sicht teurer sein, da dieselbe Nachricht mehrere Änderungsbenachrichtigungen auslösen würde, eine für jeden abonnierten Benutzer, und Sie benötigen möglicherweise einen größeren Cache, um die duplizierten Nachrichten zu speichern. Weitere Informationen zu Berechtigungen und Lizenzierungsanforderungen für die verschiedenen abonnierten Ressourcen finden Sie unter Erstellen eines Abonnements.
Für Abonnements mit Änderungsbenachrichtigungen fallen Verbrauchsgebühren an. Geben Sie den model
Parameter für die Ressourceneigenschaft an, wie im folgenden Beispiel gezeigt.
Stellen Sie beim Erstellen des Abonnements sicher, dass die includeResourceData-Eigenschaft auf true
festgelegt ist und Dass Sie die Eigenschaften encryptionCertificate und encryptionCertificateId angegeben haben. Andernfalls wird der verschlüsselte Inhalt in den Änderungsbenachrichtigungen nicht zurückgegeben. Weitere Informationen finden Sie unter Einrichten von Änderungsbenachrichtigungen, die Ressourcendaten enthalten.
Das folgende Beispiel zeigt, wie Sie alle Nachrichten pro Benutzer abrufen. Bevor Sie dieses Beispiel verwenden, muss der Abonnementbenachrichtigungsendpunkt (angegeben in der notificationUrl-Eigenschaft ) in der Lage sein, auf eine Validierungsanforderung zu reagieren, wie unter Einrichten von Benachrichtigungen für Änderungen an Benutzerdaten beschrieben. Wenn die Überprüfung fehlschlägt, gibt die Anforderung zum Erstellen des Abonnements einen 400 Bad Request
Fehler zurück.
Weitere Informationen zu diesem Beispiel finden Sie unter Erstellen eines Abonnements.
Anforderung
POST https://graph.microsoft.com/v1.0/subscriptions
Content-type: application/json
{
"changeType": "created,updated,deleted",
"notificationUrl": "https://webhook.azurewebsites.net/api/send/myNotifyClient",
"resource": "/users/87d349ed-44d7-43e1-9a83-5f2406dee5bd/chats/getAllMessages?model=B",
"expirationDateTime": "2023-01-10T18:56:49.112603+00:00",
"clientState": "ClientSecret",
"includeResourceData": true,
"encryptionCertificate": "MMMM/sMMMsssMsMMMsMMsMMMs4sMMsM4ssMsMsMMMss4ssMMMssss...s4sMMMMsM444ssM4MMsssMMMMsM4MMM4sMsM4MMsM44MMM4ssss4Ms4sMM4MMMMM4MMs+ss4MsMssMss4s==",
"encryptionCertificateId": "44M4444M4444M4M44MM4444MM4444MMMM44MM4M4"
}
Antwort
HTTP/1.1 201 Created
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#subscriptions/$entity",
"id": "88aa8a88-88a8-88a8-8888-88a8aa88a88a",
"resource": "/users/87d349ed-44d7-43e1-9a83-5f2406dee5bd/chats/getAllMessages?model=B",
"applicationId": "aa8aaaa8-8aa8-88a8-888a-aaaa8a8aa88a",
"changeType": "created,updated,deleted",
"clientState": "ClientSecret",
"notificationUrl": "https://webhook.azurewebsites.net/api/send/myNotifyClient",
"notificationQueryOptions": null,
"lifecycleNotificationUrl": null,
"expirationDateTime": "2023-01-10T18:56:49.112603Z",
"creatorId": "8888a8a8-8a88-888a-88aa-8a888a88888a",
"includeResourceData": true,
"latestSupportedTlsVersion": "v1_2",
"encryptionCertificate": "MMMM/sMMMsssMsMMMsMMsMMMs4sMMsM4ssMsMsMMMss4ssMMMssssssM4s4MMMsMMMMMMMMsMMMMMMMssMMsMMMMMMMMM4MMMMMsMMMMMMMssMMsMMMMMMMMMM4MMMssMsMMMMMMMs4MMMMsMM4sssMsM4MsMMMsMssMMsMsMMM4MMssMMMsMssMMsMsMMMsMMssMMMsMsMsMMssMsMMMMMMMsM4MMMss4ssMMMsMMssM4MsMsM4Ms4sM4MssMssMsMssMMMMMMsMMMMMsMMsssMMMMMMMMMssMMMMMMMMsMssMMMMM4ssMMs4sMsM/+MM4444s4M/+4sss4MMMMMsMsMsss/s/sMMsMss4sMsMMMss4M4Ms44M4M4MsssssM4M4MMMM444Mss4+s4M44MsssMMMs4Ms4MsMMsMMsMsMMM4sMMMMsssMssssMMss44MMs+MMssMsMsM4sMMs4MsMsM4ssM4MMMsMMs4sMMM4MsM+MsMss+sMsMM4sMM4sMMM4ss4ssssMMMsssM4MMssM+MsM/sMMss4MsMMM44+/MMMsMs4s44M++ssssssMMs/MsMMMMsMMssMsssssMMss4MMMsM4s4MssMsMssMsMMMMMMs4sMMssMsMMMM/ss4sMMsMMsMMMsMMMMMsssM4MMsMMMsMMMMMsssMMsMsMMssMsMMMsMMMMMMMsMsMsMMMsMMMMMMMsMsMMMMMsMMMMMMMsMMMMMsMsMsMsMMMMMMMsMMssMsMMMMsMsM4Ms+sMssMs4sMsMsssM4M4Ms4MMMMMMMMMssssMMMsssMsMMMMsMMMMMMs4sssM4MMMMMMsMMMMMMsMMsssssMMsMs4sM4MsMs4sM4Mss44ssM4ss44ssMsssM4sssMsM4MssMMsM44sMMsMMM4MM4MsMM4MMMMsM4MMM4MMMMMsMMssMsMsMMMsM4MsMsMsMM4sssMsMsMMMsMMMMMMMMMMM4s4sMM4Ms4sssssMsMsMM4sMsssMMssM4MMMMMMMMsMMMMMMMMsMM4MMssMMM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4M4MMMMMMsMMMMMMsMMsssssMMsMs4sM4MsMs4ssMMsM4MsM4MsMM4MMsMMM4sMMsMMMMMsMsMMMM4MMsssMM4MMMMsMM4sssMsMsMMMMMsMMM4MsMssMMMMsssMsMMMMssMsMMsMM4sMssM4MssMMsMM4sMssssM4ssMMsM44sMMsMMM4MM4MsMM4MMMMsM4MMM4MMMMMsMMssMsMsMMMsM4MsMsMsMM4sssMsMsMMMsMMMMMMMMMMM4s4sMM4Ms4ssss4MsMsMM4sMsssMMssM4MMMMMMMMsMMMMMMMMsMM4MMssMMM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4M4MM4MM4MsMsMMMMMsM4M4ssMMMssssMMMMMsM/s4MsMMMMsMMMM4MMs4MMMMMMsMsMsMMMM4MMMMsMsMssMMssMMsssMssM4ss4MssM4ssMMssssssMMsss4ss44sssMsMsMMMM4MssMsMMMMMMMMMMMsssMMsMMMMMM/sMM4sMssM4MssM4ssMMss4MsMsMsM44sM4MssMssMsMsM4MMMM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4MsssMssMMsMs4sM4MsMM4ssMMsM4MsM4MssM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4MsssMssMMsMs4sM4MsMs4ssMMsM4MsM4MssM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4MsssMssMMsMs4sM4MsMs4ssMMsM4MsM4MssM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4MsssMssMMsMs4sM4MsMM4ssMMsM4MsM4MssM4MMMMsMsMMssMsMMMsMMMMMMMsMMMsM4MsMM4MM4MsMsMMMMsMMMsMMMMssMssss4s+MMM44MMMsMsMM4MM4MsMMMMMMMMMMsMMMMMMsMMMsssMsMMMMsMMsMMMssssssM4s4MMMsMMMMMMMMMMMM4MMMMssss444MsMsMMM44MM/444sMMMs4sMsMM4sMMMssMM4+M4sssMs+MsMMMMM/M/s4MMssM4ssss/4MMMsssMsMMss44sMsss4++ss/4s+s4sMs+4sM4MsM/4/MssMMMsMssMs4MsMss4MMsMsMssssssMMM4MsMM4s+MMM4M4sMMMMs4s4sMMMMsM444ssM4MMsssMMMMsM4MsMsMMM4sMsMs4sMsMMMMMs4MsMsMsMsM4sMs4sMMMMMsssMssMsMsMMss4MMM4sMsM4sMMssMMsM44MM4ss4s4Ms44sMMM4ssss4Ms4sMM4MMMMM4MMs+ss4MsMssMss4s==",
"encryptionCertificateId": "44M4444M4444M4M44MM4444MM4444MMMM44MM4M4",
"notificationUrlAppId": null
}
Schritt 7: Empfangen und Entschlüsseln von Änderungsbenachrichtigungen
Wenn eine Änderung an der abonnierten Ressource erfolgt, wird eine Änderungsbenachrichtigung an die notificationUrl gesendet. Aus Sicherheitsgründen wird der Inhalt verschlüsselt. Informationen zum Entschlüsseln des Inhalts finden Sie unter Entschlüsseln von Ressourcendaten aus Änderungsbenachrichtigungen.
Stellen Sie beim Erstellen des Abonnements sicher, dass die includeResourceData-Eigenschaft auf true
festgelegt ist und dass Sie die Eigenschaften encryptionCertificate und encryptionCertificateId angegeben haben. Andernfalls wird der verschlüsselte Inhalt in den Änderungsbenachrichtigungen nicht zurückgegeben. Einzelheiten hierzu finden Sie unter Überprüfung von Benachrichtigungsendpunkten.
Anforderung (gesendet von Microsoft Graph)
POST https://webhook.azurewebsites.net/api/send/myNotifyClient
Content-type: application/json
{
"value": [
{
"subscriptionId": "88aa8a88-88a8-88a8-8888-88a8aa88a88a",
"changeType": "created",
"clientState": "ClientSecret",
"subscriptionExpirationDateTime": "2023-01-10T11:03:37.0068432-08:00",
"resource": "chats('19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2')/messages('1677774058888')",
"resourceData": {
"id": "1677774058888",
"@odata.type": "#Microsoft.Graph.chatMessage",
"@odata.id": "chats('19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2')/messages('1677774058888')"
},
"encryptedContent": {
"data": "sMMsMsMM+3MMMs8MMsMMsss5M+M0+8sMMsM96MM/8MMMsM4MM12sMsssMMsssMsMMssMs8Mss6sssMMsM2ssssssssMss7sssMs4s35ssMs+0ss1sssMsMssMMMMsssss5MsMssssss+sMsMMMM8s4M3MMsMssM54s1ssssMs4ssMsss3MMM8M4sM+3MMss7MM8sMsMMMs3sssss5MssMss6s+Ms7sMssMMssMsMMss1sMs2sM6sss6sMssssMss7s1MMs7/Msssss5M9M7sMsMMMsMs+MMs+MsMMsMsMMMMsMMMss1M2ssMM8M3sMMMsMss2MMMMsM+ss0M+sssMM4M+sMsM69sMs+sMsssM+MMsMsMM/ssssMMMMMss/s6/47Ms0s5Ms6MsssM2sss4MMMMMMsMsMMM+s8MssMsMMssMMs+MMMM56ss0sMM+sssMsss1ssMsMs21s3MssM9ssMsss9M2+MM3sMMMMMM7MM770MMM2MMsssM11MsssMssMsMsMM2sM1s+84MMs6sss8MsMMsMMsMM3MMssMss1MssMsMsMMMMsMsssMMsssM1sssssM9MMM6s4MMss524sMMMssMs4ss3/+ssssss8MMs2ssMMs2MsMsMMssM8MMMMsMM0sss4MMs/sMsMMs0sMMsssss135sssss9+sssMsMMsMsssMsMsMsMsMM7Ms+MssMsMM1sMssss5s64sMss6sMs6sM0MMs3s29MMssM62ssMsMMssMsM0ssssssss+sM1MsM3sMM9sssssMMMsssMMsMsMsssMssssssMsMssMMMsM8Ms5MsssMM9ss/4MssMs3s5M81sMMssssMMMssMMs7Ms2M9M+7MsssMss6sM0sssM7M0ssMssssMMsMMs9s4MsMsMM6MMsMMssMMssM+Mss6MM8MMM6MM1s75MsssMMsM+MMMs2s9M1MMMsMMs1MssMsssssssMs8MsMsMMMMMM7sMsss0MssMsMMssMMM/sM0M01s2M7MsssssMs37MMs140sMMM0ssMMM/ssMMs3sMsM+Ms+sMMsM3MMssMssMsssss6MMssMMMs1MMMMMsssMs0sM9sMMMss+sssss2sssMssMsMMM1MssMMMs8MMMssssMM99ssMsssMssss2Ms5sMs1/5MMssssMsMM3MMMMM1MsMsMsMMsMMssMsMMsssssMs9Mss6Mss+sM+73Msss0ssMsss8sMssMssssssssssMM9MMMMsMMMMMMMM5MMMM27sM+ssMG",
"dataSignature": "sMM+sss2sMssMMsMMMMMMMM6ssMs93MssMMM8sMMMMM=",
"dataKey": "MMsMMMMMss7sssM34sMMsMMsMssMss7MssMssss+MM+4sMsssMss6Msss9sMssMssMsssMM0+MMsss0sMs8MMsMssss2MMMMsMsssMMsMsM3MssMs9ss5sssMMsMssMsMMM6MMssMsM1M+MMMMsMss3MMsssMs9s0ssMs/1sM6ssMMssM+Ms9MsssMMM8MMssssMMs2s94MsMssMMM92/MMMs4Ms8/ssssssMs5+0s+Ms2M7sMMMMsMMsMsMs+5MMM3sssMsMMMsM8sMss+MssssMsMs/MMsMM5ssssM8M0s0MM06sssMMsMM4MsssMMsMssMM9M9MsMMMMM7sMsMM==",
"encryptionCertificateId": "44M4444M4444M4M44MM4444MM4444MMMM44MM4M4",
"encryptionCertificateThumbprint": "07M3411M4904M3M78MM8211MM4589MMMM47MM7M6"
},
"tenantId": "4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1"
}
],
"validationTokens": [
"ssM0sMMsMsMMM1MsMMMssMssMsMMMsM1MsMsMss1sMM6Ms1MMMMMMM5MMsssMs9ssM1sMs9MsMMMMsssssMsMsssMMM6Ms1MMMMMMM5MMsssMs9ssM1sMs9MsMMMMsssssM9.ssMssMMsMsMsMsssMMMsMs04M2M2MMM1MMMsMMs4MM1sM2MsMMM5MsM3MsMsMMMss3MsMsMssMMsssssM3M0ss53sM5ss3ssMs5ssM8sMMMsMsM3Ms0sMMMsMMMsMMMsMMM3Ms0sMsMsMMMsMMMsMsMsMssssMM0MsssMsssMsssMsMsMMMsMsMsMsM2MsMsMsM3MMMsMsM4sMM6MMM3MsM2MMM1MMssMMssMsssMMMsM1sMssM5MMs4ssMsMMssMMMMM2MsMMMsMMsMMM0sMMMssMMsMMM6MsMsMsMsMsMsMMMsMMMsMMssMs05MMssMMMsMMssMMM0MMM4MsMsMsMssMssMMMsMsssMsMsMssssMM6Mss0sMMsMs8ss3MsMsssssMss3MsssM0MsM0MsMsMMssMMMsMsMsMMMsMs1sMMssMMM2MMMsMMMsMMMsMM8sMMMssMMsMsMsMsMsMsMsMM1sMsssMMMsMMMsMsssMM1sMMMsMMM0M2M2MMssMMMssMM6MsMsMMMsMMM3MMsMMMMMMsMMsMM4MsMsMsMsMssMsMMsMMMsM05MsMssMMssMMM5sMsMMMMMMsMsMsM1MsM6MsMsMsMsMsM1MMM3MMMsMMM5Ms1sM2M1MMMsMMM0MMMsMsM1MsMsMsMsMMM6MsM0MsMsMMssMMMsMsMsMMMsMs1sMMssMMM2MMMsMMMsMMMsMMMsMsM0sMM6MssMMs1sMMMssMsMMMMMssMMss16MMMsMMM2MMMsMsMsMsMssM.s16ssMMM97sM_MMs_ss8s8s3MMs95ssMMM8M6ss4M4Ms3sMMMs-M_7ss80MMMsss6ssM0sMM20MsMMs15sMM_ssMsssMMMs9ssM0M_sss5sMssMsMss4s-M-8Ms1ssM8sMsMMss9sMsMsMMMMMMMsMs6MMss2MMMsMMss0MMssMMssMssMMMMMMMMsMs817ssssssMss8MMMssMMMMsss0sMs1ssM0sM1ssMMMs6MMMMss6ss_sMMss3M4MM3sMss45s4s8MMss6s75ssMsM5sssMM0MMMMMM_1ssMMMMsMMMssMs44sMs4MssM5s-__ss5MMs6sMM_MMss5MsMMMM"
]
}
Entschlüsselter Inhalt
{
"@odata.context": "https://graph.microsoft.com/$metadata#chats('19%3Ab1234aaa12345a123aa12aa12aaaa1a9%40thread.v2')/messages/$entity",
"id": "1677774058888",
"replyToId": null,
"etag": "1677774058888",
"messageType": "message",
"createdDateTime": "2023-01-10T18:07:30.302Z",
"lastModifiedDateTime": "2023-01-10T18:07:30.302Z",
"lastEditedDateTime": null,
"deletedDateTime": null,
"subject": "",
"summary": null,
"chatId": "19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2",
"importance": "normal",
"locale": "en-us",
"webUrl": null,
"from": {
"application": null,
"device": null,
"user": {
"userIdentityType": "aadUser",
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
"displayName": "John Smith",
"tenantId": "4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1"
}
},
"body": {
"contentType": "html",
"content": "<p>Hello world</p>"
},
"channelIdentity": null,
"attachments": [
],
"mentions": [
],
"onBehalfOf": null,
"policyViolation": null,
"reactions": [
],
"messageHistory": [
],
"replies": [
],
"hostedContents": [
],
"eventDetail": null
}
Änderungsbenachrichtigungen werden manchmal in der richtigen Reihenfolge übermittelt, da sie asynchron sind. Wenn ihre Anwendung erfordert, dass die Ressourcen in einer bestimmten Reihenfolge sortiert werden, stellen Sie sicher, dass Sie den entschlüsselten Inhalt nach der entsprechenden Eigenschaft sortieren. Wenn die Nachrichten beispielsweise in Ihrer Chatanwendung in chronologischer Reihenfolge angezeigt werden sollen, sortieren Sie die entschlüsselten chatMessages nach createdDateTime.
Wenn eine Chatnachricht bearbeitet wird, wird eine Änderungsbenachrichtigung für die Bearbeitung mit einer aktualisierten lastEditedDateTime
gesendet. Ihre Chatanwendung sollte die bearbeitete Nachricht anstelle der ursprünglichen Nachricht anzeigen, wenn die neueste Version von Nachrichten angezeigt werden soll.
Die Hinweise zu contentType, Images, Data Loss Prevention (DLP) und Aufbewahrungsrichtlinien in Schritt 4: Abrufen von Nachrichten gelten auch für die entschlüsselten Nachrichten.
Schritt 8: Verlängern von Abonnements für Änderungsbenachrichtigungen
Aus Sicherheitsgründen laufen Abonnements für chatMessage in 60 Minuten ab. Es wird empfohlen, alle 30 Minuten zu verlängern, um puffern zu können. Lebenszyklusbenachrichtigungen für ablaufende Abonnements sind derzeit nicht verfügbar. Daher müssen Sie die Abonnements nachverfolgen und verlängern, bevor sie ablaufen, indem Sie die eigenschaft expirationDateTime aktualisieren, wie unter Abonnement aktualisieren beschrieben. Da die Verlängerung Von Tausenden von Abonnements Zeit in Anspruch nimmt, ist dies ein Grund, änderungsbenachrichtigungen pro Chat zu vermeiden.
Wenn ein Abonnement abläuft, bevor es verlängert wird, werden möglicherweise einige Änderungsbenachrichtigungen übersehen. Synchronisieren Sie die Nachrichten erneut, indem Sie Schritt 4: Abrufen von Nachrichten wiederholen.
Das folgende Beispiel zeigt, wie Sie ein Abonnement verlängern.
Anforderung
PATCH https://graph.microsoft.com/v1.0/subscriptions/88aa8a88-88a8-88a8-8888-88a8aa88a88a
Content-type: application/json
{
"expirationDateTime":"2023-01-12T18:23:45.9356913Z"
}
Antwort
HTTP/1.1 200 OK
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#subscriptions/$entity",
"id": "88aa8a88-88a8-88a8-8888-88a8aa88a88a",
"resource": "/users/87d349ed-44d7-43e1-9a83-5f2406dee5bd/chats/getAllMessages",
"applicationId": "aa8aaaa8-8aa8-88a8-888a-aaaa8a8aa88a",
"changeType": "created",
"clientState": null,
"notificationUrl": "https://function-ms-teams-subscription-webhook-z2a2ig2bfq-uc.a.run.app",
"notificationQueryOptions": null,
"lifecycleNotificationUrl": null,
"expirationDateTime": "2023-01-12T18:23:45.9356913Z",
"creatorId": "8888a8a8-8a88-888a-88aa-8a888a88888a",
"includeResourceData": null,
"latestSupportedTlsVersion": "v1_2",
"encryptionCertificate": null,
"encryptionCertificateId": null,
"notificationUrlAppId": null
}
Schritt 9: Abrufen und Festlegen von Standpunkten
Ein Standpunkt in einem Chat markiert den Zeitstempel, zu dem der Chat zuletzt von Benutzern gelesen wurde, sodass Benutzer sehen können, dass alle Nachrichten unter dem Standpunkt ungelesen sind.
Um den Standpunkt eines Chats abzurufen, verwenden Sie die GET
HTTP-Methode für die Chatressource , wie im folgenden Beispiel gezeigt.
Anforderung
GET https://graph.microsoft.com/v1.0/users/87d349ed-44d7-43e1-9a83-5f2406dee5bd/chats/19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2
Antwort
HTTP/1.1 200 OK
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#chats/$entity",
"id": "19:b1234aaa12345a123aa12aa12aaaa1a9@thread.v2",
"topic": null,
"createdDateTime": "2023-01-11T01:34:18.929Z",
"lastUpdatedDateTime": "2023-01-11T01:34:18.929Z",
"chatType": "group",
"webUrl": "https://teams.microsoft.com/l/chat/19%3Ab1234aaa12345a123aa12aa12aaaa1a9%40thread.v2/0?tenantId=4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1",
"tenantId": "4dc1fe35-8ac6-4f0d-904a-7ebcd364bea1",
"onlineMeetingInfo": null,
"viewpoint": {
"isHidden": false,
"lastMessageReadDateTime": "2021-05-27T22:13:01.577Z"
}
}
Der Standpunkt eines Chats für einen Benutzer wird aktualisiert, wenn der Benutzer den Chat als gelesen markiert, den Chat als ungelesen markiert, den Chat ausblendet oder den Chateinblendet.
Kostenschätzung
Derzeit fallen für das Abrufen von Nachrichten pro Benutzer und Chat (Schritt 4) keine Verbrauchsgebühren an (es gelten jedoch Drosselungsgrenzwerte). Nur bei Änderungsbenachrichtigungen fallen Verbrauchsgebühren von 0,00075 USD pro Nachricht an.
Wenn Ihre App 50 Benutzer hat und jeder Benutzer Nachrichten von 20 Benutzern empfängt und 300 Nachrichten pro Monat sendet, würden die ungefähren Kosten wie folgt ausfallen:
- 50 Empfänger x (20 Absender x 300 Nachrichten/Monat/Absender)/Empfänger x 0,00075 USD/Nachricht = 300.000 Nachrichten/Monat x 0,00075 USD/Nachricht = 225 USD/Monat.
Die aktuellsten Preisinformationen finden Sie unter Lizenzierungs- und Zahlungsanforderungen für die Microsoft Teams-API.