Pesquisar com extensões de mensagensSearch with messaging extensions

Importante

Os artigos desta seção são baseados no SDK do v3 bot Framework.The articles in this section are based on the v3 Bot Framework SDK. Se você estiver procurando a documentação atual (versão 4,6 ou posterior do SDK), confira a seção interações orientadas por tarefas com extensões de mensagens .If you're looking for current documentation (version 4.6 or later version of the SDK) see the Task-oriented interactions with Messaging Extensions section.

As extensões de mensagens baseadas em pesquisa permitem consultar seu serviço e postar essas informações na forma de um cartão, diretamente na sua mensagemSearch based messaging extensions allow you to query your service and post that information in the form of a card, right into your message

Exemplo de cartão de extensão de mensagens

As seções a seguir descrevem como fazer isso.The following sections describe how to do this.

Adicionar uma extensão de mensagem ao seu aplicativoAdd a messaging extension to your app

Uma extensão de mensagens é um serviço hospedado na nuvem que escuta solicitações de usuário e responde com dados estruturados, como um cartão.A messaging extension is a cloud-hosted service that listens to user requests and responds with structured data, such as a card. Você integra seu serviço ao Microsoft Teams via objetos Activity da estrutura de bot.You integrate your service with Microsoft Teams via Bot Framework Activity objects. As extensões .NET e node. js para o SDK do bot Builder podem ajudá-lo a adicionar a funcionalidade de extensão de mensagens ao seu aplicativo.Our .NET and Node.js extensions for the Bot Builder SDK can help you add messaging extension functionality to your app.

Diagrama do fluxo de mensagens para extensões de mensagens

Registrar-se na estrutura de botRegister in the Bot Framework

Se ainda não tiver feito isso, primeiro você deve registrar um bot com a Microsoft bot Framework.If you haven’t done so already, you must first register a bot with the Microsoft Bot Framework. A ID do aplicativo da Microsoft e os pontos de extremidade de retorno de chamada do bot, conforme definido aqui, serão usados em sua extensão de mensagens para receber e responder às solicitações do usuário.The Microsoft app ID and callback endpoints for your bot, as defined there, will be used in your messaging extension to receive and respond to user requests. Lembre-se de habilitar o canal do Microsoft Teams para o bot.Remember to enable the Microsoft Teams channel for your bot.

Registre sua ID de aplicativo do bot e a senha do aplicativo, você precisará fornecer a ID do aplicativo em seu manifesto do aplicativo.Record your bot app ID and app password, you will need to supply the app ID in your app manifest.

Atualizar o manifesto do aplicativoUpdate your app manifest

Como com bots e guias, você atualiza o manifesto do seu aplicativo para incluir as propriedades de extensão de mensagens.As with bots and tabs, you update the manifest of your app to include the messaging extension properties. Essas propriedades controlam como sua extensão de mensagens aparece e se comporta no cliente Microsoft Teams.These properties govern how your messaging extension appears and behaves in the Microsoft Teams client. As extensões de mensagens têm suporte a partir da versão v 1.0 do manifesto.Messaging extensions are supported beginning with v1.0 of the manifest.

Declarar sua extensão de mensagensDeclare your messaging extension

Para adicionar uma extensão de mensagens, inclua uma nova estrutura JSON de nível superior no manifesto com a composeExtensions propriedade.To add a messaging extension, include a new top-level JSON structure in your manifest with the composeExtensions property. Atualmente, você está limitado a criar uma única extensão de mensagens para o seu aplicativo.Currently, you are limited to creating a single messaging extension for your app.

Observação

O manifesto se refere a extensões de composeExtensionsmensagens como.The manifest refers to messaging extensions as composeExtensions. Isso é para manter a compatibilidade com versões anteriores.This is to maintain backward compatibility.

A definição de extensão é um objeto que tem a seguinte estrutura:The extension definition is an object that has the following structure:

Nome da propriedadeProperty name FinalidadePurpose Obrigatório?Required?
botId A ID exclusiva do aplicativo da Microsoft para o bot, conforme registrado na estrutura do bot.The unique Microsoft app ID for the bot as registered with the Bot Framework. Isso deve ser normalmente o mesmo que a ID do aplicativo de suas equipes gerais.This should typically be the same as the ID for your overall Teams app. SimYes
scopes Matriz que declara se essa extensão pode ser adicionada personal a team ou escopos (ou ambos).Array declaring whether this extension can be added to personal or team scopes (or both). SimYes
canUpdateConfiguration Habilita o item de menu configurações .Enables Settings menu item. NãoNo
commands Matriz de comandos que esta extensão de mensagens suporta.Array of commands that this messaging extension supports. Você está limitado a 10 comandos.You are limited to 10 commands. SimYes

Definir comandosDefine commands

Sua extensão de mensagens deve declarar um comando, que aparece quando o usuário seleciona seu aplicativo no botão mais opções () na caixa de composição.Your messaging extension should declare one command, which appears when the user selects your app from the More options () button in the compose box.

Captura de tela da lista de extensões de mensagens no Microsoft Teams

No manifesto do aplicativo, seu item de comando é um objeto com a seguinte estrutura:In the app manifest, your command item is an object with the following structure:

Nome da propriedadeProperty name FinalidadePurpose Obrigatório?Required? Versão mínima do manifestoMinimum manifest version
id ID exclusiva que você atribui a este comando.Unique ID that you assign to this command. A solicitação do usuário incluirá essa ID.The user request will include this ID. SimYes 1.01.0
title Nome do comando.Command name. Esse valor é exibido na interface do usuário.This value appears in the UI. SimYes 1.01.0
description Texto de ajuda que indica o que esse comando faz.Help text indicating what this command does. Esse valor é exibido na interface do usuário.This value appears in the UI. SimYes 1.01.0
type Defina o tipo de comando.Set the type of command. Os valores possíveis incluem query e action.Possible values include query and action. Se não estiver presente, o valor padrão será definido comoqueryIf not present the default value is set to query NãoNo 1.41.4
initialRun Parâmetro opcional, usado com query comandos.Optional parameter, used with query commands. Se definido como true, indica que este comando deve ser executado assim que o usuário escolhe este comando na interface do usuário.If set to true, indicates this command should be executed as soon as the user chooses this command in the UI. NãoNo 1.01.0
fetchTask Parâmetro opcional, usado com action comandos.Optional parameter, used with action commands. Defina como true para buscar o cartão adaptável ou a URL da Web a serem exibidos no módulo de tarefa.Set to true to fetch the adaptive card or web url to display within the task module. Isso é usado quando as entradas do action comando são dinâmicas, em vez de um conjunto estático de parâmetros.This is used when the inputs to the action command is dynamic as opposed to a static set of parameters. Observe que, se definido como true , a lista de parâmetros estáticos do comando é ignoradaNote that the if set to true the static parameter list for the command is ignored NãoNo 1.41.4
parameters Lista estática de parâmetros para o comando.Static list of parameters for the command. SimYes 1.01.0
parameter.name O nome do parâmetro.The name of the parameter. Isso é enviado para o serviço na solicitação do usuário.This is sent to your service in the user request. SimYes 1.01.0
parameter.description Descreve os fins deste parâmetro ou o exemplo do valor que deve ser fornecido.Describes this parameter’s purposes or example of the value that should be provided. Esse valor é exibido na interface do usuário.This value appears in the UI. SimYes 1.01.0
parameter.title Título ou rótulo curto de parâmetro amigável.Short user-friendly parameter title or label. SimYes 1.01.0
parameter.inputType Defina como o tipo de entrada obrigatória.Set to the type of input required. Os valores possíveis textincluem textarea, number date time,,, toggle.Possible values include text, textarea, number, date, time, toggle. O padrão é definido comotextDefault is set to text NãoNo 1.41.4
context Matriz opcional de valores que define o contexto no qual a ação de mensagem está disponível.Optional array of values that defines the context the message action is available in. Os valores possíveis messagesão compose,, commandBoxou.Possible values are message, compose, or commandBox. O padrão é ["compose", "commandBox"].Default is ["compose", "commandBox"]. NãoNo 1,51.5

Extensões de mensagens de tipo de pesquisaSearch type message extensions

Para a extensão de mensagens com base na pesquisa, defina o type parâmetro como query .For search based messaging extension set the type parameter to query. Veja a seguir um exemplo de um manifesto com um único comando de pesquisa.Below is an example of a manifest with a single search command. Uma única extensão de mensagens pode ter até 10 comandos diferentes associados a ela.A single messaging extension can have up to 10 different commands associated with it. Isso pode incluir vários comandos de pesquisa e múltiplos baseados em ação.This can include both multiple search and multiple Action-based commands.

Exemplo de manifesto de aplicativo completoComplete app manifest example

{
  "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.7/MicrosoftTeams.schema.json",
  "manifestVersion": "1.5",
  "version": "1.0",
  "id": "57a3c29f-1fc5-4d97-a142-35bb662b7b23",
  "packageName": "com.microsoft.teams.samples.bing",
  "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"
  ]
}

Testar via carregamentoTest via uploading

Você pode testar sua extensão de mensagens carregando seu aplicativo.You can test your messaging extension by uploading your app.

Para abrir sua extensão de mensagens, navegue até qualquer um dos seus chats ou canais.To open your messaging extension, navigate to any of your chats or channels. Escolha o botão mais opções () na caixa redigir e escolha sua extensão de mensagens.Choose the More options () button in the compose box, and choose your messaging extension.

Adicionar manipuladores de eventosAdd event handlers

A maior parte do seu trabalho envolve o onQuery evento, que lida com todas as interações na janela de extensão de mensagens.Most of your work involves the onQuery event, which handles all interactions in the messaging extension window.

Se você definir canUpdateConfiguration true no manifesto, habilite o item de menu configurações para sua extensão de mensagens e também deve lidar onQuerySettingsUrl e onSettingsUpdate .If you set canUpdateConfiguration to true in the manifest, you enable the Settings menu item for your messaging extension and must also handle onQuerySettingsUrl and onSettingsUpdate.

Manipular eventos onqueryHandle onQuery events

Uma extensão de mensagens recebe um onQuery evento quando algo acontece na janela de extensão de mensagens ou é enviado para a janela.A messaging extension receives an onQuery event when anything happens in the messaging extension window or is sent to the window.

Se sua extensão de mensagens usa uma página de configuração, seu manipulador para onQuery deve primeiro verificar qualquer informação de configuração armazenada; se a extensão de mensagens não estiver configurada, retorne uma config resposta com um link para sua página de configuração.If your messaging extension uses a configuration page, your handler for onQuery should first check for any stored configuration information; if the messaging extension isn't configured, return a config response with a link to your configuration page. Lembre-se de que a resposta da página de configuração também é manipulada pelo onQuery .Be aware that the response from the configuration page is also handled by onQuery. (A única exceção é quando a página de configuração é chamada pelo manipulador de onQuerySettingsUrl ; consulte a seção a seguir.(The sole exception is when the configuration page is called by the handler for onQuerySettingsUrl; see the following section.)

Se sua extensão de mensagens requer autenticação, verifique as informações de estado do usuário; Se o usuário não estiver conectado, siga as instruções na seção autenticação mais adiante neste tópico.If your messaging extension requires authentication, check the user state information; if the user isn't signed in, follow the instructions in the Authentication section later in this topic.

Em seguida, verifique se initialRun o está definido; em caso afirmativo, execute a ação apropriada, como fornecer instruções ou uma lista de respostas.Next, check whether initialRun is set; if so, take appropriate action, such as providing instructions or a list of responses.

O restante do manipulador para onQuery solicitar informações ao usuário, exibe uma lista de cartões de visualização e retorna o cartão selecionado pelo usuário.The remainder of your handler for onQuery prompts the user for information, displays a list of preview cards, and returns the card selected by the user.

Manipular eventos onQuerySettingsUrl e onSettingsUpdateHandle onQuerySettingsUrl and onSettingsUpdate events

O onQuerySettingsUrl e os onSettingsUpdate eventos trabalham em conjunto para habilitar o item de menu configurações .The onQuerySettingsUrl and onSettingsUpdate events work together to enable the Settings menu item.

Capturas de tela de locais do item de menu configurações

O manipulador de onQuerySettingsUrl retorno da URL para a página de configuração; após o fechamento da página de configuração, o manipulador para onSettingsUpdate aceitar e salvar o estado retornado.Your handler for onQuerySettingsUrl returns the URL for the configuration page; after the configuration page closes, your handler for onSettingsUpdate accepts and saves the returned state. (Este é o único caso no qual onQuery não recebe a resposta da página de configuração.)(This is the one case in which onQuery doesn't receive the response from the configuration page.)

Receber e responder a consultasReceive and respond to queries

Cada solicitação para sua extensão de mensagens é feita por meio de um Activity objeto que é publicado na sua URL de retorno de chamada.Every request to your messaging extension is done via an Activity object that is posted to your callback URL. A solicitação contém informações sobre o comando de usuário, como valores de ID e de parâmetro.The request contains information about the user command, such as ID and parameter values. A solicitação também fornece metadados sobre o contexto no qual sua extensão foi invocada, incluindo o ID de usuário e de locatário, junto com a ID de chat ou as identificações de canal e equipe.The request also supplies metadata about the context in which your extension was invoked, including user and tenant ID, along with chat ID or channel and team IDs.

Receber solicitações de usuárioReceive user requests

Quando um usuário realiza uma consulta, o Microsoft Teams envia o serviço de um objeto da estrutura de bot padrão Activity .When a user performs a query, Microsoft Teams sends your service a standard Bot Framework Activity object. Seu serviço deve executar sua lógica para um Activity que tenha type definido como invoke e name definido como um tipo com suporte composeExtension , conforme mostrado na tabela a seguir.Your service should perform its logic for an Activity that has type set to invoke and name set to a supported composeExtension type, as shown in the following table.

Além das propriedades de atividade de bot padrão, a carga contém os seguintes metadados de solicitação:In addition to the standard bot activity properties, the payload contains the following request metadata:

Nome da propriedadeProperty name FinalidadePurpose
type Tipo de solicitação; deve ser invoke .Type of request; must be invoke.
name Tipo de comando que é emitido para o serviço.Type of command that is issued to your service. Atualmente, há suporte para os seguintes tipos:Currently the following types are supported:
composeExtension/query
composeExtension/querySettingUrl
composeExtension/setting
composeExtension/selectItem
composeExtension/queryLink
from.id ID do usuário que enviou a solicitação.ID of the user that sent the request.
from.name Nome do usuário que enviou a solicitação.Name of the user that sent the request.
from.aadObjectId ID de objeto do Azure Active Directory do usuário que enviou a solicitação.Azure Active Directory object id of the user that sent the request.
channelData.tenant.id Locatário do Azure Active Directory.Azure Active Directory tenant ID.
channelData.channel.id ID do canal (se a solicitação tiver sido feita em um canal).Channel ID (if the request was made in a channel).
channelData.team.id ID da equipe (se a solicitação tiver sido feita em um canal).Team ID (if the request was made in a channel).
clientInfo Metadados opcionais sobre o software cliente usado para enviar a mensagem de um usuário.Optional metadata about the client software used to send a user's message. A entidade pode conter duas propriedades:The entity can contain two properties:
O country campo contém o local detectado do usuário.The country field contains the user's detected location.
O platform campo descreve a plataforma do cliente de mensagens.The platform field describes the messaging client platform.
Para obter informações adicionais, Confira tipos de entidade não IRI — clientInfo.For additional information, please see Non-IRI entity types — clientInfo.

Os próprios parâmetros de solicitação são encontrados no objeto value, que inclui as seguintes propriedades:The request parameters itself are found in the value object, which includes the following properties:

Nome da propriedadeProperty name FinalidadePurpose
commandId O nome do comando invocado pelo usuário, correspondendo a um dos comandos declarados no manifesto do aplicativo.The name of the command invoked by the user, matching one of the commands declared in the app manifest.
parameters Matriz de parâmetros.Array of parameters. Cada objeto Parameter contém o nome do parâmetro, juntamente com o valor do parâmetro fornecido pelo usuário.Each parameter object contains the parameter name, along with the parameter value provided by the user.
queryOptions Parâmetros de paginação:Pagination parameters:
skip: ignorar contagem para esta consultaskip: skip count for this query
count: número de elementos a serem retornadoscount: number of elements to return

Exemplo de solicitaçãoRequest example

{
  "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"
    }
  ]
}

Como alternativa (ou adicional) para pesquisar seu serviço externo, você pode usar uma URL inserida na caixa de mensagem de composição para consultar seu serviço e retornar um cartão.As an alternative (or in addition) to searching your external service, you can use a URL inserted into the compose message box to query your service and return a card. Na captura de tela abaixo de um usuário colou em uma URL para um item de trabalho no Azure DevOps que a extensão de mensagens foi resolvida em um cartão.In the screenshot below a user has pasted in a URL for a work item in Azure DevOps which the messaging extension has resolved into a card.

Exemplo de link Unfurling

Para habilitar sua extensão de mensagens para interagir com os links dessa forma, primeiro você precisará adicionar a messageHandlers matriz ao manifesto do aplicativo, como no exemplo abaixo:To enable your messaging extension to interact with links this way you'll first need to add the messageHandlers array to your app manifest as in the example below:

"composeExtensions": [
  {
    "botId": "abc123456-ab12-ab12-ab12-abcdef123456",
    "messageHandlers": [
      {
        "type": "link",
        "value": {
          "domains": [
            "*.trackeddomain.com"
          ]
        }
      }
    ]
  }
]

Após adicionar o domínio para ouvir o manifesto do aplicativo, você precisará alterar o código do bot para responder à solicitação de invocação abaixo.Once you've added the domain to listen on to the app manifest, you'll need to change your bot code to respond to the below invoke request.

{
  "type": "invoke",
  "name": "composeExtension/queryLink",
  "value": {
    "url": "https://theurlsubmittedbyyouruser.trackeddomain.com/id/1234"
  }
}

Se seu aplicativo retornar vários itens, apenas o primeiro será usado.If your app returns multiple items only the first will be used.

Responder às solicitações do usuárioRespond to user requests

Quando o usuário executa uma consulta, o Microsoft Teams emite uma solicitação HTTP síncrona para o serviço.When the user performs a query, Microsoft Teams issues a synchronous HTTP request to your service. Nesse ponto, o código tem cinco segundos para fornecer uma resposta HTTP para a solicitação.At that point, your code has 5 seconds to provide an HTTP response to the request. Durante esse tempo, o serviço pode executar pesquisa adicional ou qualquer outra lógica de negócios necessária para atender à solicitação.During this time, your service can perform additional lookup, or any other business logic needed to serve the request.

Seu serviço deve responder com os resultados que correspondem à consulta do usuário.Your service should respond with the results matching the user query. A resposta deve indicar um código de status HTTP 200 OK e um objeto Application/JSON válido com o seguinte corpo:The response must indicate an HTTP status code of 200 OK and a valid application/json object with the following body:

Nome da propriedadeProperty name FinalidadePurpose
composeExtension Envelope de resposta de nível superior.Top-level response envelope.
composeExtension.type Tipo de resposta.Type of response. Há suporte para os seguintes tipos:The following types are supported:
result: exibe uma lista de resultados de pesquisaresult: displays a list of search results
auth: solicita que o usuário autentiqueauth: asks the user to authenticate
config: solicita que o usuário configure a extensão de mensagensconfig: asks the user to set up the messaging extension
message: exibe uma mensagem de texto sem formataçãomessage: displays a plain text message
composeExtension.attachmentLayout Especifica o layout dos anexos.Specifies the layout of the attachments. Usado para respostas do tipo result .Used for responses of type result.
Atualmente, há suporte para os seguintes tipos:Currently the following types are supported:
list: uma lista de objetos Card contendo campos de miniatura, título e textolist: a list of card objects containing thumbnail, title, and text fields
grid: uma grade de imagens em miniaturagrid: a grid of thumbnail images
composeExtension.attachments Matriz de objetos Attachment válidos.Array of valid attachment objects. Usado para respostas do tipo result .Used for responses of type result.
Atualmente, há suporte para os seguintes tipos:Currently the following types are supported:
application/vnd.microsoft.card.thumbnail
application/vnd.microsoft.card.hero
application/vnd.microsoft.teams.card.o365connector
application/vnd.microsoft.card.adaptive
composeExtension.suggestedActions Ações sugeridas.Suggested actions. Usado para respostas do tipo auth ou config .Used for responses of type auth or config.
composeExtension.text Mensagem a ser exibida.Message to display. Usado para respostas do tipo message .Used for responses of type message.

Tipos e visualizações de cartões de respostaResponse card types and previews

Oferecemos suporte para os seguintes tipos de anexo:We support the following attachment types:

Consulte cartões para obter uma visão geral.See Cards for an overview.

Para saber como usar os tipos de cartão de miniatura e herói, confira Adicionar cartões e ações de cartão.To learn how to use the thumbnail and hero card types, see Add cards and card actions.

Para obter documentação adicional sobre a placa de conector do Office 365, consulte usando cartões de conector do office 365.For additional documentation regarding the Office 365 Connector card, see Using Office 365 Connector cards.

A lista de resultados é exibida na interface do usuário do Microsoft Teams com uma visualização de cada item.The result list is displayed in the Microsoft Teams UI with a preview of each item. A visualização é gerada de duas maneiras:The preview is generated in one of two ways:

  • Usando a preview propriedade dentro do attachment objeto.Using the preview property within the attachment object. O preview anexo só pode ser um herói ou cartão de miniatura.The preview attachment can only be a Hero or Thumbnail card.
  • Extraído do básico title , text e das image Propriedades do anexo.Extracted from the basic title, text, and image properties of the attachment. Eles são usados apenas se a preview propriedade não estiver definida e essas propriedades estiverem disponíveis.These are used only if the preview property is not set and these properties are available.

Você pode exibir uma visualização de um cartão de conexão adaptável ou do Office 365 na lista de resultados, simplesmente definindo sua propriedade Preview; Isso não é necessário se os resultados já são herói ou cartões em miniatura.You can display a preview of an Adaptive or Office 365 Connector card in the result list simply by setting its preview property; this is not necessary if the results are already hero or thumbnail cards. Se você usar o anexo de visualização, ele deve ser um herói ou cartão de miniatura.If you use the preview attachment, it must be either a Hero or Thumbnail card. Se nenhuma propriedade Preview for especificada, a visualização do cartão falhará e nada será exibido.If no preview property is specified, the preview of the card will fail and nothing will be displayed.

Exemplo de respostaResponse example

Este exemplo mostra uma resposta com dois resultados, combinando formatos de cartão diferentes: conector e adaptável do Office 365.This example shows a response with two results, mixing different card formats: Office 365 Connector and Adaptive. Embora você provavelmente queira usar um formato de cartão em sua resposta, ele mostra como a preview propriedade de cada elemento da attachments coleção deve definir explicitamente uma visualização no formato herói ou miniatura, conforme descrito acima.While you'll likely want to stick with one card format in your response, it shows how the preview property of each element in the attachments collection must explicitly define a preview in hero or thumbnail format as described above.

{
  "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 padrãoDefault query

Se você definir initialRun para true no manifesto, o Microsoft Teams emitirá uma consulta "padrão" quando o usuário abrir pela primeira vez a extensão de mensagens.If you set initialRun to true in the manifest, Microsoft Teams issues a "default" query when the user first opens the messaging extension. O serviço pode responder a essa consulta com um conjunto de resultados previamente preenchidos.Your service can respond to this query with a set of prepopulated results. Isso pode ser útil para exibir, por exemplo, itens exibidos recentemente, favoritos ou qualquer outra informação que não seja dependente da entrada do usuário.This can be useful for displaying, for instance, recently viewed items, favorites, or any other information that is not dependent on user input.

A consulta padrão tem a mesma estrutura que qualquer consulta de usuário regular, exceto com um parâmetro initialRun cujo valor de cadeia de caracteres é true .The default query has the same structure as any regular user query, except with a parameter initialRun whose string value is true.

Exemplo de solicitação para uma consulta padrãoRequest example for a default query

{
  "type": "invoke",
  "name": "composeExtension/query",
  "value": {
    "commandId": "searchCmd",
    "parameters": [
      {
        "name": "initialRun",
        "value": "true"
      }
    ],
    "queryOptions": {
      "skip": 0,
      "count": 25
    }
  },
  ⋮
}

Identificar o usuárioIdentify the user

Todas as solicitações para seus serviços incluem a ID ofuscada do usuário que realizou a solicitação, bem como o nome de exibição do usuário e a ID de objeto do Azure Active Directory.Every request to your services includes the obfuscated ID of the user that performed the request, as well as the user's display name and Azure Active Directory object ID.

"from": {
  "id": "29:1C7dbRrC_5yzN1RGtZIrcWT0xz88KPGP9sxdpVpV8sODlgPHeQE9RqQ02hnpuKzy6zZ-AaZx6swUOMj_Dsdse3TQ4sIaeebbFBF-VgjJy_nY",
  "name": "Larry Jin",
  "aadObjectId": "cd723fa0-0591-416a-9290-e93ecf3a9b92"
},

Os id aadObjectId valores e são garantidos do usuário do Microsoft Teams.The id and aadObjectId values are guaranteed to be that of the authenticated Teams user. Eles podem ser usados como chaves para procurar credenciais ou qualquer estado em cache em seu serviço.They can be used as keys to look up credentials or any cached state in your service. Além disso, cada solicitação contém a ID de locatário do Azure Active Directory do usuário, que pode ser usada para identificar a organização do usuário.In addition, each request contains the Azure Active Directory tenant ID of the user, which can be used to identify the user’s organization. Se aplicável, a solicitação também contém as IDs de canal e equipe das quais a solicitação foi originada.If applicable, the request also contains the team and channel IDs from which the request originated.

AutenticaçãoAuthentication

Se o serviço exigir autenticação do usuário, você precisará entrar no usuário antes de poder usar a extensão de mensagens.If your service requires user authentication, you need to sign in the user before he or she can use the messaging extension. Se você escreveu um bot ou uma guia que entra no usuário, esta seção deve ser familiar.If you have written a bot or a tab that signs in the user, this section should be familiar.

A sequência é a seguinte:The sequence is as follows:

  1. O usuário emite uma consulta ou a consulta padrão é enviada automaticamente ao seu serviço.User issues a query, or the default query is automatically sent to your service.
  2. Seu serviço verifica se o usuário foi autenticado pela primeira vez inspecionando a ID de usuário do teams.Your service checks whether the user has first authenticated by inspecting the Teams user ID.
  3. Se o usuário não tiver sido autenticado, envie uma auth resposta com uma openUrl ação sugerida, incluindo a URL de autenticação.If the user has not authenticated, send back an auth response with an openUrl suggested action including the authentication URL.
  4. O cliente do Microsoft Teams inicia uma janela pop-up hospedando sua página da Web usando a URL de autenticação determinada.The Microsoft Teams client launches a pop-up window hosting your webpage using the given authentication URL.
  5. Após o usuário entrar, você deve fechar sua janela e enviar um "código de autenticação" para o cliente do teams.After the user signs in, you should close your window and send an "authentication code" to the Teams client.
  6. Em seguida, o cliente do teams emite novamente a consulta para o serviço, o que inclui o código de autenticação passado na etapa 5.The Teams client then reissues the query to your service, which includes the authentication code passed in step 5.

Seu serviço deve verificar se o código de autenticação recebido na etapa 6 corresponde ao da etapa 5.Your service should verify that the authentication code received in step 6 matches the one from step 5. Isso garante que um usuário mal-intencionado não tente falsificar ou comprometer o fluxo de entrada.This ensures that a malicious user does not try to spoof or compromise the sign-in flow. Isso efetivamente "fecha o loop" para concluir a sequência de autenticação segura.This effectively "closes the loop" to finish the secure authentication sequence.

Responder com uma ação de entradaRespond with a sign-in action

Para solicitar que um usuário não autenticado entre, responda com uma ação sugerida do tipo openUrl que inclui a URL de autenticação.To prompt an unauthenticated user to sign in, respond with a suggested action of type openUrl that includes the authentication URL.

Exemplo de resposta para uma ação de logonResponse example for a sign-in action

{
  "composeExtension":{
    "type":"auth",
    "suggestedActions":{
      "actions":[
        {
          "type": "openUrl",
          "value": "https://example.com/auth",
          "title": "Sign in to this app"
        }
      ]
    }
  }
}

Observação

Para que a experiência de entrada seja hospedada em um pop-up de equipes, a parte de domínio da URL deve estar na lista de domínios válidos de seu aplicativo.For the sign-in experience to be hosted in a Teams pop-up, the domain portion of the URL must be in your app’s list of valid domains. (Consulte validDomains no esquema de manifesto.)(See validDomains in the manifest schema.)

Iniciar o fluxo de entradaStart the sign-in flow

Sua experiência de entrada deve ser responsiva e ajustada em uma janela pop-up.Your sign-in experience should be responsive and fit within a popup window. Ele deve se integrar ao SDK do cliente JavaScript do Microsoft Teams, que usa a transmissão de mensagens.It should integrate with the Microsoft Teams JavaScript client SDK, which uses message passing.

Assim como ocorre com outras experiências incorporadas no Microsoft Teams, seu código dentro da janela precisa primeiro chamar microsoftTeams.initialize() .As with other embedded experiences running inside Microsoft Teams, your code inside the window needs to first call microsoftTeams.initialize(). Se o código executar um fluxo OAuth, você poderá passar a ID de usuário do teams para sua janela, o que pode passá-la para a URL de entrada OAuth.If your code performs an OAuth flow, you can pass the Teams user ID into your window, which then can pass it to the OAuth sign-in URL.

Concluir o fluxo de entradaComplete the sign-in flow

Quando a solicitação de entrada é concluída e redireciona de volta para sua página, ela deve executar as seguintes etapas:When the sign-in request completes and redirects back to your page, it should perform the following steps:

  1. Gere um código de segurança.Generate a security code. (Pode ser um número aleatório.) Você precisa armazenar em cache esse código em seu serviço, junto com as credenciais obtidas por meio do fluxo de entrada (como tokens OAuth 2,0).(This can be a random number.) You need to cache this code on your service, along with the credentials obtained through the sign-in flow (such as OAuth 2.0 tokens).
  2. Chame microsoftTeams.authentication.notifySuccess e passe o código de segurança.Call microsoftTeams.authentication.notifySuccess and pass the security code.

Neste ponto, a janela é fechada e o controle é passado para o cliente Teams.At this point, the window closes and control is passed to the Teams client. Agora, o cliente pode reemitir a consulta de usuário original, juntamente com o código de segurança na state propriedade.The client now can reissue the original user query, along with the security code in the state property. Seu código pode usar o código de segurança para pesquisar as credenciais armazenadas anteriormente para concluir a sequência de autenticação e concluir a solicitação do usuário.Your code can use the security code to look up the credentials stored earlier to complete the authentication sequence and then complete the user request.

Exemplo de solicitação reemitidaReissued request example

{
    "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"
}

Suporte a SDKSDK support

.NET.NET

Para receber e lidar com consultas com o SDK do bot Builder para .NET, você pode verificar o invoke tipo de ação na atividade de entrada e, em seguida, usar o método auxiliar no pacote NuGet Microsoft. bot. Connector. Teams para determinar se é uma atividade de extensão de mensagens.To receive and handle queries with the Bot Builder SDK for .NET, you can check for the invoke action type on the incoming activity and then use the helper method in the NuGet package Microsoft.Bot.Connector.Teams to determine whether it’s a messaging extension activity.

Código de exemplo no .NETExample code 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.jsNode.js

Código de exemplo no Node.jsExample code 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();

Confira também exemplos da estrutura de bot.See also Bot Framework samples.