Поиск с расширениями обмена сообщениямиSearch with messaging extensions

Важно!

Статьи, приведенные в этом разделе, основаны на пакете SDK "V3 Bot Framework".The articles in this section are based on the v3 Bot Framework SDK. Если вы ищете текущую документацию (версия 4,6 или более поздняя версия пакета SDK), ознакомьтесь со статьей " взаимодействия, ориентированные на задачи с расширениями обмена сообщениями ".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.

Расширения обмена сообщениями на основе поиска позволяют запросить службу и отправить эти сведения в виде карточки, прямо в сообщение.Search based messaging extensions allow you to query your service and post that information in the form of a card, right into your message

Пример карточки расширения обмена сообщениями

В следующих разделах описано, как это сделать.The following sections describe how to do this.

Добавление расширения обмена сообщениями в приложениеAdd a messaging extension to your app

Расширение системы обмена сообщениями — это размещенная в облаке служба, которая прослушивает запросы пользователей и отвечает на структурированные данные, такие как карточка.A messaging extension is a cloud-hosted service that listens to user requests and responds with structured data, such as a card. Вы интегрируете службу с Microsoft Teams с помощью Activity объектов Bot Framework.You integrate your service with Microsoft Teams via Bot Framework Activity objects. Наши расширения .NET и Node. js для пакета SDK построителя построителя могут помочь добавить функциональность расширения обмена сообщениями в приложение.Our .NET and Node.js extensions for the Bot Builder SDK can help you add messaging extension functionality to your app.

Схема процесса обработки сообщений для расширений обмена сообщениями

Регистрация в Bot FrameworkRegister in the Bot Framework

Если вы еще не сделали этого, сначала необходимо зарегистрировать Bot с помощью Microsoft Bot Framework.If you haven’t done so already, you must first register a bot with the Microsoft Bot Framework. Идентификатор приложения Microsoft и конечные точки обратного вызова для ленты, как определено, будут использоваться в вашем расширении обмена сообщениями для получения запросов пользователей и реагирования на них.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. Не забудьте включить канал Microsoft Teams для ленты.Remember to enable the Microsoft Teams channel for your bot.

Запишите идентификатор приложения Bot и пароль приложения, вам потребуется указать идентификатор приложения в манифесте приложения.Record your bot app ID and app password, you will need to supply the app ID in your app manifest.

Обновление манифеста приложенияUpdate your app manifest

Как и в случае с Боты и вкладками, Манифест приложения можно изменить, добавив в него свойства расширения Messaging.As with bots and tabs, you update the manifest of your app to include the messaging extension properties. Эти свойства определяют, как ваше расширение обмена сообщениями отображается и работает в клиенте Microsoft Teams.These properties govern how your messaging extension appears and behaves in the Microsoft Teams client. Расширения обмена сообщениями поддерживаются начиная с версии 1.0 манифеста.Messaging extensions are supported beginning with v1.0 of the manifest.

Объявление расширения обмена сообщениямиDeclare your messaging extension

Чтобы добавить расширение обмена сообщениями, включите новую структуру JSON верхнего уровня в манифест со composeExtensions свойством.To add a messaging extension, include a new top-level JSON structure in your manifest with the composeExtensions property. В настоящее время вы можете создать только один добавочный номер для обмена сообщениями для вашего приложения.Currently, you are limited to creating a single messaging extension for your app.

Примечание

Манифест содержит ссылки на расширения обмена сообщениями composeExtensions.The manifest refers to messaging extensions as composeExtensions. Это необходимо для обеспечения обратной совместимости.This is to maintain backward compatibility.

Определение расширения — это объект, имеющий следующую структуру:The extension definition is an object that has the following structure:

Имя свойстваProperty name НазначениеPurpose Обязательный?Required?
botId Уникальный идентификатор приложения для ленты, зарегистрированный с помощью Bot Framework.The unique Microsoft app ID for the bot as registered with the Bot Framework. Как правило, это должен быть тот же идентификатор, что и для всего приложения Teams.This should typically be the same as the ID for your overall Teams app. ДаYes
scopes Массив, объявляющий, можно ли добавлять это расширение personal в team области или в области (или и то, и другое).Array declaring whether this extension can be added to personal or team scopes (or both). ДаYes
canUpdateConfiguration Включает пункт меню параметров .Enables Settings menu item. НетNo
commands Массив команд, поддерживаемых этим расширением обмена сообщениями.Array of commands that this messaging extension supports. Можно выполнить не более 10 команд.You are limited to 10 commands. ДаYes

Определение командDefine commands

Ваш модуль обмена сообщениями должен объявить одну команду, которая появляется, когда пользователь выбирает приложение из кнопки Дополнительные параметры () в поле Создать.Your messaging extension should declare one command, which appears when the user selects your app from the More options () button in the compose box.

Снимок экрана: список расширений обмена сообщениями в Teams

В манифесте приложения командный элемент представляет собой объект со следующей структурой:In the app manifest, your command item is an object with the following structure:

Имя свойстваProperty name НазначениеPurpose Обязательный?Required? Минимальная версия манифестаMinimum manifest version
id Уникальный идентификатор, назначенный этой команде.Unique ID that you assign to this command. Запрос пользователя будет включать этот идентификатор.The user request will include this ID. ДаYes 1.01.0
title Имя команды.Command name. Это значение отображается в пользовательском интерфейсе.This value appears in the UI. ДаYes 1.01.0
description Текст справки, указывающий, что делает эта команда.Help text indicating what this command does. Это значение отображается в пользовательском интерфейсе.This value appears in the UI. ДаYes 1.01.0
type Задайте тип команды.Set the type of command. Возможные значения: query и action.Possible values include query and action. Если не указано, по умолчанию установлено значениеqueryIf not present the default value is set to query НетNo 1.41.4
initialRun Необязательный параметр, query используемый с командами.Optional parameter, used with query commands. Если задано значение true, то эта команда должна выполняться сразу после того, как пользователь выберет эту команду в пользовательском интерфейсе.If set to true, indicates this command should be executed as soon as the user chooses this command in the UI. НетNo 1.01.0
fetchTask Необязательный параметр, action используемый с командами.Optional parameter, used with action commands. Установите значение true для получения URL-адреса адаптивной карты или веб-сайта для отображения в модуле задачи.Set to true to fetch the adaptive card or web url to display within the task module. Используется, когда входные данные action команды динамически, а не статический набор параметров.This is used when the inputs to the action command is dynamic as opposed to a static set of parameters. Обратите внимание, что если задано значение true , то список статических параметров для команды игнорируетсяNote that the if set to true the static parameter list for the command is ignored НетNo 1.41.4
parameters Статический список параметров для команды.Static list of parameters for the command. ДаYes 1.01.0
parameter.name Имя параметра.The name of the parameter. Он отправляется службе по запросу пользователя.This is sent to your service in the user request. ДаYes 1.01.0
parameter.description Описывает назначение этого параметра или пример значения, которое следует предоставить.Describes this parameter’s purposes or example of the value that should be provided. Это значение отображается в пользовательском интерфейсе.This value appears in the UI. ДаYes 1.01.0
parameter.title Краткий заголовком или меткой с понятным пользователем параметром.Short user-friendly parameter title or label. ДаYes 1.01.0
parameter.inputType Укажите требуемый тип ввода.Set to the type of input required. Возможные значения: text, textarea, number, date, time, toggle.Possible values include text, textarea, number, date, time, toggle. Значение по умолчанию:textDefault is set to text НетNo 1.41.4
context Необязательный массив значений, определяющий контекст, в котором доступно действие с сообщением.Optional array of values that defines the context the message action is available in. Возможные значения: message, compose, или commandBox.Possible values are message, compose, or commandBox. Значение по умолчанию: ["compose", "commandBox"].Default is ["compose", "commandBox"]. НетNo 1.51.5

Расширения сообщений для типа поискаSearch type message extensions

Для расширения системы обмена сообщениями на основе поиска задайте type для параметра значение query .For search based messaging extension set the type parameter to query. Ниже приведен пример манифеста с одной командой поиска.Below is an example of a manifest with a single search command. Одно расширение обмена сообщениями может иметь до 10 различных команд, связанных с ней.A single messaging extension can have up to 10 different commands associated with it. Сюда могут входить как несколько команд поиска, так и несколько команд, основанных на действиях.This can include both multiple search and multiple Action-based commands.

Пример полного манифеста приложенияComplete app manifest example

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

Тестирование через отправкуTest via uploading

Вы можете проверить расширение системы обмена сообщениями, отправив свое приложение.You can test your messaging extension by uploading your app.

Чтобы открыть расширение системы обмена сообщениями, перейдите к любому из бесед или каналов.To open your messaging extension, navigate to any of your chats or channels. Нажмите кнопку Дополнительные параметры ( ) в поле создать и выберите ваш добавочный номер для обмена сообщениями.Choose the More options ( ) button in the compose box, and choose your messaging extension.

Добавление обработчиков событийAdd event handlers

Большая часть работы включает onQuery событие, которое обрабатывает все взаимодействия в окне расширения системы обмена сообщениями.Most of your work involves the onQuery event, which handles all interactions in the messaging extension window.

Если вы задаете значение canUpdateConfiguration true в манифесте, вы включаете элемент меню Параметры для расширения системы обмена сообщениями, а также обрабатывает onQuerySettingsUrl и 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.

Обработка событий onqueryHandle onQuery events

Расширение системы обмена сообщениями получает onQuery событие, когда что-то происходит в окне расширения обмена сообщениями или отправляется в окно.A messaging extension receives an onQuery event when anything happens in the messaging extension window or is sent to the window.

Если расширение системы обмена сообщениями использует страницу конфигурации, обработчик onQuery должен сначала проверить наличие сохраненных сведений о конфигурации; если расширение системы обмена сообщениями не настроено, возвращайте config ответ со ссылкой на страницу конфигурации.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. Помните, что ответ на странице конфигурации также обрабатывается onQuery .Be aware that the response from the configuration page is also handled by onQuery. (Единственное исключение — при вызове страницы конфигурации обработчиком onQuerySettingsUrl ; в следующем разделе.)(The sole exception is when the configuration page is called by the handler for onQuerySettingsUrl; see the following section.)

Если для расширения системы обмена сообщениями требуется проверка подлинности, проверьте сведения о состоянии пользователя; Если пользователь не вошел в систему, следуйте инструкциям в разделе authentication (проверка подлинности ) далее в этом разделе.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.

Затем проверьте, initialRun установлено ли значение; если это так, выполните соответствующие действия, такие как предоставление инструкций или списка ответов.Next, check whether initialRun is set; if so, take appropriate action, such as providing instructions or a list of responses.

В оставшейся части обработчика onQuery запрашивается информация для пользователя, отображается список карточек предварительного просмотра и возвращается карточка, выбранная пользователем.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.

Обработка событий Онкуерисеттингсурл и ОнсеттингсупдатеHandle onQuerySettingsUrl and onSettingsUpdate events

onQuerySettingsUrlСобытия and onSettingsUpdate работают вместе, чтобы включить элемент меню Параметры .The onQuerySettingsUrl and onSettingsUpdate events work together to enable the Settings menu item.

Снимки экрана расположения элемента меню параметров

Обработчик onQuerySettingsUrl возвращает URL-адрес страницы конфигурации; после закрытия страницы конфигурации обработчик onSettingsUpdate принимает и сохраняет возвращенное состояние.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. (Это тот случай, когда onQuery не получает ответ на страницу настройки.)(This is the one case in which onQuery doesn't receive the response from the configuration page.)

Получение запросов и реагирование на нихReceive and respond to queries

Каждый запрос к своему расширению обмена сообщениями выполняется через Activity объект, который отправляется на URL-адрес обратного вызова.Every request to your messaging extension is done via an Activity object that is posted to your callback URL. Запрос содержит сведения о команде User, такие как идентификатор и значения параметров.The request contains information about the user command, such as ID and parameter values. В запросе также предоставляются метаданные о контексте, в котором был вызван ваш добавочный номер, включая ИДЕНТИФИКАТОРы пользователей и клиентов, а также ИДЕНТИФИКАТОРы и идентификаторы каналов и групп.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.

Получение запросов пользователейReceive user requests

Когда пользователь выполняет запрос, Microsoft Teams отправляет службу стандартным объектом Bot Framework Activity .When a user performs a query, Microsoft Teams sends your service a standard Bot Framework Activity object. Служба должна выполнять свою логику для параметра Activity , для которого type установлено invoke значение name поддерживаемого composeExtension типа, как показано в следующей таблице.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.

В дополнение к стандартным свойствам действия Bot полезные данные содержат следующие метаданные запроса:In addition to the standard bot activity properties, the payload contains the following request metadata:

Имя свойстваProperty name НазначениеPurpose
type Тип запроса; должно быть invoke .Type of request; must be invoke.
name Тип команды, выданной службе.Type of command that is issued to your service. В настоящее время поддерживаются следующие типы:Currently the following types are supported:
composeExtension/query
composeExtension/querySettingUrl
composeExtension/setting
composeExtension/selectItem
composeExtension/queryLink
from.id Идентификатор пользователя, отправившего запрос.ID of the user that sent the request.
from.name Имя пользователя, отправившего запрос.Name of the user that sent the request.
from.aadObjectId Идентификатор объекта Azure Active Directory пользователя, отправившего запрос.Azure Active Directory object id of the user that sent the request.
channelData.tenant.id Идентификатор клиента Azure Active Directory.Azure Active Directory tenant ID.
channelData.channel.id Идентификатор канала (если запрос был сделан в канале).Channel ID (if the request was made in a channel).
channelData.team.id Идентификатор группы (если запрос был сделан в канале).Team ID (if the request was made in a channel).
clientInfo Необязательные метаданные о клиентском программном обеспечении, используемом для отправки сообщения пользователя.Optional metadata about the client software used to send a user's message. Сущность может содержать два свойства:The entity can contain two properties:
В этом country поле содержится обнаруженное пользователем расположение.The country field contains the user's detected location.
platformПоле описывает клиентскую платформу обмена сообщениями.The platform field describes the messaging client platform.
Дополнительную информацию можно узнать в статье типы не-IRI, клиентинфо.For additional information, please see Non-IRI entity types — clientInfo.

Собственно параметры запроса находятся в объекте value, который включает следующие свойства:The request parameters itself are found in the value object, which includes the following properties:

Имя свойстваProperty name НазначениеPurpose
commandId Имя команды, вызываемой пользователем, которая соответствует одной из команд, объявленных в манифесте приложения.The name of the command invoked by the user, matching one of the commands declared in the app manifest.
parameters Массив параметров.Array of parameters. Каждый объект Parameter содержит имя параметра вместе со значением параметра, предоставленным пользователем.Each parameter object contains the parameter name, along with the parameter value provided by the user.
queryOptions Параметры разбивки на страницы:Pagination parameters:
skip: количество пропусков для этого запросаskip: skip count for this query
count: число возвращаемых элементовcount: number of elements to return

Пример запросаRequest 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"
    }
  ]
}

В качестве альтернативы (или дополнительно) для поиска во внешней службе можно использовать URL-адрес, вставленный в поле создать сообщение, чтобы отправить запрос в службу и возвратить карточку.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. На снимке экрана после вставки пользователя в URL-адрес рабочего элемента в Azure DevOps, который разрешал расширение обмена сообщениями в карточке.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.

Пример ссылки унфурлинг

Чтобы разрешить своему расширению обмена сообщениями взаимодействовать с ссылками таким способом, сначала необходимо добавить messageHandlers массив в манифест приложения, как показано в примере ниже: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"
          ]
        }
      }
    ]
  }
]

Добавив домен для прослушивания манифеста приложения, вам потребуется изменить код ленты, чтобы ответить на следующий запрос Invoke.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"
  }
}

Если ваше приложение возвращает несколько элементов, будет использоваться только первый.If your app returns multiple items only the first will be used.

Ответ на запросы пользователейRespond to user requests

Когда пользователь выполняет запрос, Microsoft Teams отправляет службе синхронный HTTP-запрос.When the user performs a query, Microsoft Teams issues a synchronous HTTP request to your service. В этот момент код имеет 5 секунд, чтобы предоставить HTTP-ответ на запрос.At that point, your code has 5 seconds to provide an HTTP response to the request. В течение этого времени служба может выполнять дополнительные операции поиска или любую другую бизнес-логику, необходимую для обслуживания запроса.During this time, your service can perform additional lookup, or any other business logic needed to serve the request.

Служба должна отвечать на результаты, соответствующие запросу пользователя.Your service should respond with the results matching the user query. Ответ должен указывать код состояния HTTP 200 OK и допустимый объект Application/JSON следующего основного текста:The response must indicate an HTTP status code of 200 OK and a valid application/json object with the following body:

Имя свойстваProperty name НазначениеPurpose
composeExtension Конверт отклика верхнего уровня.Top-level response envelope.
composeExtension.type Тип ответа.Type of response. Поддерживаются следующие типы:The following types are supported:
result: отображает список результатов поискаresult: displays a list of search results
auth: запрос на проверку подлинности пользователяauth: asks the user to authenticate
config: запрашивает у пользователя установку расширения для обмена сообщениямиconfig: asks the user to set up the messaging extension
message: отображается обычное текстовое сообщениеmessage: displays a plain text message
composeExtension.attachmentLayout Задает макет вложений.Specifies the layout of the attachments. Используется для ответов типа result .Used for responses of type result.
В настоящее время поддерживаются следующие типы:Currently the following types are supported:
list: список объектов карточек, содержащих поля эскиза, заголовка и текста.list: a list of card objects containing thumbnail, title, and text fields
grid: сетка эскизов изображенийgrid: a grid of thumbnail images
composeExtension.attachments Массив допустимых объектов вложений.Array of valid attachment objects. Используется для ответов типа result .Used for responses of type result.
В настоящее время поддерживаются следующие типы: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 Предложенные действия.Suggested actions. Используется для ответов типа auth или config .Used for responses of type auth or config.
composeExtension.text Сообщение для отображения.Message to display. Используется для ответов типа message .Used for responses of type message.

Типы карточек ответа и предварительный просмотрResponse card types and previews

Поддерживаются следующие типы вложений:We support the following attachment types:

Общие сведения приведены в карточки .See Cards for an overview.

Сведения о том, как использовать типы карт эскизов и главный Имиджевый баннер, приведены в разделе Add cards and Card Actions.To learn how to use the thumbnail and hero card types, see Add cards and card actions.

Дополнительную документацию по карте соединителей Office 365 можно узнать в статье Использование соединителей карт office 365.For additional documentation regarding the Office 365 Connector card, see Using Office 365 Connector cards.

Список результатов отображается в пользовательском интерфейсе Microsoft Teams с предварительным просмотром каждого элемента.The result list is displayed in the Microsoft Teams UI with a preview of each item. Предварительный просмотр создается одним из двух способов:The preview is generated in one of two ways:

  • Использование preview свойства в attachment объекте.Using the preview property within the attachment object. previewВложение может быть только картой главный Имиджевый баннер или эскиза.The preview attachment can only be a Hero or Thumbnail card.
  • Извлекается из базового title text image Свойства и свойства вложения.Extracted from the basic title, text, and image properties of the attachment. Они используются только в том случае, если preview свойство не задано, а эти свойства доступны.These are used only if the preview property is not set and these properties are available.

Вы можете просмотреть предварительный просмотр адаптивной карты или карты Office 365 в списке результатов, просто задав свойство Preview; Это не требуется, если результаты уже главный Имиджевый баннер или эскизы страниц.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. Если вы используете предварительный просмотр вложения, это должна быть карта главный Имиджевый баннер или эскиза.If you use the preview attachment, it must be either a Hero or Thumbnail card. Если свойство Preview не указано, предварительный просмотр карты завершается с ошибками, и ничего не отображается.If no preview property is specified, the preview of the card will fail and nothing will be displayed.

Пример ответаResponse example

В этом примере показан ответ с двумя результатами, смешивание разных форматов карт: Office 365 Connector и адаптивный.This example shows a response with two results, mixing different card formats: Office 365 Connector and Adaptive. Хотя вы, скорее всего, захотите прикрепить к одному формату карточки в своем ответе, он показывает, как preview свойство каждого элемента в attachments коллекции должно явно определять предварительный просмотр в формате главный Имиджевый баннер или эскиза, как описано выше.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%)"
          }
        }
      }
    ]
  }
}

Запрос по умолчаниюDefault query

Если initialRun для манифеста задано значение true в манифесте, Microsoft Teams по умолчанию выдает запрос "по умолчанию", когда пользователь впервые открывает расширение системы обмена сообщениями.If you set initialRun to true in the manifest, Microsoft Teams issues a "default" query when the user first opens the messaging extension. Служба может ответить на этот запрос с помощью набора предварительно заполненных результатов.Your service can respond to this query with a set of prepopulated results. Это может быть полезно для отображения, например, недавно просмотренных элементов, избранного или любой другой информации, которая не зависит от вводимых пользователем данных.This can be useful for displaying, for instance, recently viewed items, favorites, or any other information that is not dependent on user input.

Запрос по умолчанию имеет ту же структуру, что и любой запрос обычного пользователя, за исключением параметра initialRun , строковое значение которого равно true .The default query has the same structure as any regular user query, except with a parameter initialRun whose string value is true.

Пример запроса для запроса по умолчаниюRequest example for a default query

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

Идентификация пользователяIdentify the user

Каждый запрос к службам включает в себя идентификатор пользователя, который выполнил запрос, а также отображаемое имя пользователя и идентификатор объекта 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"
},

id aadObjectId Гарантируется, что значения и значения для пользователя Teams прошли проверку подлинности.The id and aadObjectId values are guaranteed to be that of the authenticated Teams user. Они могут использоваться в качестве ключей для поиска учетных данных или любого кэшированного состояния в службе.They can be used as keys to look up credentials or any cached state in your service. Кроме того, каждый запрос содержит идентификатор клиента Azure Active Directory для пользователя, который можно использовать для определения организации пользователя.In addition, each request contains the Azure Active Directory tenant ID of the user, which can be used to identify the user’s organization. Если это возможно, запрос также содержит идентификаторы команд и каналов, из которых поступил запрос.If applicable, the request also contains the team and channel IDs from which the request originated.

Проверка подлинностиAuthentication

Если для вашей службы требуется проверка подлинности пользователя, необходимо войти в систему, прежде чем ее сможет использовать расширение системы обмена сообщениями.If your service requires user authentication, you need to sign in the user before he or she can use the messaging extension. Если вы написали робот или вкладку, которые подписываются пользователю, этот раздел должен быть знаком.If you have written a bot or a tab that signs in the user, this section should be familiar.

Последовательность выглядит следующим образом:The sequence is as follows:

  1. Пользователь выдает запрос, или запрос по умолчанию автоматически отправляется в службу.User issues a query, or the default query is automatically sent to your service.
  2. Служба проверяет, прошел ли пользователь проверку подлинности, проверив идентификатор пользователя Teams.Your service checks whether the user has first authenticated by inspecting the Teams user ID.
  3. Если пользователь не прошел проверку подлинности, отправьте auth ответ с openUrl предложенным действием, включая URL-адрес проверки подлинности.If the user has not authenticated, send back an auth response with an openUrl suggested action including the authentication URL.
  4. Клиент Microsoft Teams запускает всплывающее окно, в котором размещается веб-страница, используя указанный URL-адрес проверки подлинности.The Microsoft Teams client launches a pop-up window hosting your webpage using the given authentication URL.
  5. После входа пользователя необходимо закрыть окно и отправить ему код проверки подлинности в клиент Teams.After the user signs in, you should close your window and send an "authentication code" to the Teams client.
  6. Затем клиент Teams повторно отправляет запрос в службу, который включает код проверки подлинности, переданный на шаге 5.The Teams client then reissues the query to your service, which includes the authentication code passed in step 5.

Ваша служба должна проверить, что код проверки подлинности, полученный на шаге 6, соответствует тому, что получено на шаге 5.Your service should verify that the authentication code received in step 6 matches the one from step 5. Это гарантирует, что злоумышленник не будет пытаться подменить или ослабить процесс входа в систему.This ensures that a malicious user does not try to spoof or compromise the sign-in flow. Это фактически "закрывает цикл" для завершения безопасной последовательности проверки подлинности.This effectively "closes the loop" to finish the secure authentication sequence.

Ответ с действием входаRespond with a sign-in action

Чтобы выдать запрос пользователю, не прошедшему проверку подлинности, выполните ответ с предложенным действием типа openUrl , которое включает URL-адрес проверки подлинности.To prompt an unauthenticated user to sign in, respond with a suggested action of type openUrl that includes the authentication URL.

Пример отклика для действия при входеResponse example for a sign-in action

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

Примечание

Для того чтобы при входе в систему можно было размещаться в всплывающем окне Teams, в списке допустимых доменов приложения должен находиться домен, являющийся частью URL-адреса.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. (См. раздел валиддомаинс в схеме манифеста.)(See validDomains in the manifest schema.)

Запуск процесса входаStart the sign-in flow

Ваш интерфейс пользователя должен отвечать на запросы и размещаться в всплывающем окне.Your sign-in experience should be responsive and fit within a popup window. Он должен интегрироваться с клиентским пакетом SDK для Microsoft Teams JavaScript, который использует передачу сообщений.It should integrate with the Microsoft Teams JavaScript client SDK, which uses message passing.

Как и другие встроенные возможности, выполняемые в Microsoft Teams, код в окне должен вызываться первым microsoftTeams.initialize() .As with other embedded experiences running inside Microsoft Teams, your code inside the window needs to first call microsoftTeams.initialize(). Если ваш код выполняет процесс OAuth, можно передать идентификатор пользователя Teams в ваше окно, которое затем может передать его в URL-адрес входа 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.

Завершение процесса входаComplete the sign-in flow

Когда запрос на вход завершается и перенаправляется обратно на страницу, он должен выполнить следующие действия:When the sign-in request completes and redirects back to your page, it should perform the following steps:

  1. Создайте код безопасности.Generate a security code. (Это может быть случайное число.) Необходимо кэшировать этот код в службе, а также учетные данные, полученные с помощью процесса входа (например, OAuth 2,0 tokens).(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. Позвоните microsoftTeams.authentication.notifySuccess и передайте код безопасности.Call microsoftTeams.authentication.notifySuccess and pass the security code.

На этом шаге окно закрывается и управление передается клиенту Teams.At this point, the window closes and control is passed to the Teams client. Теперь клиент может повторно отправить исходный запрос пользователя, а также код безопасности в state свойстве.The client now can reissue the original user query, along with the security code in the state property. Код может использовать код безопасности для поиска ранее сохраненных учетных данных, чтобы выполнить последовательность проверки подлинности, а затем выполнить запрос пользователя.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.

Пример повторной выданной заявкиReissued 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"
}

Поддержка SDKSDK support

.NET.NET

Для получения и обработки запросов с помощью пакета SDK построителя построителя для .NET можно проверить invoke тип действия для входящего действия и затем использовать вспомогательный метод в пакете NuGet Microsoft. Bot. Connector. Teams , чтобы определить, является ли он действием расширения системы обмена сообщениями.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.

Пример кода в .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

Пример кода в 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();

В этой статье также приведены примеры кода Bot Framework.See also Bot Framework samples.