Rechercher avec des extensions de message
Importante
Les articles de cette section sont basés sur le Kit de développement logiciel (SDK) Bot Framework v3. Si vous recherchez la documentation actuelle (version 4.6 ou ultérieure du SDK), consultez la section Interactions orientées tâches avec les extensions de message .
Les extensions de message basées sur la recherche vous permettent d’interroger votre service et de publier ces informations sous la forme d’une carte, directement dans votre message.
Les sections suivantes décrivent comment procéder :
Ajouter une extension de message à votre application
Une extension de message est un service hébergé dans le cloud qui écoute les demandes des utilisateurs et répond avec des données structurées, telles qu’une carte. Vous intégrez votre service à Microsoft Teams via des objets Bot Framework Activity
. Nos extensions .NET et Node.js pour le Kit de développement logiciel (SDK) Bot Builder peuvent vous aider à ajouter des fonctionnalités d’extension de message à votre application.
S’inscrire dans Bot Framework
Vous devez d’abord inscrire un bot auprès de Microsoft Bot Framework. L’ID d’application Microsoft et les points de terminaison de rappel de votre bot, tels qu’ils sont définis ici, sont utilisés dans votre extension de message pour recevoir et répondre aux demandes des utilisateurs. N’oubliez pas d’activer le canal Microsoft Teams pour votre bot.
Notez l’ID de votre application bot et le mot de passe de votre application. Vous devez fournir l’ID d’application dans le manifeste de votre application.
Mettre à jour le manifeste de l’application
Comme avec les bots et les onglets, vous mettez à jour le manifeste de votre application pour inclure les propriétés d’extension de message. Ces propriétés régissent la façon dont votre extension de message apparaît et se comporte dans le client Microsoft Teams. Les extensions de message sont prises en charge à partir du manifeste v1.0.
Déclarer votre extension de message
Pour ajouter une extension de message, incluez une nouvelle structure JSON de niveau supérieur dans votre manifeste avec la composeExtensions
propriété . Vous êtes limité à la création d’une seule extension de message pour votre application.
Remarque
Le manifeste fait référence aux extensions de message en tant que composeExtensions
. Il s’agit de maintenir la compatibilité descendante.
La définition d’extension est un objet qui a la structure suivante :
Nom de la propriété | Objectif | Obligatoire ? |
---|---|---|
botId |
ID d’application Microsoft unique pour le bot inscrit dans le Bot Framework. Cela doit généralement être identique à l’ID de votre application Teams globale. | Oui |
scopes |
Tableau déclarant si cette extension peut être ajoutée aux personal étendues ou team (ou aux deux). |
Oui |
canUpdateConfiguration |
Active l’élément de menu Paramètres. | Non |
commands |
Tableau de commandes que cette extension de message prend en charge. Vous êtes limité à 10 commandes. | Oui |
Remarque
Si vous définissez la canUpdateConfiguration
propriété true
sur dans le manifeste de l’application, vous pouvez afficher l’élément de menu Paramètres de votre extension de message. Pour activer les paramètres, vous devez également gérer onQuerySettingsUrl
et onSettingsUpdate
.
Définir des commandes
Votre extension de message doit déclarer une commande, qui s’affiche lorsque l’utilisateur sélectionne votre application à partir du bouton Plus d’options (⋯) dans la zone de composition.
Dans le manifeste de l’application, votre élément de commande est un objet avec la structure suivante :
Nom de la propriété | Objectif | Obligatoire ? | Version minimale du manifeste |
---|---|---|---|
id |
ID unique que vous affectez à cette commande. La demande de l’utilisateur inclut cet ID. | Oui | 1.0 |
title |
Nom de la commande. Cette valeur apparaît dans l’interface utilisateur. | Oui | 1.0 |
description |
Texte d’aide indiquant l’action de cette commande. Cette valeur apparaît dans l’interface utilisateur. | Oui | 1.0 |
type |
Définissez le type de commande. Les valeurs possibles sont query et action . S’il n’est pas présent, la valeur par défaut est définie sur query . |
Non | 1.4 |
initialRun |
Paramètre facultatif, utilisé avec query les commandes. Si la valeur est true, indique que cette commande doit être exécutée dès que l’utilisateur choisit cette commande dans l’interface utilisateur. |
Non | 1.0 |
fetchTask |
Paramètre facultatif, utilisé avec action les commandes. Définissez la valeur true pour extraire la carte adaptative ou l’URL web à afficher dans le module de tâche. Il est utilisé lorsque l’entrée de la action commande est dynamique, par opposition à un ensemble statique de paramètres. Notez que si la valeur est true, la liste de paramètres statiques de la commande est ignorée. |
Non | 1.4 |
parameters |
Liste statique des paramètres de la commande. | Oui | 1.0 |
parameter.name |
Le nom du paramètre. Il est envoyé à votre service dans la demande de l’utilisateur. | Oui | 1.0 |
parameter.description |
Décrit les objectifs de ce paramètre et l’exemple de la valeur qui doit être fournie. Cette valeur apparaît dans l’interface utilisateur. | Oui | 1.0 |
parameter.title |
Titre ou étiquette court du paramètre convivial. | Oui | 1.0 |
parameter.inputType |
Définissez sur le type d’entrée requis. Les valeurs possibles incluent text , textarea , number , date , time , toggle . La valeur par défaut est définie sur text . |
Non | 1.4 |
context |
Tableau facultatif de valeurs qui définit le contexte dans lequel l’action de message est disponible. Les valeurs possibles sont message , compose ou commandBox . La valeur par défaut est ["compose", "commandBox"] . |
Non | 1,5 |
Extensions de message de type de recherche
Pour l’extension de message basée sur la recherche, définissez le type
paramètre sur query
. Voici un exemple de manifeste avec une seule commande de recherche. Une seule extension de message peut avoir jusqu’à 10 commandes différentes associées. Cela peut inclure plusieurs commandes de recherche et plusieurs commandes basées sur une action.
Exemple de manifeste d’application complet
{
"$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"
]
}
Tester via le chargement
Vous pouvez tester votre extension de message en chargeant votre application.
Pour ouvrir votre extension de message, accédez à l’une de vos conversations ou canaux. Choisissez le bouton Plus d’options (⋯) dans la zone de composition, puis choisissez votre extension de message.
Ajouter des gestionnaires d’événements
La plupart de votre travail implique l’événement onQuery
, qui gère toutes les interactions dans la fenêtre d’extension de message.
Si vous définissez canUpdateConfiguration
true
sur dans le manifeste, vous activez l’élément de menu Paramètres pour votre extension de message et devez également gérer onQuerySettingsUrl
et onSettingsUpdate
.
Gérer les événements onQuery
Une extension de message reçoit un onQuery
événement quand quelque chose se produit dans la fenêtre d’extension de message ou est envoyé à la fenêtre.
Si votre extension de message utilise une page de configuration, votre gestionnaire pour onQuery
doit d’abord vérifier les informations de configuration stockées ; si l’extension de message n’est pas configurée, renvoyez une config
réponse avec un lien vers votre page de configuration. La réponse de la page de configuration est également gérée par onQuery
. La seule exception est lorsque la page de configuration est appelée par le gestionnaire pour onQuerySettingsUrl
; consultez la section suivante :
Si votre extension de message nécessite une authentification, vérifiez les informations d’état utilisateur. Si l’utilisateur n’est pas connecté, suivez les instructions de la section Authentification plus loin dans cet article.
Ensuite, vérifiez si initialRun
est défini ; si c’est le cas, prenez les mesures appropriées, telles que la fourniture d’instructions ou d’une liste de réponses.
Le reste de votre gestionnaire pour onQuery
invite l’utilisateur à fournir des informations, affiche une liste de cartes d’aperçu et retourne la carte sélectionnée par l’utilisateur.
Gérer les événements onQuerySettingsUrl et onSettingsUpdate
Les onQuerySettingsUrl
événements et onSettingsUpdate
fonctionnent ensemble pour activer l’élément de menu Paramètres .
Votre gestionnaire pour onQuerySettingsUrl
retourne l’URL de la page de configuration ; une fois la page de configuration fermée, votre gestionnaire pour onSettingsUpdate
accepte et enregistre l’état retourné. Il s’agit du seul cas dans lequel onQuery
ne reçoit pas la réponse de la page de configuration.
Recevoir des requêtes et y répondre
Chaque demande à votre extension de message est effectuée via un Activity
objet qui est publié dans votre URL de rappel. La requête contient des informations sur la commande utilisateur, telles que les valeurs d’ID et de paramètre. La requête fournit également des métadonnées sur le contexte dans lequel votre extension a été appelée, y compris l’ID d’utilisateur et de locataire, ainsi que les ID de conversation ou de canal et d’équipe.
Recevoir les demandes des utilisateurs
Lorsqu’un utilisateur effectue une requête, Microsoft Teams envoie à votre service un objet Bot Framework Activity
standard. Votre service doit exécuter sa logique pour un Activity
qui a type
défini invoke
sur et name
défini sur un type pris en charge composeExtensions
, comme indiqué dans le tableau suivant.
En plus des propriétés d’activité standard du bot, la charge utile contient les métadonnées de requête suivantes :
Nom de la propriété | Objectif |
---|---|
type |
Type de demande ; doit être invoke . |
name |
Type de commande qui est émise à votre service. Les types suivants sont pris en charge :composeExtension/query composeExtension/querySettingUrl composeExtension/setting composeExtension/selectItem composeExtension/queryLink |
from.id |
Identification de l'utilisateur qui a envoyé la demande. |
from.name |
Nom de l'utilisateur qui a envoyé la demande. |
from.aadObjectId |
ID d’objet Microsoft Entra de l’utilisateur qui a envoyé la demande. |
channelData.tenant.id |
ID de locataire Microsoft Entra. |
channelData.channel.id |
Identification du canal (si la demande a été faite dans un canal). |
channelData.team.id |
Identification de l'équipe (si la demande a été faite dans un canal). |
clientInfo |
Métadonnées facultatives sur le logiciel client utilisé pour envoyer le message d’un utilisateur. L’entité peut contenir deux propriétés : Le country champ contient l’emplacement détecté de l’utilisateur.Le platform champ décrit la plateforme cliente de messagerie. Pour plus d’informations, consultezTypes d’entités non-IRI — clientInfo. |
Les paramètres de requête se trouvent dans l’objet value, qui inclut les propriétés suivantes :
Nom de la propriété | Objectif |
---|---|
commandId |
Nom de la commande appelée par l’utilisateur, correspondant à l’une des commandes déclarées dans le manifeste de l’application. |
parameters |
Tableau de paramètres : chaque objet de paramètre contient le nom du paramètre, ainsi que la valeur de paramètre fournie par l’utilisateur. |
queryOptions |
Paramètres de pagination :skip : nombre d’ignores pour cette requêtecount : nombre d’éléments à retourner |
Exemple de requête
{
"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"
}
]
}
Recevoir des demandes à partir de liens insérés dans la boîte de message de rédaction
Comme alternative (ou en plus) à la recherche de votre service externe, vous pouvez utiliser une URL insérée dans la zone de message de composition pour interroger votre service et retourner une carte. Dans la capture d’écran ci-dessous, un utilisateur a collé une URL pour un élément de travail dans Azure DevOps, que l’extension de message a résolue dans une carte.
Pour permettre à votre extension de message d’interagir avec les liens de cette façon, vous devez d’abord ajouter le messageHandlers
tableau au manifeste de votre application, comme dans l’exemple :
"composeExtensions": [
{
"botId": "abc123456-ab12-ab12-ab12-abcdef123456",
"messageHandlers": [
{
"type": "link",
"value": {
"domains": [
"*.trackeddomain.com"
]
}
}
]
}
]
Une fois que vous avez ajouté le domaine pour écouter le manifeste de l’application, vous devez modifier le code de votre bot pour répondre à la demande d’appel ci-dessous.
{
"type": "invoke",
"name": "composeExtension/queryLink",
"value": {
"url": "https://theurlsubmittedbyyouruser.trackeddomain.com/id/1234"
}
}
Si votre application retourne plusieurs éléments, seul le premier est utilisé.
Répondre aux demandes des utilisateurs
Lorsque l’utilisateur exécute une requête, Teams émet une requête HTTP synchrone à votre service. Pendant ce temps, votre code dispose de 5 secondes pour fournir une réponse HTTP à la requête. Pendant ce temps, votre service peut effectuer une autre recherche ou toute autre logique métier nécessaire pour traiter la requête.
Votre service doit répondre avec les résultats correspondant à la requête de l’utilisateur. La réponse doit indiquer un code d’état HTTP et 200 OK
un objet application/json valide avec le corps suivant :
Nom de la propriété | Objectif |
---|---|
composeExtension |
Enveloppe de réponse de niveau supérieur. |
composeExtension.type |
Type de réponse. Les types suivants sont pris en charge :result : affiche une liste de résultats de rechercheauth : invite l’utilisateur à s’authentifierconfig : invite l’utilisateur à configurer l’extension de messagemessage : affiche un message en texte brut. |
composeExtension.attachmentLayout |
Spécifie la disposition des pièces jointes. Utilisé pour les réponses de type result . Les types suivants sont pris en charge : list : liste d’objets de carte contenant des champs miniature, titre et textegrid : grille d’images miniatures |
composeExtension.attachments |
Tableau d’objets de pièce jointe valides. Utilisé pour les réponses de type result . Les types suivants sont pris en charge : application/vnd.microsoft.card.thumbnail application/vnd.microsoft.card.hero application/vnd.microsoft.teams.card.o365connector application/vnd.microsoft.card.adaptive |
composeExtension.suggestedActions |
Actions suggérées. Utilisé pour les réponses de type auth ou config . |
composeExtension.text |
Message à afficher. Utilisé pour les réponses de type message . |
Types de cartes de réponse et aperçus
Nous prenons en charge les types de pièces jointes suivants :
- Carte miniature
- Carte de bannière
- Carte de connecteur pour les groupes Microsoft 365
- Carte adaptative
Pour plus d’informations, consultez Cartes pour une vue d’ensemble.
Pour savoir comment utiliser les types de cartes miniature et héros, consultez Ajouter des cartes et des actions de carte.
Pour plus d’informations sur la carte de connecteur pour les groupes Microsoft 365, consultez Utilisation de la carte de connecteur pour les groupes Microsoft 365.
La liste des résultats s’affiche dans l’interface utilisateur de Microsoft Teams avec un aperçu de chaque élément. La préversion est générée de l’une des deux manières suivantes :
- Utilisation de la
preview
propriété dans l’objetattachment
. Lapreview
pièce jointe ne peut être qu’une carte Héros ou Miniature. - Extrait des propriétés de base
title
,text
etimage
de la pièce jointe. Elles sont utilisées uniquement si lapreview
propriété n’est pas définie et que ces propriétés sont disponibles.
Vous pouvez afficher un aperçu d’une carte adaptative ou de connecteur pour les groupes Microsoft 365 dans la liste des résultats simplement en définissant sa propriété d’aperçu. Cela n’est pas nécessaire si les résultats sont déjà des cartes héroïque ou miniature. Si vous utilisez la pièce jointe en préversion, il doit s’agir d’une carte Hero ou d’une miniature. Si aucune propriété d’aperçu n’est spécifiée, l’aperçu de la carte échoue et rien n’est affiché.
Exemple de réponse
Cet exemple montre une réponse avec deux résultats, combinant différents formats de carte : Connecteur pour les groupes Microsoft 365 et Adaptatif. Bien que vous souhaitiez probablement conserver un format de carte dans votre réponse, il montre comment la preview
propriété de chaque élément de la attachments
collection doit définir explicitement un aperçu au format héros ou miniature, comme décrit ci-dessus.
{
"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%)"
}
}
}
]
}
}
Requête par défaut
Si vous définissez initialRun
true
sur dans le manifeste, Microsoft Teams émet une requête « par défaut » lorsque l’utilisateur ouvre l’extension de message pour la première fois. Votre service peut répondre à cette requête avec un ensemble de résultats préremplies. Cela peut être utile pour afficher, par exemple, les éléments récemment consultés, les favoris ou toute autre information qui ne dépend pas de l’entrée utilisateur.
La requête par défaut a la même structure que toute requête d’utilisateur standard, sauf avec un paramètre initialRun
dont la valeur de chaîne est true
.
Exemple de requête pour une requête par défaut
{
"type": "invoke",
"name": "composeExtension/query",
"value": {
"commandId": "searchCmd",
"parameters": [
{
"name": "initialRun",
"value": "true"
}
],
"queryOptions": {
"skip": 0,
"count": 25
}
},
⋮
}
Identifier l’utilisateur
Chaque demande adressée à vos services inclut l’ID obfusqué de l’utilisateur qui a effectué la demande, ainsi que le nom d’affichage de l’utilisateur et l’ID d’objet Microsoft Entra.
"from": {
"id": "29:1C7dbRrC_5yzN1RGtZIrcWT0xz88KPGP9sxdpVpV8sODlgPHeQE9RqQ02hnpuKzy6zZ-AaZx6swUOMj_Dsdse3TQ4sIaeebbFBF-VgjJy_nY",
"name": "Larry Jin",
"aadObjectId": "cd723fa0-0591-416a-9290-e93ecf3a9b92"
},
Les id
valeurs et aadObjectId
sont garanties comme celles de l’utilisateur Teams authentifié. Elles peuvent être utilisées comme clés pour rechercher des informations d’identification ou tout état mis en cache dans votre service. En outre, chaque requête contient l’ID de locataire Microsoft Entra de l’utilisateur, qui peut être utilisé pour identifier l’organisation de l’utilisateur. Le cas échéant, la demande contient également les ID d’équipe et de canal d’où provient la demande.
Authentification
Si votre service nécessite l’authentification de l’utilisateur, vous devez connecter l’utilisateur avant que l’utilisateur puisse utiliser l’extension de message. Si vous avez écrit un bot ou un onglet qui connecte l’utilisateur, cette section doit être familière.
La séquence est la suivante :
- L’utilisateur émet une requête, ou la requête par défaut est automatiquement envoyée à votre service.
- Votre service vérifie si l’utilisateur s’est d’abord authentifié en inspectant l’ID utilisateur Teams.
- Si l’utilisateur ne s’est pas authentifié, renvoyez une
auth
réponse avec uneopenUrl
action suggérée, y compris l’URL d’authentification. - Le client Microsoft Teams lance une fenêtre contextuelle hébergeant votre page web à l’aide de l’URL d’authentification donnée.
- Une fois que l’utilisateur s’est connecté, vous devez fermer votre fenêtre et envoyer un « code d’authentification » au client Teams.
- Le client Teams réexécute ensuite la requête à votre service, qui inclut le code d’authentification passé à l’étape 5. Votre service doit vérifier que le code d’authentification reçu à l’étape 6 correspond à celui de l’étape 5, ce qui garantit qu’un utilisateur malveillant n’essaie pas d’usurper ou de compromettre le flux de connexion. Cela « ferme la boucle » pour terminer la séquence d’authentification sécurisée.
Répondre avec une action de connexion
Pour inviter un utilisateur non authentifié à se connecter, répondez avec une action suggérée de type openUrl
qui inclut l’URL d’authentification.
Exemple de réponse pour une action de connexion
{
"composeExtension":{
"type":"auth",
"suggestedActions":{
"actions":[
{
"type": "openUrl",
"value": "https://example.com/auth",
"title": "Sign in to this app"
}
]
}
}
}
Remarque
Pour que l’expérience de connexion soit hébergée dans une fenêtre contextuelle Teams, la partie domaine de l’URL doit figurer dans la liste des domaines valides de votre application. Pour plus d’informations, consultez validDomains dans le schéma du manifeste.
Démarrer le flux de connexion
Votre connexion doit être réactive et tenir dans une fenêtre contextuelle. Il doit s’intégrer au kit de développement logiciel (SDK) client JavaScript Microsoft Teams, qui utilise la transmission de messages.
Comme pour les autres expériences incorporées exécutées dans Teams, votre code à l’intérieur de la fenêtre doit d’abord appeler microsoftTeams.initialize()
. Si votre code exécute un flux OAuth, vous pouvez passer l’ID utilisateur Teams dans votre fenêtre, qui peut ensuite le transmettre à l’URL de l’URL de connexion OAuth.
Terminer le flux de connexion
Une fois la demande de connexion terminée et redirigée vers votre page, elle doit effectuer les étapes suivantes :
- Générez un code de sécurité. (Il peut s’agir d’un nombre aléatoire.) Vous devez mettre en cache ce code sur votre service, ainsi que les informations d’identification obtenues par le biais de la connexion, telles que les jetons OAuth 2.0.
- Appelez
microsoftTeams.authentication.notifySuccess
et transmettez le code de sécurité.
À ce stade, la fenêtre se ferme et le contrôle est passé au client Teams. Le client peut maintenant réémettre la requête utilisateur d’origine, ainsi que le code de sécurité dans la state
propriété . Votre code peut utiliser le code de sécurité pour rechercher les informations d’identification stockées précédemment afin de terminer la séquence d’authentification, puis la requête de l’utilisateur.
Exemple de nouvelle publication de requête
{
"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"
}
Prise en charge du Kit de développement logiciel
.NET
Pour recevoir et gérer des requêtes avec le Kit de développement logiciel (SDK) Bot Builder pour .NET, vous pouvez rechercher le invoke
type d’action sur l’activité entrante, puis utiliser la méthode d’assistance dans le package NuGet Microsoft.Bot.Connector.Teams pour déterminer s’il s’agit d’une activité d’extension de message.
Exemple de code dans .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
Exemple de code dans 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();