Partilhar via


Procurar com extensões de mensagens

Importante

Os artigos nesta secção baseiam-se no SDK v3 do Bot Framework. Se estiver à procura da documentação atual (versão 4.6 ou versão posterior do SDK), veja a secção Interações orientadas para tarefas com Extensões de Mensagens .

As extensões de mensagens baseadas em pesquisa permitem-lhe consultar o seu serviço e publicar essas informações sob a forma de um cartão, diretamente na sua mensagem.

Captura de ecrã a mostrar o exemplo do cartão de extensão de mensagem.

As secções seguintes descrevem como fazê-lo:

Adicionar uma extensão de mensagem à sua aplicação

Uma extensão de mensagem é um serviço alojado na cloud que escuta os pedidos dos utilizadores e responde com dados estruturados, como um cartão. Integra o seu serviço no Microsoft Teams através de objetos do Bot Framework Activity . As nossas extensões .NET e Node.js para o SDK do Bot Builder podem ajudá-lo a adicionar a funcionalidade de extensão de mensagens à sua aplicação.

Captura de ecrã que mostra a extensão de mensagem baseada em ação no Teams.

Registar no Bot Framework

Primeiro, tem de registar um bot no Microsoft Bot Framework. O ID da aplicação Microsoft e os pontos finais de chamada de retorno para o bot, conforme definido aqui, são utilizados na extensão da sua mensagem para receber e responder a pedidos de utilizador. Lembre-se de ativar o canal do Microsoft Teams para o seu bot.

Tome nota do ID da aplicação do bot e da palavra-passe da aplicação. Tem de fornecer o ID da aplicação no manifesto da aplicação.

Atualizar seu manifesto do aplicativo

Tal como acontece com bots e separadores, atualiza o manifesto da sua aplicação para incluir as propriedades da extensão da mensagem. Estas propriedades regem a forma como a extensão de mensagem é apresentada e comporta-se no cliente do Microsoft Teams. As extensões de mensagens são suportadas a partir do manifesto v1.0.

Declarar a extensão da mensagem

Para adicionar uma extensão de mensagem, inclua uma nova estrutura JSON de nível superior no seu manifesto com a composeExtensions propriedade . Está limitado à criação de uma extensão de mensagem única para a sua aplicação.

Observação

O manifesto refere-se às extensões de mensagens como composeExtensions. Isto é para manter a retrocompatibilidade.

A definição da extensão é um objeto que tem a seguinte estrutura:

Nome da propriedade Objetivo Obrigatório?
botId O ID exclusivo do aplicativo Microsoft para o bot conforme registrado na estrutura do bot. Normalmente, deve ser igual ao ID da sua aplicação geral do Teams. Sim
scopes Matriz a declarar se esta extensão pode ser adicionada a personal ou team âmbitos (ou ambos). Sim
canUpdateConfiguration Ativa o item de menu Definições . Não
commands Matriz de comandos suportados por esta extensão de mensagem. Está limitado a 10 comandos. Sim

Observação

Se definir a canUpdateConfiguration propriedade como true no manifesto da aplicação, pode apresentar o item de menu Definições da sua extensão de mensagem. Para ativar as Definições, também tem de processar onQuerySettingsUrl e onSettingsUpdate.

Definir comandos

A extensão da sua mensagem deve declarar um comando, que é apresentado quando o utilizador seleciona a sua aplicação a partir do botão Mais opções () na caixa de composição.

Captura de ecrã a mostrar um exemplo que mostra uma lista de extensões de mensagens no Teams.

No manifesto da aplicação, o item de comando é um objeto com a seguinte estrutura:

Nome da propriedade Objetivo Obrigatório? Versão mínima do manifesto
id ID exclusivo que atribui a este comando. A solicitação do usuário inclui essa ID. Sim 1.0
title Nome do comando. Esse valor aparece na interface do usuário. Sim 1.0
description Texto de ajuda que indica o que este comando faz. Esse valor aparece na interface do usuário. Sim 1.0
type Defina o tipo de comando. Os valores possíveis incluem query e action. Se não estiver presente, o valor predefinido está definido como query. Não 1.4
initialRun Parâmetro opcional, utilizado com query comandos. Se definido como verdadeiro, indica que este comando deve ser executado assim que o utilizador escolher este comando na IU. Não 1.0
fetchTask Parâmetro opcional, utilizado com action comandos. Defina como verdadeiro para obter o cartão ajustável ou o URL da Web a apresentar no módulo de tarefa. Isto é utilizado quando a entrada para o action comando é dinâmica em oposição a um conjunto estático de parâmetros. Tenha em atenção que, se definido como verdadeiro, a lista de parâmetros estáticos do comando é ignorada. Não 1.4
parameters Lista estática de parâmetros para o comando . Sim 1.0
parameter.name O nome do parâmetro. Isso é enviado ao seu serviço na solicitação do usuário. Sim 1.0
parameter.description Descreve os objetivos deste parâmetro e o exemplo do valor que deve ser fornecido. Esse valor aparece na interface do usuário. Sim 1.0
parameter.title Título ou etiqueta abreviado do parâmetro amigável do utilizador. Sim 1.0
parameter.inputType Defina para o tipo de entrada necessário. Os valores possíveis incluem text, textarea, number, date, time, . toggle A predefinição está definida como text. Não 1.4
context Matriz opcional de valores que define o contexto em que a ação de mensagem está disponível. Os valores possíveis são message, composeou commandBox. O padrão é ["compose", "commandBox"]. Não 1,5

Extensões de mensagens de tipo de pesquisa

Para a extensão de mensagem baseada em pesquisa, defina o type parâmetro como query. Segue-se um exemplo de um manifesto com um único comando de pesquisa. Uma extensão de mensagem única pode ter até 10 comandos diferentes associados à mesma. Isto pode incluir múltiplas pesquisas e vários comandos baseados em ações.

Exemplo de manifesto de aplicação 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"
  ]
}

Testar através do carregamento

Pode testar a extensão da mensagem ao carregar a sua aplicação.

Para abrir a extensão da sua mensagem, aceda a qualquer uma das suas conversas ou canais. Selecione o botão Mais opções () na caixa de composição e selecione a extensão da sua mensagem.

Adicionar processadores de eventos

A maior parte do seu trabalho envolve o onQuery evento, que processa todas as interações na janela da extensão da mensagem.

Se definir canUpdateConfiguration como true no manifesto, ative o item de menu Definições para a extensão da sua mensagem e também tem de processar onQuerySettingsUrl e onSettingsUpdate.

Processar eventos onQuery

Uma extensão de mensagem recebe um onQuery evento quando algo acontece na janela da extensão da mensagem ou é enviada para a janela.

Se a extensão da sua mensagem utilizar uma página de configuração, o processador de onQuery deve verificar primeiro se existem informações de configuração armazenadas; se a extensão da mensagem não estiver configurada, devolva uma config resposta com uma ligação para a sua página de configuração. A resposta da página de configuração também é processada pelo onQuery. A única exceção é quando a página de configuração é chamada pelo processador para onQuerySettingsUrl; consulte a secção seguinte:

Se a extensão da mensagem exigir autenticação, verifique as informações de estado do utilizador. Se o utilizador não tiver sessão iniciada, siga as instruções na secção Autenticação mais à frente neste artigo.

Em seguida, verifique se initialRun está definido; se for o caso, tome as medidas adequadas, como fornecer instruções ou uma lista de respostas.

O resto do processador pede onQuery informações ao utilizador, apresenta uma lista de cartões de pré-visualização e devolve o cartão selecionado pelo utilizador.

Processar eventos onQuerySettingsUrl e onSettingsUpdate

Os onQuerySettingsUrl eventos e onSettingsUpdate funcionam em conjunto para ativar o item de menu Definições .

Captura de ecrã a mostrar as localizações do item de menu Definições.

O processador de onQuerySettingsUrl devolve o URL da página de configuração; depois de a página de configuração fechar, o processador de onSettingsUpdate aceita e guarda o estado devolvido. Este é o único caso em que onQuerynão recebe a resposta da página de configuração.

Receber e responder a consultas

Cada pedido à extensão da mensagem é feito através de um Activity objeto que é publicado no URL de chamada de retorno. O pedido contém informações sobre o comando do utilizador, como o ID e os valores dos parâmetros. O pedido também fornece metadados sobre o contexto em que a extensão foi invocada, incluindo o ID de utilizador e inquilino, juntamente com o ID do chat ou o canal e os IDs de equipa.

Receber pedidos de utilizador

Quando um utilizador efetua uma consulta, o Microsoft Teams envia ao seu serviço um objeto padrão do Bot Framework Activity . O serviço deve efetuar a respetiva lógica para um Activity que tenha type definido invoke como e name definido como um tipo suportado composeExtensions , conforme mostrado na tabela seguinte.

Além das propriedades de atividade do bot padrão, o payload contém os seguintes metadados de pedido:

Nome da propriedade Objetivo
type Tipo de pedido; tem de ser invoke.
name Tipo de comando que é emitido para o serviço. São suportados os seguintes tipos:
composeExtension/query
composeExtension/querySettingUrl
composeExtension/setting
composeExtension/selectItem
composeExtension/queryLink
from.id ID do usuário que enviou a solicitação.
from.name Nome do usuário que enviou a solicitação.
from.aadObjectId ID de objeto do Microsoft Entra do utilizador que enviou o pedido.
channelData.tenant.id ID do inquilino do Microsoft Entra.
channelData.channel.id ID do canal (se a solicitação foi feita em um canal).
channelData.team.id ID da equipe (se a solicitação foi feita em um canal).
clientInfo Metadados opcionais sobre o software de cliente utilizado para enviar a mensagem de um utilizador. A entidade pode conter duas propriedades:
O country campo contém a localização detetada pelo utilizador.
O platform campo descreve a plataforma de cliente de mensagens.
Para obter mais informações, vejaTipos de entidade não IRI — clientInfo.

Os parâmetros do pedido encontram-se no objeto de valor, que inclui as seguintes propriedades:

Nome da propriedade Objetivo
commandId O nome do comando invocado pelo utilizador, que corresponde a um dos comandos declarados no manifesto da aplicação.
parameters Matriz de parâmetros: cada objeto de parâmetro contém o nome do parâmetro, juntamente com o valor do parâmetro fornecido pelo utilizador.
queryOptions Parâmetros de paginação:
skip: ignorar contagem para esta consulta
count: número de elementos a devolver

Exemplo de solicitação

{
  "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 além disso) à pesquisa no seu serviço externo, pode utilizar um URL inserido na caixa de mensagem de composição para consultar o seu serviço e devolver um cartão. Na captura de ecrã abaixo, um utilizador colou um URL para um item de trabalho no Azure DevOps, que a extensão da mensagem resolveu num cartão.

Captura de ecrã a mostrar o exemplo de desfraldamento da ligação.

Para permitir que a extensão de mensagem interaja com ligações desta forma, primeiro tem de adicionar a messageHandlers matriz ao manifesto da aplicação, tal como no exemplo:

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

Depois de adicionar o domínio para escutar o manifesto da aplicação, tem de alterar o código do bot para responder ao pedido de invocação abaixo.

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

Se a sua aplicação devolver vários itens, apenas o primeiro é utilizado.

Responder a pedidos de utilizador

Quando o utilizador efetua uma consulta, o Teams emite um pedido HTTP síncrono ao seu serviço. Durante este período, o código tem 5 segundos para fornecer uma resposta HTTP ao pedido. Durante este período, o serviço pode efetuar outra pesquisa ou qualquer outra lógica de negócio necessária para servir o pedido.

O seu serviço deve responder com os resultados correspondentes à consulta do utilizador. A resposta tem de indicar um código de estado HTTP de 200 OK e um objeto application/json válido com o seguinte corpo:

Nome da propriedade Objetivo
composeExtension Envelope de resposta de nível superior.
composeExtension.type Tipo de resposta. São suportados os seguintes tipos:
result: apresenta uma lista de resultados da pesquisa
auth: pede ao utilizador para se autenticar
config: pede ao utilizador para configurar a extensão da mensagem
message: exibe uma mensagem de texto simples
composeExtension.attachmentLayout Especifica o esquema dos anexos. Utilizado para respostas do tipo result.
São suportados os seguintes tipos:
list: uma lista de objetos de cartão que contêm campos de miniatura, título e texto
grid: uma grelha de imagens em miniatura
composeExtension.attachments Matriz de objetos de anexo válidos. Utilizado para respostas do tipo result.
São suportados os seguintes tipos:
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. Utilizado para respostas do tipo auth ou config.
composeExtension.text Mensagem a apresentar. Utilizado para respostas do tipo message.

Tipos e pré-visualizações de cartões de resposta

Suportamos os seguintes tipos de anexo:

Para obter mais informações, consulte Cartões para obter uma descrição geral.

Para saber como utilizar os tipos de cartões de miniatura e de destaque, consulte Adicionar cartões e ações de cartão.

Para obter mais informações sobre o cartão de conector dos Grupos do Microsoft 365, consulte Utilizar o cartão de conector para Grupos do Microsoft 365.

A lista de resultados é apresentada na IU do Microsoft Teams com uma pré-visualização de cada item. A pré-visualização é gerada de uma de duas formas:

  • Utilizar a preview propriedade dentro do attachment objeto. O preview anexo só pode ser um cartão Hero ou Thumbnail.
  • Extraído das propriedades básicas title, texte image do anexo. Estes são utilizados apenas se a preview propriedade não estiver definida e estas propriedades estiverem disponíveis.

Pode apresentar uma pré-visualização de um cartão Adaptável ou de conector para Grupos do Microsoft 365 na lista de resultados, bastando definir a respetiva propriedade de pré-visualização. Isto não é necessário se os resultados já forem cartões de destaque ou miniaturas. Se utilizar o anexo de pré-visualização, este tem de ser um cartão Hero ou Miniatura. Se não for especificada nenhuma propriedade de pré-visualização, a pré-visualização do cartão falha e nada é apresentado.

Exemplo de resposta

Este exemplo mostra uma resposta com dois resultados, combinando diferentes formatos de cartão: Conector para Grupos do Microsoft 365 e Adaptável. Embora provavelmente queira manter um formato de cartão na sua resposta, mostra como a preview propriedade de cada elemento na attachments coleção tem de definir explicitamente uma pré-visualização no formato de destaque ou miniatura, conforme descrito acima.

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

Se definir initialRun como true no manifesto, o Microsoft Teams emite uma consulta "predefinida" quando o utilizador abre pela primeira vez a extensão da mensagem. O seu serviço pode responder a esta consulta com um conjunto de resultados pré-preenchidos. Isto pode ser útil para apresentar, por exemplo, itens visualizados recentemente, favoritos ou qualquer outra informação que não dependa da entrada do utilizador.

A consulta predefinida tem a mesma estrutura que qualquer consulta de utilizador normal, exceto com um parâmetro initialRun cujo valor de cadeia é true.

Exemplo de pedido para uma consulta predefinida

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

Identifique o usuário

Todos os pedidos aos seus serviços incluem o ID oculto do utilizador que efetuou o pedido e o nome a apresentar do utilizador e o ID de objeto do Microsoft Entra.

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

Os id valores e aadObjectId são garantidos como o do utilizador autenticado do Teams. Podem ser utilizadas como chaves para procurar credenciais ou qualquer estado em cache no seu serviço. Além disso, cada pedido contém o ID de inquilino do Microsoft Entra do utilizador, que pode ser utilizado para identificar a organização do utilizador. Se aplicável, o pedido também contém os IDs da equipa e do canal a partir dos quais o pedido teve origem.

Autenticação

Se o seu serviço necessitar de autenticação de utilizador, tem de iniciar sessão no utilizador antes de o utilizador poder utilizar a extensão de mensagem. Se escreveu um bot ou um separador que inicia sessão no utilizador, esta secção deverá ser familiar.

A sequência é a seguinte:

  1. O utilizador emite uma consulta ou a consulta predefinida é enviada automaticamente para o seu serviço.
  2. O seu serviço verifica se o utilizador se autenticou primeiro ao inspecionar o ID de utilizador do Teams.
  3. Se o utilizador não se tiver autenticado, envie uma auth resposta com uma openUrl ação sugerida, incluindo o URL de autenticação.
  4. O cliente do Microsoft Teams inicia uma janela de pop-up que aloja a sua página Web com o URL de autenticação especificado.
  5. Depois de o utilizador iniciar sessão, deve fechar a janela e enviar um "código de autenticação" para o cliente do Teams.
  6. Em seguida, o cliente do Teams reedita a consulta para o seu serviço, que inclui o código de autenticação transmitido no passo 5. O seu serviço tem de verificar se o código de autenticação recebido no passo 6 corresponde ao do passo 5, o que garante que um utilizador malicioso não tenta falsificar ou comprometer o fluxo de início de sessão. Isso efetivamente "fecha o loop" para concluir a sequência de autenticação segura.

Responder com uma ação de início de sessão

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.

Exemplo de resposta para uma ação de início de sessão

{
  "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 início de sessão seja alojada num pop-up do Teams, a parte do domínio do URL tem de estar na lista de domínios válidos da sua aplicação. Para obter mais informações, confira validDomains no esquema de manifesto.

Iniciar o fluxo de início de sessão

O seu início de sessão tem de ser reativo e estar dentro de uma janela de pop-up. Ela deve se integrar ao SDK do cliente JavaScript do Microsoft Teams, que usa a passagem de mensagens.

Tal como acontece com outras experiências incorporadas em execução no Teams, o seu código dentro da janela tem de chamar microsoftTeams.initialize()primeiro . Se o seu código executar um fluxo OAuth, pode transmitir o ID de utilizador do Teams para a janela, que, em seguida, pode passá-lo para o URL do URL de início de sessão do OAuth.

Concluir o fluxo de início de sessão

Quando o pedido de início de sessão for concluído e redirecionar novamente para a sua página, deverá executar os seguintes passos:

  1. Gerar um código de segurança. (Pode ser um número aleatório.) Tem de colocar este código em cache no seu serviço, juntamente com as credenciais obtidas através do início de sessão, como tokens OAuth 2.0.
  2. Chamar microsoftTeams.authentication.notifySuccess e passar o código de segurança.

Neste momento, a janela é fechada e o controlo é passado para o cliente do Teams. O cliente pode agora reeditar a consulta original do utilizador, juntamente com o código de segurança na state propriedade . 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, em seguida, concluir a solicitação do usuário.

Exemplo de solicitação reemitida

{
    "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 do SDK

.NET

Para receber e processar consultas com o SDK do Bot Builder para .NET, pode verificar o invoke tipo de ação na atividade de entrada e, em seguida, utilizar o método auxiliar no pacote NuGet Microsoft.Bot.Connector.Teams para determinar se é uma atividade de extensão de mensagens.

Código de exemplo no .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 exemplo no 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

Amostras de estrutura de bot