Suche mit Nachrichtenerweiterungen
Wichtig
Die Artikel in diesem Abschnitt basieren auf dem Bot Framework SDK v3. Wenn Sie nach der aktuellen Dokumentation (Version 4.6 oder höher des SDK) suchen, lesen Sie den Abschnitt Aufgabenorientierte Interaktionen mit Nachrichtenerweiterungen .
Suchbasierte Nachrichtenerweiterungen ermöglichen es Ihnen, Ihren Dienst abzufragen und diese Informationen in Form einer Karte direkt in Ihrer Nachricht zu posten.
In den folgenden Abschnitten wird die Vorgehensweise beschrieben:
Hinzufügen einer Nachrichtenerweiterung zu Ihrer App
Eine Nachrichtenerweiterung ist ein in der Cloud gehosteter Dienst, der auf Benutzeranforderungen lauscht und mit strukturierten Daten wie einer Karte antwortet. Sie integrieren Ihren Dienst über Bot Framework-Objekte Activity
in Microsoft Teams. Unsere .NET- und Node.js-Erweiterungen für das Bot Builder SDK können Ihnen helfen, Ihrer App Nachrichtenerweiterungsfunktionen hinzuzufügen.
Registrieren im Bot Framework
Sie müssen zunächst einen Bot beim Microsoft Bot Framework registrieren. Die Microsoft-App-ID und die Rückrufendpunkte für Ihren Bot, wie dort definiert, werden in Ihrer Nachrichtenerweiterung verwendet, um Benutzeranforderungen zu empfangen und darauf zu reagieren. Denken Sie daran, den Microsoft Teams-Kanal für Ihren Bot zu aktivieren.
Notieren Sie sich ihre Bot-App-ID und das App-Kennwort. Sie müssen die App-ID in Ihrem App-Manifest angeben.
Aktualisieren Ihres App-Manifests
Wie bei Bots und Registerkarten aktualisieren Sie das Manifest Ihrer App, um die Nachrichtenerweiterungseigenschaften einzuschließen. Diese Eigenschaften steuern, wie Ihre Nachrichtenerweiterung im Microsoft Teams-Client angezeigt wird und wie sie sich verhält. Nachrichtenerweiterungen werden ab Manifest v1.0 unterstützt.
Deklarieren Der Nachrichtenerweiterung
Um eine Nachrichtenerweiterung hinzuzufügen, fügen Sie eine neue JSON-Struktur der obersten Ebene in Ihr Manifest mit der -Eigenschaft ein composeExtensions
. Sie können nur eine einzelne Nachrichtenerweiterung für Ihre App erstellen.
Hinweis
Das Manifest bezieht sich auf Nachrichtenerweiterungen als composeExtensions
. Dies dient der Aufrechterhaltung der Abwärtskompatibilität.
Die Erweiterungsdefinition ist ein Objekt mit der folgenden Struktur:
Eigenschaftenname | Zweck | Pflichtfeld? |
---|---|---|
botId |
Die eindeutige Microsoft-App-ID für den Bot, wie bei Bot Framework registriert. Dies sollte in der Regel mit der ID für Ihre gesamte Teams-App identisch sein. | Ja |
scopes |
Array, das angibt, ob diese Erweiterung zu - oder team -Bereichen (oder beides) hinzugefügt personal werden kann. |
Ja |
canUpdateConfiguration |
Aktiviert das Menüelement "Einstellungen ". | Nein |
commands |
Array von Befehlen, die diese Nachrichtenerweiterung unterstützt. Sie sind auf 10 Befehle beschränkt. | Ja |
Hinweis
Wenn Sie die canUpdateConfiguration
-Eigenschaft im App-Manifest auf true
festlegen, können Sie das Menüelement Einstellungen für Ihre Nachrichtenerweiterung anzeigen. Um Einstellungen zu aktivieren, müssen Sie auch und onSettingsUpdate
behandelnonQuerySettingsUrl
.
Definieren von Befehlen
Ihre Nachrichtenerweiterung sollte einen Befehl deklarieren, der angezeigt wird, wenn der Benutzer Ihre App über die Schaltfläche Weitere Optionen (⋯) im Feld Zum Verfassen auswählt.
Im App-Manifest ist Ihr Befehlselement ein Objekt mit der folgenden Struktur:
Eigenschaftenname | Zweck | Pflichtfeld? | Minimale Manifestversion |
---|---|---|---|
id |
Eindeutige ID, die Sie diesem Befehl zuweisen. Die Benutzeranforderung enthält diese ID. | Ja | 1.0 |
title |
Befehlsname. Dieser Wert wird auf der Benutzeroberfläche angezeigt. | Ja | 1.0 |
description |
Hilfetext, der angibt, was dieser Befehl bewirkt. Dieser Wert wird auf der Benutzeroberfläche angezeigt. | Ja | 1.0 |
type |
Legen Sie den Typ des Befehls fest. Mögliche Werte sind query und action . Wenn nicht vorhanden, wird der Standardwert auf query festgelegt. |
Nein | 1.4 |
initialRun |
Optionaler Parameter, der mit query Befehlen verwendet wird. Wenn dieser Wert auf true festgelegt ist, gibt an, dass dieser Befehl ausgeführt werden soll, sobald der Benutzer diesen Befehl auf der Benutzeroberfläche auswäht. |
Nein | 1.0 |
fetchTask |
Optionaler Parameter, der mit action Befehlen verwendet wird. Legen Sie diesen Wert auf true fest, um die adaptive Karte oder Web-URL abzurufen, die im Aufgabenmodul angezeigt werden soll. Dies wird verwendet, wenn die Eingabe für den action Befehl dynamisch ist, im Gegensatz zu einem statischen Satz von Parametern. Beachten Sie, dass die statische Parameterliste für den Befehl ignoriert wird, wenn sie auf TRUE festgelegt ist. |
Nein | 1.4 |
parameters |
Statische Liste der Parameter für den Befehl. | Ja | 1.0 |
parameter.name |
Der Name des Parameters. Dies wird in der Benutzeranforderung an Ihren Dienst gesendet. | Ja | 1.0 |
parameter.description |
Beschreibt die Zwecke dieses Parameters und ein Beispiel für den Wert, der bereitgestellt werden soll. Dieser Wert wird auf der Benutzeroberfläche angezeigt. | Ja | 1.0 |
parameter.title |
Kurzer benutzerfreundlicher Parametertitel oder -bezeichnung. | Ja | 1.0 |
parameter.inputType |
Legen Sie auf den typ der erforderlichen Eingabe fest. Mögliche Werte sind text , textarea , number , date , time , . toggle Der Standardwert ist auf text festgelegt. |
Nein | 1.4 |
context |
Optionales Array von Werten, das den Kontext definiert, in dem die Nachrichtenaktion verfügbar ist. Mögliche Werte sind message , compose oder commandBox . Der Standardwert ist ["compose", "commandBox"] . |
Nein | 1,5 |
Nachrichtenerweiterungen vom Suchtyp
Legen Sie für die suchbasierte Nachrichtenerweiterung den type
Parameter auf fest query
. Im Folgenden finden Sie ein Beispiel für ein Manifest mit einem einzelnen Suchbefehl. Einer einzelnen Nachrichtenerweiterung können bis zu 10 verschiedene Befehle zugeordnet sein. Dies kann sowohl mehrere Such- als auch mehrere aktionsbasierte Befehle umfassen.
Beispiel für vollständiges App-Manifest
{
"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.8/MicrosoftTeams.schema.json",
"manifestVersion": "1.5",
"version": "1.0",
"id": "57a3c29f-1fc5-4d97-a142-35bb662b7b23",
"developer": {
"name": "John Developer",
"websiteUrl": "http://bingbotservice.azurewebsites.net/",
"privacyUrl": "http://bingbotservice.azurewebsites.net/privacy",
"termsOfUseUrl": "http://bingbotservice.azurewebsites.net/termsofuse"
},
"name": {
"short": "Bing",
"full": "Bing"
},
"description": {
"short": "Find Bing search results",
"full": "Find Bing search results and share them with your team members."
},
"icons": {
"outline": "bing-outline.jpg",
"color": "bing-color.jpg"
},
"accentColor": "#ff6a00",
"composeExtensions": [
{
"botId": "57a3c29f-1fc5-4d97-a142-35bb662b7b23",
"canUpdateConfiguration": true,
"commands": [{
"id": "searchCmd",
"description": "Search Bing for information on the web",
"title": "Search",
"initialRun": true,
"parameters": [{
"name": "searchKeyword",
"description": "Enter your search keywords",
"title": "Keywords"
}]
}
]
}
],
"permissions": [
"identity",
"messageTeamMembers"
],
"validDomains": [
"bingbotservice.azurewebsites.net",
"*.bingbotservice.azurewebsites.net"
]
}
Testen per Upload
Sie können Ihre Nachrichtenerweiterung testen, indem Sie Ihre App hochladen.
Um Ihre Nachrichtenerweiterung zu öffnen, wechseln Sie zu einem Ihrer Chats oder Kanäle. Wählen Sie im Feld Verfassen die Schaltfläche Weitere Optionen (⋯) aus, und wählen Sie Ihre Nachrichtenerweiterung aus.
Hinzufügen von Ereignishandlern
Der Großteil Ihrer Arbeit umfasst das onQuery
-Ereignis, das alle Interaktionen im Nachrichtenerweiterungsfenster behandelt.
Wenn Sie im Manifest auf true
festlegencanUpdateConfiguration
, aktivieren Sie das Menüelement Einstellungen für Ihre Nachrichtenerweiterung und müssen auch und onSettingsUpdate
behandelnonQuerySettingsUrl
.
Behandeln von onQuery-Ereignissen
Eine Nachrichtenerweiterung empfängt ein onQuery
Ereignis, wenn etwas im Nachrichtenerweiterungsfenster geschieht oder an das Fenster gesendet wird.
Wenn Ihre Nachrichtenerweiterung eine Konfigurationsseite verwendet, sollte Ihr Handler für onQuery
zuerst nach gespeicherten Konfigurationsinformationen suchen. Wenn die Nachrichtenerweiterung nicht konfiguriert ist, geben Sie eine config
Antwort mit einem Link zu Ihrer Konfigurationsseite zurück. Die Antwort von der Konfigurationsseite wird auch von onQuery
behandelt. Die einzige Ausnahme ist, wenn die Konfigurationsseite vom Handler für onQuerySettingsUrl
aufgerufen wird. Weitere Informationen finden Sie im folgenden Abschnitt:
Wenn Ihre Nachrichtenerweiterung eine Authentifizierung erfordert, überprüfen Sie die Benutzerstatusinformationen. Wenn der Benutzer nicht angemeldet ist, befolgen Sie die Anweisungen im Abschnitt Authentifizierung weiter unten in diesem Artikel.
Überprüfen Sie als Nächstes, ob initialRun
festgelegt ist. Wenn ja, führen Sie entsprechende Maßnahmen aus, z. B. Das Bereitstellen von Anweisungen oder eine Liste von Antworten.
Der Rest des Handlers für onQuery
fordert den Benutzer zur Eingabe von Informationen auf, zeigt eine Liste der Vorschaukarten an und gibt die vom Benutzer ausgewählte Karte zurück.
Behandeln von onQuerySettingsUrl- und onSettingsUpdate-Ereignissen
Die onQuerySettingsUrl
Ereignisse und onSettingsUpdate
werden zusammen verwendet, um das Menüelement Einstellungen zu aktivieren.
Ihr Handler für onQuerySettingsUrl
gibt die URL für die Konfigurationsseite zurück. Nachdem die Konfigurationsseite geschlossen wurde, akzeptiert und speichert Ihr Handler für onSettingsUpdate
den zurückgegebenen Zustand. Dies ist der fall, in dem onQuery
die Antwort von der Konfigurationsseite nicht empfangen wird.
Empfangen und Beantworten von Abfragen
Jede Anforderung an Ihre Nachrichtenerweiterung erfolgt über ein Activity
-Objekt, das an Ihre Rückruf-URL gesendet wird. Die Anforderung enthält Informationen zum Benutzerbefehl, z. B. ID- und Parameterwerte. Die Anforderung enthält auch Metadaten zum Kontext, in dem Ihre Erweiterung aufgerufen wurde, einschließlich Benutzer- und Mandanten-ID sowie Chat-ID oder Kanal- und Team-IDs.
Empfangen von Benutzeranforderungen
Wenn ein Benutzer eine Abfrage ausführt, sendet Microsoft Teams Ihrem Dienst ein Bot Framework-Standardobjekt Activity
. Ihr Dienst sollte seine Logik für eine Activity
ausführen, die auf invoke
einen unterstützten Typ festgelegt und name
auf einen unterstützten composeExtensions
Typ festgelegt hattype
, wie in der folgenden Tabelle gezeigt.
Zusätzlich zu den Standardmäßigen Botaktivitätseigenschaften enthält die Nutzlast die folgenden Anforderungsmetadaten:
Eigenschaftenname | Zweck |
---|---|
type |
Art der Anforderung; muss sein invoke . |
name |
Art des Befehls, der für Ihren Dienst ausgegeben wird. Die folgenden Typen werden unterstützt:composeExtension/query composeExtension/querySettingUrl composeExtension/setting composeExtension/selectItem composeExtension/queryLink |
from.id |
ID des Benutzers, der die Anforderung gesendet hat. |
from.name |
Name des Benutzers, der die Anforderung gesendet hat. |
from.aadObjectId |
Microsoft Entra-Objekt-ID des Benutzers, der die Anforderung gesendet hat. |
channelData.tenant.id |
Microsoft Entra-Mandanten-ID. |
channelData.channel.id |
Kanal-ID (wenn die Anforderung in einem Kanal erfolgt ist). |
channelData.team.id |
Team-ID (wenn die Anforderung in einem Kanal erfolgt ist). |
clientInfo |
Optionale Metadaten über die Clientsoftware, die zum Senden der Nachricht eines Benutzers verwendet wird. Die Entität kann zwei Eigenschaften enthalten: Das country Feld enthält den erkannten Speicherort des Benutzers.Das platform Feld beschreibt die Messagingclientplattform. Weitere Informationen finden Sie unterNicht-IRI-Entitätstypen – clientInfo. |
Die Anforderungsparameter befinden sich im Value-Objekt, das die folgenden Eigenschaften enthält:
Eigenschaftenname | Zweck |
---|---|
commandId |
Der Name des vom Benutzer aufgerufenen Befehls, der mit einem der im App-Manifest deklarierten Befehle übereinstimmt. |
parameters |
Array von Parametern: Jedes Parameterobjekt enthält den Parameternamen zusammen mit dem vom Benutzer bereitgestellten Parameterwert. |
queryOptions |
Paginierungsparameter:skip : Anzahl für diese Abfrage überspringencount : Anzahl der zurückzugebenden Elemente |
Anforderungsbeispiel
{
"name": "composeExtension/query",
"value": {
"commandId": "searchCmd",
"parameters": [
{
"name": "searchKeywords",
"value": "Toronto"
}
],
"queryOptions": {
"skip": 0,
"count": 25
}
},
"type": "invoke",
"timestamp": "2017-05-01T15:45:51.876Z",
"localTimestamp": "2017-05-01T08:45:51.876-07:00",
"id": "f:622749630322482883",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1C7dbRrC_5yzN1RGtZIrcWT0xz88KPGP9sxdpVpV8sODlgPHeQE9RqQ02hnpuKzy6zZ-AaZx6swUOMj_Dsdse3TQ4sIaeebbFBF-VgjJy_nY",
"name": "Larry Jin",
"aadObjectId": "cd723fa0-0591-416a-9290-e93ecf3a9b92"
},
"conversation": {
"id": "19:skypespaces_8198cfe0dd2647ae91930f0974768a40@thread.skype"
},
"recipient": {
"id": "28:b4922ea1-5315-4fd0-9b21-d941ab06e39f",
"name": "TheComposeExtensionDev"
},
"entities": [
{
"type": "clientInfo",
"country": "US",
"platform": "Windows"
}
]
}
Empfangen von Anforderungen von Links, die in das Feld zum Verfassen von Nachrichten eingefügt wurden
Alternativ (oder zusätzlich) zum Durchsuchen Ihres externen Diensts können Sie eine in das Meldungsfeld zum Verfassen eingefügte URL verwenden, um Ihren Dienst abzufragen und eine Karte zurückzugeben. Im folgenden Screenshot hat ein Benutzer eine URL für ein Arbeitselement in Azure DevOps eingefügt, das die Nachrichtenerweiterung in eine Karte aufgelöst hat.
Damit Ihre Nachrichtenerweiterung auf diese Weise mit Links interagieren kann, müssen Sie das messageHandlers
Array zunächst ihrem App-Manifest hinzufügen, wie im Beispiel gezeigt:
"composeExtensions": [
{
"botId": "abc123456-ab12-ab12-ab12-abcdef123456",
"messageHandlers": [
{
"type": "link",
"value": {
"domains": [
"*.trackeddomain.com"
]
}
}
]
}
]
Nachdem Sie die Domäne hinzugefügt haben, um am App-Manifest zu lauschen, müssen Sie Ihren Botcode so ändern, dass er auf die folgende Aufrufanforderung antwortet .
{
"type": "invoke",
"name": "composeExtension/queryLink",
"value": {
"url": "https://theurlsubmittedbyyouruser.trackeddomain.com/id/1234"
}
}
Wenn Ihre App mehrere Elemente zurückgibt, wird nur das erste verwendet.
Reagieren auf Benutzeranforderungen
Wenn der Benutzer eine Abfrage ausführt, gibt Teams eine synchrone HTTP-Anforderung an Ihren Dienst aus. Während dieser Zeit hat Ihr Code 5 Sekunden Zeit, um eine HTTP-Antwort auf die Anforderung bereitzustellen. Während dieser Zeit kann Ihr Dienst eine weitere Suche oder eine andere Geschäftslogik durchführen, die für die Anforderung erforderlich ist.
Ihr Dienst sollte mit den Ergebnissen antworten, die der Benutzerabfrage entsprechen. Die Antwort muss einen HTTP-Statuscode von 200 OK
und ein gültiges application/json-Objekt mit folgendem Text angeben:
Eigenschaftenname | Zweck |
---|---|
composeExtension |
Antwortumschlag der obersten Ebene. |
composeExtension.type |
Typ der Antwort. Die folgenden Typen werden unterstützt:result : zeigt eine Liste der Suchergebnisse an.auth : Fordert den Benutzer zur Authentifizierung auf.config : Fordert den Benutzer auf, die Nachrichtenerweiterung einzurichten.message : zeigt eine Nur-Text-Nachricht an. |
composeExtension.attachmentLayout |
Gibt das Layout der Anlagen an. Wird für Antworten vom Typ result verwendet. Die folgenden Typen werden unterstützt: list : eine Liste von Kartenobjekten, die Miniaturansichten, Titel und Textfelder enthaltengrid : ein Raster mit Miniaturansichten |
composeExtension.attachments |
Array gültiger Anlagenobjekte. Wird für Antworten vom Typ result verwendet. Die folgenden Typen werden unterstützt: application/vnd.microsoft.card.thumbnail application/vnd.microsoft.card.hero application/vnd.microsoft.teams.card.o365connector application/vnd.microsoft.card.adaptive |
composeExtension.suggestedActions |
Vorgeschlagene Aktionen. Wird für Antworten vom Typ auth oder config verwendet. |
composeExtension.text |
Anzuzeigende Meldung. Wird für Antworten vom Typ message verwendet. |
Antwortkartentypen und Vorschauen
Wir unterstützen die folgenden Anlagentypen:
Weitere Informationen finden Sie unter Karten für eine Übersicht.
Informationen zur Verwendung der Miniaturansichten- und Herokartentypen finden Sie unter Hinzufügen von Karten und Kartenaktionen.
Weitere Informationen zur Connectorkarte für Microsoft 365-Gruppen finden Sie unter Verwenden der Connectorkarte für Microsoft 365-Gruppen.
Die Ergebnisliste wird auf der Microsoft Teams-Benutzeroberfläche mit einer Vorschau der einzelnen Elemente angezeigt. Die Vorschau wird auf eine von zwei Arten generiert:
- Verwenden der
preview
-Eigenschaft imattachment
-Objekt. Diepreview
Anlage kann nur eine Hero- oder Miniaturansichtskarte sein. - Extrahiert aus den grundlegenden
title
Eigenschaften ,text
undimage
der Anlage. Diese werden nur verwendet, wenn diepreview
Eigenschaft nicht festgelegt ist und diese Eigenschaften verfügbar sind.
Sie können eine Vorschau einer adaptiven Karte oder einer Connectorkarte für Microsoft 365-Gruppen in der Ergebnisliste anzeigen, indem Sie einfach ihre Vorschaueigenschaft festlegen. Dies ist nicht erforderlich, wenn die Ergebnisse bereits Hero- oder Miniaturansichtskarten sind. Wenn Sie die Vorschauanlage verwenden, muss es sich entweder um eine Hero- oder Miniaturansichtskarte handelt. Wenn keine Vorschaueigenschaft angegeben ist, schlägt die Vorschau der Karte fehl, und es wird nichts angezeigt.
Anforderungsbeispiel
Dieses Beispiel zeigt eine Antwort mit zwei Ergebnissen, die verschiedene Kartenformate kombinieren: Connector für Microsoft 365-Gruppen und Adaptive. Obwohl Sie wahrscheinlich bei einem Kartenformat in Ihrer Antwort bleiben möchten, wird gezeigt, wie die preview
-Eigenschaft jedes Elements in der attachments
Auflistung explizit eine Vorschau im Hero- oder Miniaturansichtsformat definieren muss, wie oben beschrieben.
{
"composeExtension": {
"type": "result",
"attachmentLayout": "list",
"attachments": [
{
"contentType": "application/vnd.microsoft.teams.card.o365connector",
"content": {
"sections": [
{
"activityTitle": "[85069]: Create a cool app",
"activityImage": "https://placekitten.com/200/200"
},
{
"title": "Details",
"facts": [
{
"name": "Assigned to:",
"value": "[Larry Brown](mailto:larryb@example.com)"
},
{
"name": "State:",
"value": "Active"
}
]
}
]
},
"preview": {
"contentType": "application/vnd.microsoft.card.thumbnail",
"content": {
"title": "85069: Create a cool app",
"images": [
{
"url": "https://placekitten.com/200/200"
}
]
}
}
},
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"type": "AdaptiveCard",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Microsoft Corp (NASDAQ: MSFT)",
"size": "medium",
"isSubtle": true
},
{
"type": "TextBlock",
"text": "September 19, 4:00 PM EST",
"isSubtle": true
}
]
},
{
"type": "Container",
"spacing": "none",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "75.30",
"size": "extraLarge"
},
{
"type": "TextBlock",
"text": "▼ 0.20 (0.32%)",
"size": "small",
"color": "attention",
"spacing": "none"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "FactSet",
"facts": [
{
"title": "Open",
"value": "62.24"
},
{
"title": "High",
"value": "62.98"
},
{
"title": "Low",
"value": "62.20"
}
]
}
]
}
]
}
]
}
],
"version": "1.0"
},
"preview": {
"contentType": "application/vnd.microsoft.card.thumbnail",
"content": {
"title": "Microsoft Corp (NASDAQ: MSFT)",
"text": "75.30 ▼ 0.20 (0.32%)"
}
}
}
]
}
}
Standardabfrage
Wenn Sie im Manifest auf true
festlegeninitialRun
, gibt Microsoft Teams eine "Standardabfrage" aus, wenn der Benutzer die Nachrichtenerweiterung zum ersten Mal öffnet. Ihr Dienst kann auf diese Abfrage mit einer Reihe vorab aufgefüllter Ergebnisse antworten. Dies kann nützlich sein, um beispielsweise zuletzt angezeigte Elemente, Favoriten oder andere Informationen anzuzeigen, die nicht von der Benutzereingabe abhängig sind.
Die Standardabfrage hat dieselbe Struktur wie jede reguläre Benutzerabfrage, mit Ausnahme eines Parameters initialRun
, dessen Zeichenfolgenwert ist true
.
Anforderungsbeispiel für eine Standardabfrage
{
"type": "invoke",
"name": "composeExtension/query",
"value": {
"commandId": "searchCmd",
"parameters": [
{
"name": "initialRun",
"value": "true"
}
],
"queryOptions": {
"skip": 0,
"count": 25
}
},
⋮
}
Identifizieren des Benutzers
Jede Anforderung an Ihre Dienste enthält die verschleierte ID des Benutzers, der die Anforderung ausgeführt hat, sowie den Anzeigenamen des Benutzers und die Microsoft Entra-Objekt-ID.
"from": {
"id": "29:1C7dbRrC_5yzN1RGtZIrcWT0xz88KPGP9sxdpVpV8sODlgPHeQE9RqQ02hnpuKzy6zZ-AaZx6swUOMj_Dsdse3TQ4sIaeebbFBF-VgjJy_nY",
"name": "Larry Jin",
"aadObjectId": "cd723fa0-0591-416a-9290-e93ecf3a9b92"
},
Die id
Werte und aadObjectId
entsprechen garantiert dem des authentifizierten Teams-Benutzers. Sie können als Schlüssel verwendet werden, um Anmeldeinformationen oder einen zwischengespeicherten Zustand in Ihrem Dienst nachzuschlagen. Darüber hinaus enthält jede Anforderung die Microsoft Entra-Mandanten-ID des Benutzers, die verwendet werden kann, um die Organisation des Benutzers zu identifizieren. Falls zutreffend, enthält die Anforderung auch die Team- und Kanal-IDs, von denen die Anforderung stammt.
Authentifizierung
Wenn Ihr Dienst eine Benutzerauthentifizierung erfordert, müssen Sie den Benutzer anmelden, bevor der Benutzer die Nachrichtenerweiterung verwenden kann. Wenn Sie einen Bot oder eine Registerkarte geschrieben haben, die den Benutzer anmeldet, sollte dieser Abschnitt vertraut sein.
Die Sequenz sieht wie folgt aus:
- Der Benutzer gibt eine Abfrage aus, oder die Standardabfrage wird automatisch an Ihren Dienst gesendet.
- Ihr Dienst überprüft, ob sich der Benutzer zuerst authentifiziert hat, indem er die Teams-Benutzer-ID überprüft.
- Wenn sich der Benutzer nicht authentifiziert hat, senden Sie eine
auth
Antwort mit eineropenUrl
vorgeschlagenen Aktion einschließlich der Authentifizierungs-URL zurück. - Der Microsoft Teams-Client startet ein Popupfenster, in dem Ihre Webseite mit der angegebenen Authentifizierungs-URL gehostet wird.
- Nachdem sich der Benutzer angemeldet hat, sollten Sie Ihr Fenster schließen und einen "Authentifizierungscode" an den Teams-Client senden.
- Der Teams-Client gibt die Abfrage dann erneut an Ihren Dienst aus, die den in Schritt 5 übergebenen Authentifizierungscode enthält. Ihr Dienst muss überprüfen, ob der in Schritt 6 empfangene Authentifizierungscode mit dem aus Schritt 5 übereinstimmt, wodurch sichergestellt wird, dass ein böswilliger Benutzer nicht versucht, den Anmeldeflow zu spoofen oder zu kompromittieren. Dies wird effektiv „die Schleife schließen“, um die sichere Authentifizierungssequenz abzuschließen.
Antworten mit einer Anmeldeaktion
Um einen nicht authentifizierten Benutzer zur Anmeldung aufzufordern, antworten Sie mit einer vorgeschlagenen Aktion vom Typ openUrl
, welche die Authentifizierungs-URL enthält.
Antwortbeispiel für eine Anmeldeaktion
{
"composeExtension":{
"type":"auth",
"suggestedActions":{
"actions":[
{
"type": "openUrl",
"value": "https://example.com/auth",
"title": "Sign in to this app"
}
]
}
}
}
Hinweis
Damit die Anmeldeoberfläche in einem Teams-Popup gehostet werden kann, muss sich der Domänenteil der URL in der Liste der gültigen Domänen Ihrer App befinden. Weitere Informationen finden Sie unter validDomains im Manifestschema.
Starten des Anmeldeflows
Ihre Anmeldung muss reaktionsfähig sein und in ein Popupfenster passen. Sie sollte in das Microsoft Teams JavaScript-Client SDK integriert werden, das die Nachrichtenübergabe verwendet.
Wie bei anderen eingebetteten Umgebungen, die in Teams ausgeführt werden, muss Ihr Code im Fenster zuerst aufrufen microsoftTeams.initialize()
. Wenn Ihr Code einen OAuth-Flow ausführt, können Sie die Teams-Benutzer-ID an Ihr Fenster übergeben, die sie dann an die URL der OAuth-Anmelde-URL übergeben kann.
Abschließen des Anmeldeflows
Wenn die Anmeldeanforderung abgeschlossen ist und zurück zu Ihrer Seite weitergeleitet wird, sollten die folgenden Schritte ausgeführt werden:
- Generieren sie einen Sicherheitscode. (Dies kann eine Zufallszahl sein.) Sie müssen diesen Code zusammen mit den Anmeldeinformationen, die sie durch die Anmeldung erhalten haben, wie z. B. OAuth 2.0-Token, in Ihrem Dienst zwischenspeichern.
- Rufen Sie
microsoftTeams.authentication.notifySuccess
auf, und übergeben Sie den Sicherheitscode.
An diesem Punkt wird das Fenster geschlossen, und die Steuerung wird an den Teams-Client übergeben. Der Client kann nun die ursprüngliche Benutzerabfrage zusammen mit dem Sicherheitscode in der state
-Eigenschaft erneut ausführen. Ihr Code kann den Sicherheitscode verwenden, um die zuvor gespeicherten Anmeldeinformationen nachzuschlagen, um die Authentifizierungssequenz abzuschließen und dann die Benutzeranforderung abzuschließen.
Beispiel für neu ausgestellte Anforderung
{
"name": "composeExtension/query",
"value": {
"commandId": "insertWiki",
"parameters": [{
"name": "searchKeyword",
"value": "lakers"
}],
"state": "12345",
"queryOptions": {
"skip": 0,
"count": 25
}
},
"type": "invoke",
"timestamp": "2017-04-26T05:18:25.629Z",
"localTimestamp": "2017-04-25T22:18:25.629-07:00",
"entities": [{
"type": "clientInfo",
"country": "US",
"platform": "Web",
}],
"text": "",
"attachments": [],
"address": {
"id": "f:7638210432489287768",
"channelId": "msteams",
"user": {
"id": "29:1A5TJWHkbOwSyu_L9Ktk9QFI1d_kBOEPeNEeO1INscpKHzHTvWfiau5AX_6y3SuiOby-r73dzHJ17HipUWqGPgw",
"aadObjectId": "fc8ca1c0-d043-4af6-b09f-141536207403"
},
"conversation": {
"id": "19:7705841b240044b297123ad7f9c99217@thread.skype"
},
"bot": {
"id": "28:c073afa8-7e77-4f92-b3e7-aa589e952a3e",
"name": "maotestbot2"
},
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"useAuth": true
},
"source": "msteams"
}
SDK-Unterstützung
.NET
Um Abfragen mit dem Bot Builder SDK für .NET zu empfangen und zu verarbeiten, können Sie den Aktionstyp für die eingehende Aktivität überprüfen invoke
und dann die Hilfsmethode im NuGet-Paket Microsoft.Bot.Connector.Teams verwenden, um zu bestimmen, ob es sich um eine Nachrichtenerweiterungsaktivität handelt.
Beispielcode in .NET
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Invoke) // Received an invoke
{
if (activity.IsComposeExtensionQuery())
{
// This is the response object that will get sent back to the messaging extension request.
ComposeExtensionResponse invokeResponse = null;
// This helper method gets the query as an object.
var query = activity.GetComposeExtensionQueryData();
if (query.CommandId != null && query.Parameters != null && query.Parameters.Count > 0)
{
// query.Parameters has the parameters sent by client
var results = new ComposeExtensionResult()
{
AttachmentLayout = "list",
Type = "result",
Attachments = new List<ComposeExtensionAttachment>(),
};
invokeResponse.ComposeExtension = results;
}
// Return the response
return Request.CreateResponse<ComposeExtensionResponse>(HttpStatusCode.OK, invokeResponse);
} else
{
// Handle other types of Invoke activities here.
}
} else {
// Failure case catch-all.
var response = Request.CreateResponse(HttpStatusCode.BadRequest);
response.Content = new StringContent("Invalid request! This API supports only messaging extension requests. Check your query and try again");
return response;
}
}
Node.js
Beispielcode in Node.js
require('dotenv').config();
import * as restify from 'restify';
import * as builder from 'botbuilder';
import * as teamBuilder from 'botbuilder-teams';
class App {
run() {
const server = restify.createServer();
let teamChatConnector = new teamBuilder.TeamsChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
// Command ID must match what's defined in manifest
teamChatConnector.onQuery('<%= commandId %>',
(event: builder.IEvent,
query: teamBuilder.ComposeExtensionQuery,
callback: (err: Error, result: teamBuilder.IComposeExtensionResponse, statusCode: number) => void) => {
// Check for initialRun; i.e., when you should return default results
// if (query.parameters[0].name === 'initialRun') {}
// Check query.queryOptions.count and query.queryOptions.skip for paging
// Return auth response
// let response = teamBuilder.ComposeExtensionResponse.auth().actions([
// builder.CardAction.openUrl(null, 'https://authUrl', 'Please sign in')
// ]).toResponse();
// Return config response
// let response = teamBuilder.ComposeExtensionResponse.config().actions([
// builder.CardAction.openUrl(null, 'https://configUrl', 'Please sign in')
// ]).toResponse();
// Return result response
let response = teamBuilder.ComposeExtensionResponse.result('list').attachments([
new builder.ThumbnailCard()
.title('Test thumbnail card')
.text('This is a test thumbnail card')
.images([new builder.CardImage().url('https://bot-framework.azureedge.net/bot-icons-v1/bot-framework-default-9.png')])
.toAttachment()
]).toResponse();
callback(null, response, 200);
});
server.post('/api/composeExtension', teamChatConnector.listen());
server.listen(process.env.PORT, () => console.log(`listening to port:` + process.env.PORT));
}
}
const app = new App();
app.run();