Búsqueda con extensiones de mensaje
Importante
Los artículos de esta sección se basan en el SDK de Bot Framework v3. Si busca documentación actual (versión 4.6 o posterior del SDK), consulte la sección Interacciones orientadas a tareas con extensiones de mensaje .
Las extensiones de mensaje basadas en búsquedas le permiten consultar el servicio y publicar esa información en forma de tarjeta, directamente en el mensaje.
En las secciones siguientes se describe cómo hacerlo:
Agregar una extensión de mensaje a la aplicación
Una extensión de mensaje es un servicio hospedado en la nube que escucha las solicitudes del usuario y responde con datos estructurados, como una tarjeta. Integre el servicio con Microsoft Teams a través de objetos de Bot Framework Activity
. Nuestras extensiones .NET y Node.js del SDK de Bot Builder pueden ayudarle a agregar la funcionalidad de extensión de mensaje a la aplicación.
Registro en Bot Framework
Primero debe registrar un bot con Microsoft Bot Framework. El identificador de aplicación de Microsoft y los puntos de conexión de devolución de llamada del bot, tal como se define allí, se usan en la extensión de mensaje para recibir y responder a las solicitudes del usuario. No olvide habilitar el canal de Microsoft Teams para el bot.
Tome nota del identificador de la aplicación de bot y la contraseña de la aplicación; debe proporcionar el identificador de la aplicación en el manifiesto de la aplicación.
Actualizar el manifiesto de la aplicación
Al igual que con los bots y las pestañas, se actualiza el manifiesto de la aplicación para incluir las propiedades de la extensión de mensaje. Estas propiedades rigen cómo aparece y se comporta la extensión de mensaje en el cliente de Microsoft Teams. Las extensiones de mensaje se admiten a partir del manifiesto v1.0.
Declaración de la extensión de mensaje
Para agregar una extensión de mensaje, incluya una nueva estructura JSON de nivel superior en el manifiesto con la composeExtensions
propiedad . Está limitado a crear una sola extensión de mensaje para la aplicación.
Nota:
El manifiesto hace referencia a las extensiones de mensaje como composeExtensions
. Esto es para mantener la compatibilidad con versiones anteriores.
La definición de extensión es un objeto que tiene la estructura siguiente:
Nombre de propiedad | Objetivo | ¿Necesario? |
---|---|---|
botId |
El ID. de aplicación de Microsoft único para el bot, registrado con Bot Framework. Normalmente, debe ser el mismo que el identificador de la aplicación general de Teams. | Yes |
scopes |
Matriz que declara si esta extensión se puede agregar a personal o team ámbitos (o ambos). |
Yes |
canUpdateConfiguration |
Habilita el elemento de menú Configuración . | No |
commands |
Matriz de comandos que admite esta extensión de mensaje. Está limitado a 10 comandos. | Yes |
Nota:
Si establece la canUpdateConfiguration
propiedad true
en en el manifiesto de la aplicación, puede mostrar el elemento de menú Configuración de la extensión de mensaje. Para habilitar La configuración, también debe controlar onQuerySettingsUrl
y onSettingsUpdate
.
Definición de comandos
La extensión de mensaje debe declarar un comando, que aparece cuando el usuario selecciona la aplicación en el botón Más opciones (⋯) del cuadro de redacción.
En el manifiesto de la aplicación, el elemento de comando es un objeto con la siguiente estructura:
Nombre de propiedad | Objetivo | ¿Necesario? | Versión mínima del manifiesto |
---|---|---|---|
id |
Identificador único que se asigna a este comando. La solicitud de usuario incluye este id. | Sí | 1.0 |
title |
Nombre del comando. Este valor aparece en la interfaz de usuario. | Sí | 1.0 |
description |
Texto de ayuda que indica lo que hace este comando. Este valor aparece en la interfaz de usuario. | Sí | 1.0 |
type |
Establezca el tipo de comando. Los valores posibles incluyen query y action . Si no está presente, el valor predeterminado se establece en query . |
No | 1.4 |
initialRun |
Parámetro opcional, que se usa con query comandos. Si se establece en true, indica que este comando debe ejecutarse en cuanto el usuario elija este comando en la interfaz de usuario. |
No | 1.0 |
fetchTask |
Parámetro opcional, que se usa con action comandos. Establézcalo en true para capturar la tarjeta adaptable o la dirección URL web que se mostrará en el módulo de tareas. Esto se usa cuando la entrada al action comando es dinámica en lugar de un conjunto estático de parámetros. Tenga en cuenta que si se establece en true, se omite la lista de parámetros estáticos para el comando. |
No | 1.4 |
parameters |
Lista estática de parámetros para el comando. | Sí | 1.0 |
parameter.name |
Nombre del parámetro. Esto se envía al servicio en la solicitud del usuario. | Sí | 1.0 |
parameter.description |
Describe los propósitos de este parámetro y el ejemplo del valor que se debe proporcionar. Este valor aparece en la interfaz de usuario. | Sí | 1.0 |
parameter.title |
Título o etiqueta de parámetros breves fáciles de usar. | Sí | 1.0 |
parameter.inputType |
Establezca en el tipo de entrada necesaria. Entre los valores posibles se incluyen , , , , , toggle time . date number textarea text El valor predeterminado está establecido en text . |
No | 1.4 |
context |
Matriz opcional de valores que define el contexto en el que está disponible la acción del mensaje. Los valores posibles son message , compose o commandBox . El valor predeterminado es ["compose", "commandBox"] . |
No | 1,5 |
Extensiones de mensaje de tipo de búsqueda
Para la extensión de mensaje basada en búsqueda, establezca el type
parámetro en query
. A continuación se muestra un ejemplo de un manifiesto con un único comando de búsqueda. Una sola extensión de mensaje puede tener hasta 10 comandos diferentes asociados. Esto puede incluir varias búsquedas y varios comandos basados en acciones.
Ejemplo de manifiesto de aplicación completo
{
"$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"
]
}
Prueba a través de la carga
Para probar la extensión de mensaje, cargue la aplicación.
Para abrir la extensión de mensaje, vaya a cualquiera de sus chats o canales. Elija el botón Más opciones (⋯) en el cuadro de redacción y elija la extensión del mensaje.
Agregar controladores de eventos
La mayor parte del trabajo implica el onQuery
evento , que controla todas las interacciones en la ventana de extensión de mensaje.
Si establece canUpdateConfiguration
true
en en el manifiesto, habilitará el elemento de menú Configuración para la extensión de mensaje y también debe controlar onQuerySettingsUrl
y onSettingsUpdate
.
Controlar eventos onQuery
Una extensión de mensaje recibe un onQuery
evento cuando ocurre algo en la ventana de extensión de mensaje o se envía a la ventana.
Si la extensión de mensaje usa una página de configuración, el controlador de onQuery
debe comprobar primero si hay información de configuración almacenada; si la extensión de mensaje no está configurada, devuelve una config
respuesta con un vínculo a la página de configuración. La respuesta de la página de configuración también se controla mediante onQuery
. La única excepción es cuando el controlador llama a la página de configuración para onQuerySettingsUrl
; vea la sección siguiente:
Si la extensión de mensaje requiere autenticación, compruebe la información de estado del usuario. Si el usuario no ha iniciado sesión, siga las instrucciones de la sección Autenticación más adelante en este artículo.
A continuación, compruebe si initialRun
está establecido; si es así, realice las acciones adecuadas, como proporcionar instrucciones o una lista de respuestas.
El resto del controlador solicita onQuery
información al usuario, muestra una lista de tarjetas en vista previa y devuelve la tarjeta seleccionada por el usuario.
Controlar eventos onQuerySettingsUrl y onSettingsUpdate
Los onQuerySettingsUrl
eventos y onSettingsUpdate
funcionan juntos para habilitar el elemento de menú Configuración .
El controlador de onQuerySettingsUrl
devuelve la dirección URL de la página de configuración; una vez que se cierra la página de configuración, el controlador de onSettingsUpdate
acepta y guarda el estado devuelto. Este es el único caso en el que onQuery
no recibe la respuesta de la página de configuración.
Recepción y respuesta a consultas
Cada solicitud a la extensión de mensaje se realiza a través de un Activity
objeto que se publica en la dirección URL de devolución de llamada. La solicitud contiene información sobre el comando de usuario, como el identificador y los valores de parámetro. La solicitud también proporciona metadatos sobre el contexto en el que se invocó la extensión, incluidos el identificador de usuario e inquilino, junto con el identificador de chat o el canal y los identificadores de equipo.
Recepción de solicitudes de usuario
Cuando un usuario realiza una consulta, Microsoft Teams envía al servicio un objeto estándar de Bot Framework Activity
. El servicio debe realizar su lógica para un Activity
que se haya type
establecido invoke
en y name
establecido en un tipo admitido composeExtensions
, como se muestra en la tabla siguiente.
Además de las propiedades de actividad de bot estándar, la carga contiene los siguientes metadatos de solicitud:
Nombre de propiedad | Objetivo |
---|---|
type |
Tipo de solicitud; debe ser invoke . |
name |
Tipo de comando que se emite para el servicio. Se admiten los tipos siguientes:composeExtension/query composeExtension/querySettingUrl composeExtension/setting composeExtension/selectItem composeExtension/queryLink |
from.id |
Id. del usuario que envió la solicitud. |
from.name |
Nombre del usuario que envió la solicitud. |
from.aadObjectId |
Identificador de objeto de Microsoft Entra del usuario que envió la solicitud. |
channelData.tenant.id |
Identificador de inquilino de Microsoft Entra. |
channelData.channel.id |
Id. de canal (si la solicitud se realizó en un canal). |
channelData.team.id |
Id. de equipo (si la solicitud se realizó en un canal). |
clientInfo |
Metadatos opcionales sobre el software cliente que se usa para enviar el mensaje de un usuario. La entidad puede contener dos propiedades: El country campo contiene la ubicación detectada del usuario.El platform campo describe la plataforma de cliente de mensajería. Para obtener más información, veaTipos de entidad que no son IRI: clientInfo. |
Los parámetros de solicitud se encuentran en el objeto value, que incluye las siguientes propiedades:
Nombre de propiedad | Objetivo |
---|---|
commandId |
Nombre del comando invocado por el usuario, que coincide con uno de los comandos declarados en el manifiesto de la aplicación. |
parameters |
Matriz de parámetros: cada objeto de parámetro contiene el nombre del parámetro, junto con el valor de parámetro proporcionado por el usuario. |
queryOptions |
Parámetros de paginación:skip : omita el recuento de esta consulta.count : número de elementos que se van a devolver |
Ejemplo de solicitud
{
"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"
}
]
}
Recepción de solicitudes de vínculos insertados en el cuadro de mensaje de redacción
Como alternativa (o además) a la búsqueda en el servicio externo, puede usar una dirección URL insertada en el cuadro de mensaje de redacción para consultar el servicio y devolver una tarjeta. En la captura de pantalla siguiente, un usuario ha pegado una dirección URL para un elemento de trabajo en Azure DevOps, que la extensión de mensaje ha resuelto en una tarjeta.
Para permitir que la extensión de mensaje interactúe con vínculos de esta manera, primero debe agregar la messageHandlers
matriz al manifiesto de la aplicación, como en el ejemplo:
"composeExtensions": [
{
"botId": "abc123456-ab12-ab12-ab12-abcdef123456",
"messageHandlers": [
{
"type": "link",
"value": {
"domains": [
"*.trackeddomain.com"
]
}
}
]
}
]
Una vez que haya agregado el dominio para escuchar el manifiesto de la aplicación, debe cambiar el código del bot para responder a la solicitud de invocación siguiente.
{
"type": "invoke",
"name": "composeExtension/queryLink",
"value": {
"url": "https://theurlsubmittedbyyouruser.trackeddomain.com/id/1234"
}
}
Si la aplicación devuelve varios elementos, solo se usa el primero.
Respuesta a las solicitudes de usuario
Cuando el usuario realiza una consulta, Teams emite una solicitud HTTP sincrónica al servicio. Durante este tiempo, el código tiene 5 segundos para proporcionar una respuesta HTTP a la solicitud. Durante este tiempo, el servicio puede realizar otra búsqueda o cualquier otra lógica de negocios necesaria para atender la solicitud.
El servicio debe responder con los resultados que coincidan con la consulta del usuario. La respuesta debe indicar un código de estado HTTP de 200 OK
y un objeto application/json válido con el siguiente cuerpo:
Nombre de propiedad | Objetivo |
---|---|
composeExtension |
Sobre de respuesta de nivel superior. |
composeExtension.type |
Tipo de respuesta. Se admiten los tipos siguientes:result : muestra una lista de resultados de búsquedaauth : solicita al usuario que se autentiqueconfig : solicita al usuario que configure la extensión de mensaje.message : muestra un mensaje de texto sin formato |
composeExtension.attachmentLayout |
Especifica el diseño de los datos adjuntos. Se usa para respuestas de tipo result . Se admiten los tipos siguientes: list : una lista de objetos de tarjeta que contienen campos de miniatura, título y textogrid : una cuadrícula de imágenes en miniatura |
composeExtension.attachments |
Matriz de objetos de datos adjuntos válidos. Se usa para respuestas de tipo result . Se admiten los tipos siguientes: application/vnd.microsoft.card.thumbnail application/vnd.microsoft.card.hero application/vnd.microsoft.teams.card.o365connector application/vnd.microsoft.card.adaptive |
composeExtension.suggestedActions |
Acciones sugeridas. Se usa para respuestas de tipo auth o config . |
composeExtension.text |
Mensaje que se va a mostrar. Se usa para respuestas de tipo message . |
Tipos y vistas previas de tarjetas de respuesta
Se admiten los siguientes tipos de datos adjuntos:
- Tarjeta miniatura
- Tarjeta de héroe
- Tarjeta del conector para grupos de Microsoft 365
- Tarjeta adaptable
Para obtener más información, consulte Tarjetas para obtener información general.
Para obtener información sobre cómo usar los tipos de miniaturas y tarjetas principales, consulte Agregar tarjetas y acciones de tarjeta.
Para obtener más información sobre la tarjeta del conector para grupos de Microsoft 365, consulte Uso de la tarjeta del conector para grupos de Microsoft 365.
La lista de resultados se muestra en la interfaz de usuario de Microsoft Teams con una vista previa de cada elemento. La versión preliminar se genera de dos maneras:
- Uso de la
preview
propiedad dentro delattachment
objeto . Lospreview
datos adjuntos solo pueden ser una tarjeta de héroe o miniatura. - Extraído de las propiedades básicas
title
,text
yimage
de los datos adjuntos. Solo se usan si lapreview
propiedad no está establecida y estas propiedades están disponibles.
Puede mostrar una vista previa de una tarjeta adaptable o conector para grupos de Microsoft 365 en la lista de resultados simplemente estableciendo su propiedad de vista previa. Esto no es necesario si los resultados ya son tarjetas de héroe o miniatura. Si usa los datos adjuntos de vista previa, debe ser una tarjeta hero o thumbnail. Si no se especifica ninguna propiedad de vista previa, se produce un error en la vista previa de la tarjeta y no se muestra nada.
Ejemplo de respuesta
En este ejemplo se muestra una respuesta con dos resultados, mezclando diferentes formatos de tarjeta: Conector para grupos de Microsoft 365 y Adaptable. Aunque es probable que quieras mantener un formato de tarjeta en la respuesta, muestra cómo la preview
propiedad de cada elemento de la attachments
colección debe definir explícitamente una vista previa en formato de héroe o miniatura, como se describió anteriormente.
{
"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%)"
}
}
}
]
}
}
Consulta predeterminada
Si establece initialRun
true
en en el manifiesto, Microsoft Teams emite una consulta "predeterminada" cuando el usuario abre por primera vez la extensión de mensaje. El servicio puede responder a esta consulta con un conjunto de resultados rellenados previamente. Esto puede ser útil para mostrar, por ejemplo, elementos vistos recientemente, favoritos o cualquier otra información que no dependa de la entrada del usuario.
La consulta predeterminada tiene la misma estructura que cualquier consulta de usuario normal, excepto con un parámetro initialRun
cuyo valor de cadena es true
.
Ejemplo de solicitud para una consulta predeterminada
{
"type": "invoke",
"name": "composeExtension/query",
"value": {
"commandId": "searchCmd",
"parameters": [
{
"name": "initialRun",
"value": "true"
}
],
"queryOptions": {
"skip": 0,
"count": 25
}
},
⋮
}
Identificación del usuario
Cada solicitud a los servicios incluye el identificador ofuscado del usuario que realizó la solicitud y el nombre para mostrar del usuario y el identificador del objeto Microsoft Entra.
"from": {
"id": "29:1C7dbRrC_5yzN1RGtZIrcWT0xz88KPGP9sxdpVpV8sODlgPHeQE9RqQ02hnpuKzy6zZ-AaZx6swUOMj_Dsdse3TQ4sIaeebbFBF-VgjJy_nY",
"name": "Larry Jin",
"aadObjectId": "cd723fa0-0591-416a-9290-e93ecf3a9b92"
},
Se id
garantiza que los valores y aadObjectId
son los del usuario autenticado de Teams. Se pueden usar como claves para buscar credenciales o cualquier estado almacenado en caché en el servicio. Además, cada solicitud contiene el identificador de inquilino de Microsoft Entra del usuario, que se puede usar para identificar la organización del usuario. Si procede, la solicitud también contiene los identificadores de equipo y canal desde los que se originó la solicitud.
Autenticación
Si el servicio requiere autenticación de usuario, debe iniciar sesión en el usuario antes de que el usuario pueda usar la extensión de mensaje. Si ha escrito un bot o una pestaña que inicia sesión en el usuario, esta sección debería ser familiar.
La secuencia es la siguiente:
- El usuario emite una consulta o la consulta predeterminada se envía automáticamente al servicio.
- El servicio comprueba si el usuario se ha autenticado primero inspeccionando el identificador de usuario de Teams.
- Si el usuario no se ha autenticado, envíe una
auth
respuesta con unaopenUrl
acción sugerida, incluida la dirección URL de autenticación. - El cliente de Microsoft Teams inicia una ventana emergente que hospeda la página web mediante la dirección URL de autenticación especificada.
- Después de que el usuario inicie sesión, debe cerrar la ventana y enviar un "código de autenticación" al cliente de Teams.
- A continuación, el cliente de Teams vuelve a emitir la consulta al servicio, lo que incluye el código de autenticación pasado en el paso 5. El servicio debe comprobar que el código de autenticación recibido en el paso 6 coincide con el del paso 5, lo que garantiza que un usuario malintencionado no intente suplantar o poner en peligro el flujo de inicio de sesión. Así se “cierra el bucle” de forma eficaz para finalizar la secuencia de autenticación segura.
Responder con una acción de inicio de sesión
Para solicitar a un usuario no autenticado que inicie sesión, responda con una acción sugerida de tipo openUrl
que incluya la dirección URL de autenticación.
Ejemplo de respuesta para una acción de inicio de sesión
{
"composeExtension":{
"type":"auth",
"suggestedActions":{
"actions":[
{
"type": "openUrl",
"value": "https://example.com/auth",
"title": "Sign in to this app"
}
]
}
}
}
Nota:
Para que la experiencia de inicio de sesión se hospede en un elemento emergente de Teams, la parte del dominio de la dirección URL debe estar en la lista de dominios válidos de la aplicación. Para obtener más información, consulte validDomains en el esquema de manifiesto.
Inicio del flujo de inicio de sesión
El inicio de sesión debe tener capacidad de respuesta y ajustarse a una ventana emergente. Debe integrarse con el SDK de cliente de JavaScript de Microsoft Teams, que usa el paso de mensajes.
Al igual que con otras experiencias incrustadas que se ejecutan dentro de Teams, el código dentro de la ventana debe llamar microsoftTeams.initialize()
primero a . Si el código realiza un flujo de OAuth, puede pasar el identificador de usuario de Teams a la ventana, que luego puede pasarlo a la dirección URL de inicio de sesión de OAuth.
Completar el flujo de inicio de sesión
Cuando la solicitud de inicio de sesión se complete y vuelva a redirigir a la página, debe realizar los pasos siguientes:
- Generar un código de seguridad. (Puede ser un número aleatorio). Debe almacenar en caché este código en el servicio, junto con las credenciales obtenidas mediante el inicio de sesión, como los tokens de OAuth 2.0.
- Llame a
microsoftTeams.authentication.notifySuccess
y pase el código de seguridad.
En este momento, la ventana se cierra y el control se pasa al cliente de Teams. El cliente ahora puede volver a emitir la consulta de usuario original, junto con el código de seguridad de la state
propiedad . El código puede usar un código de seguridad para buscar las credenciales almacenadas anteriormente y completar la secuencia de autenticación, y así completar la solicitud del usuario.
Ejemplo de solicitud reemitido
{
"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"
}
Compatibilidad con SDK
.NET
Para recibir y controlar consultas con el SDK de Bot Builder para .NET, puede comprobar el invoke
tipo de acción en la actividad entrante y, a continuación, usar el método auxiliar en el paquete NuGet Microsoft.Bot.Connector.Teams para determinar si se trata de una actividad de extensión de mensaje.
Código de ejemplo en .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
Código de ejemplo en 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();