メッセージ拡張機能を使用した検索

重要

このセクションの記事は、v3 Bot Framework SDK に基づいています。 現在のドキュメント (バージョン 4.6 以降のバージョンの SDK) をお探しの場合は、「 メッセージ拡張機能とのタスク指向の対話 」セクションを参照してください。

検索ベースのメッセージ拡張機能を使用すると、サービスに対してクエリを実行し、その情報をカードの形式でメッセージに投稿できます。

メッセージ拡張機能のカードの例を示すスクリーンショット。

次のセクションでは、これを行う方法について説明します。

アプリにメッセージ拡張機能を追加する

メッセージ拡張機能は、ユーザーの要求をリッスンし、カードなどの構造化データで応答するクラウドホスト型サービスです。 Bot Framework Activity オブジェクトを使用して、サービスを Microsoft Teams と統合します。 Bot Builder SDK の .NET および Node.js 拡張機能は、アプリにメッセージ拡張機能機能を追加するのに役立ちます。

Teams のアクション ベースのメッセージ拡張機能を示すスクリーンショット。

Bot Framework に登録する

まだ登録していない場合は、まずボットをMicrosoft Bot Frameworkに登録する必要があります。 ボットの Microsoft アプリ ID とコールバック エンドポイントは、そこで定義されているように、メッセージ拡張機能でユーザーの要求を受信して応答するために使用されます。 必ずボットの Microsoft Teams チャネルを有効にしてください。

ボット アプリ ID とアプリ パスワードをメモします。アプリ マニフェストでアプリ ID を指定する必要があります。

アプリ マニフェストを更新する

ボットとタブと同様に、アプリの マニフェスト を更新してメッセージ拡張機能のプロパティを含めます。 これらのプロパティは、Microsoft Teams クライアントでのメッセージ拡張機能の表示方法と動作を制御します。 メッセージ拡張機能は、マニフェスト v1.0 以降でサポートされています。

メッセージ拡張機能を宣言する

メッセージ拡張機能を追加するには、 プロパティを使用して、マニフェストに新しい最上位の JSON 構造を composeExtensions 含めます。 現時点では、アプリの 1 つのメッセージ拡張機能の作成に制限されています。

注:

マニフェストは、メッセージ拡張機能を として composeExtensions参照します。 これは、下位互換性を維持するためです。

拡張定義は、次の構造を持つオブジェクトです。

プロパティ名 用途 必須
botId Bot Framework に登録された、ボット用の一意の Microsoft アプリ ID。 これは通常、Teams アプリ全体の ID と同じである必要があります。 はい
scopes この拡張機能をスコープまたはteamスコープ (またはその両方) にpersonal追加できるかどうかを宣言する配列。 はい
canUpdateConfiguration [設定] メニュー項目を有効にします。 なし
commands このメッセージ拡張機能がサポートするコマンドの配列。 コマンドは 10 個に制限されています。 はい

コマンドを定義する

メッセージ拡張機能で 1 つのコマンドを宣言する必要があります。このコマンドは、ユーザーが作成ボックスの [ その他のオプション ()] ボタンからアプリを選択したときに表示されます。

スクリーンショットは、Teams のメッセージ拡張機能の一覧を示す例です。

アプリ マニフェストでは、コマンド項目は次の構造を持つオブジェクトです。

プロパティ名 用途 必須 マニフェストの最小バージョン
id このコマンドに割り当てる一意の ID。 ユーザー要求には、この ID が含まれます。 はい 1.0
title コマンド名。 この値は UI に表示されます。 はい 1.0
description このコマンドの動作を示すヘルプ テキスト。 この値は UI に表示されます。 はい 1.0
type コマンドの種類を設定します。 使用可能な値は、queryaction です。 存在しない場合、既定値は に query設定されます。 いいえ 1.4
initialRun コマンドで使用される省略可能な query パラメーター。 true に設定されている場合は、ユーザーが UI でこのコマンドを選択するとすぐに、このコマンドを実行する必要があることを示します。 いいえ 1.0
fetchTask コマンドで使用される省略可能な action パラメーター。 タスク モジュール内に表示するアダプティブ カードまたは Web URL を取得するには、true に設定します。 これは、静的なパラメーター セットではなく、 action コマンドへの入力が動的な場合に使用されます。 true に設定すると、コマンドの静的パラメーター リストは無視されることに注意してください。 いいえ 1.4
parameters コマンドのパラメーターの静的リスト。 はい 1.0
parameter.name パラメーターの名前です。 これは、ユーザー要求でサービスに送信されます。 はい 1.0
parameter.description このパラメーターの目的と、指定する必要がある値の例について説明します。 この値は UI に表示されます。 はい 1.0
parameter.title 短い使いやすいパラメーター のタイトルまたはラベル。 はい 1.0
parameter.inputType 必要な入力の種類に設定します。 指定できる値には、、numbertextareadatetimetoggle含まれますtext。 既定値は に text設定されています。 いいえ 1.4
context メッセージ アクションが使用できるコンテキストを定義する値の省略可能な配列。 指定できる値は、 message、、 composeまたは commandBoxです。 既定値は ["compose", "commandBox"] です。 いいえ 1.5

検索の種類のメッセージ拡張機能

検索ベースのメッセージ拡張機能の場合は、 パラメーターを typequery設定します。 次に、1 つの検索コマンドを持つマニフェストの例を示します。 1 つのメッセージ拡張機能には、最大 10 個の異なるコマンドを関連付けることができます。 これには、複数の検索コマンドと複数のアクション ベースのコマンドの両方を含めることができます。

完全なアプリ マニフェストの例

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

アップロードによるテスト

アプリをアップロードすることで、メッセージ拡張機能をテストできます。

メッセージ拡張機能を開くには、チャットまたはチャネルのいずれかに移動します。 作成ボックスで [ その他のオプション ()] ボタンを選択し、メッセージ拡張機能を選択します。

イベント ハンドラーを追加する

ほとんどの作業には、メッセージ拡張ウィンドウ内のすべての操作を処理するイベントが含 onQuery まれます。

マニフェストで を にtrue設定canUpdateConfigurationした場合は、メッセージ拡張機能の [設定] メニュー項目を有効にし、 と onSettingsUpdateも処理onQuerySettingsUrlする必要があります。

onQuery イベントを処理する

メッセージ拡張機能は、 onQuery メッセージ拡張ウィンドウで何らかの処理が行われた場合、またはウィンドウに送信されたときにイベントを受け取ります。

メッセージ拡張機能で構成ページを使用する場合は、格納されている構成情報に対してハンドラーonQueryが最初にチェックする必要があります。メッセージ拡張機能が構成されていない場合は、構成ページへのリンクを含む応答を返しますconfig。 構成ページからの応答も によって onQuery処理されます。 唯一の例外は、 のハンドラー onQuerySettingsUrlによって構成ページが呼び出されたときです。次のセクションを参照してください。

メッセージ拡張機能で認証が必要な場合は、ユーザー状態情報をチェックします。 ユーザーがサインインしていない場合は、この記事の後半の 「認証 」セクションの手順に従ってください。

次に、設定されているかどうかをinitialRunチェックします。設定されている場合は、指示の提供や応答の一覧などの適切なアクションを実行します。

ハンドラーonQueryの残りの部分では、ユーザーに情報の入力を求め、プレビュー カードの一覧を表示し、ユーザーが選択したカードを返します。

onQuerySettingsUrl イベントと onSettingsUpdate イベントを処理する

イベントと onSettingsUpdate イベントはonQuerySettingsUrl連携して、[設定] メニュー項目を有効にします。

[設定] メニュー項目の場所を示すスクリーンショット。

onQuerySettingsUrl ハンドラーは、構成ページの URL を返します。構成ページが閉じると、 の onSettingsUpdate ハンドラーは、返された状態を受け入れて保存します。 これは、構成ページから応答を受け取らない 1 つのケースonQueryです。

クエリの受信と応答

メッセージ拡張機能に対するすべての要求は、コールバック URL に投稿される オブジェクトを介して Activity 行われます。 要求には、ID やパラメーター値など、ユーザー コマンドに関する情報が含まれています。 要求では、ユーザーとテナント ID など、拡張機能が呼び出されたコンテキストに関するメタデータと、チャット ID またはチャネルとチーム ID も提供されます。

ユーザー要求を受信する

ユーザーがクエリを実行すると、Microsoft Teams はサービスに標準の Bot Framework Activity オブジェクトを送信します。 サービスはtype、次のActivity表に示すように、 にinvoke設定されname、サポートされている型に設定されている composeExtensions のロジックを実行する必要があります。

標準のボット アクティビティプロパティに加えて、ペイロードには次の要求メタデータが含まれています。

プロパティ名 用途
type 要求の種類。は である invoke必要があります。
name サービスに対して発行されるコマンドの種類。 現在、次の種類がサポートされています。
composeExtension/query
composeExtension/querySettingUrl
composeExtension/setting
composeExtension/selectItem
composeExtension/queryLink
from.id 要求を送信したユーザーの ID。
from.name 要求を送信したユーザーの名前。
from.aadObjectId Microsoft Entra要求を送信したユーザーのオブジェクト ID。
channelData.tenant.id テナント ID をMicrosoft Entraします。
channelData.channel.id チャネル ID (要求がチャネルで行われた場合)。
channelData.team.id チーム ID (要求がチャネルで行われた場合)。
clientInfo ユーザーのメッセージの送信に使用されるクライアント ソフトウェアに関する省略可能なメタデータ。 エンティティには、次の 2 つのプロパティを含めることができます。
countryフィールドには、ユーザーが検出した場所が含まれます。
フィールドには platform 、メッセージング クライアント プラットフォームについて説明します。
詳細については、「IRI 以外のエンティティ型 —clientInfo」を参照してください

要求パラメーターは、次のプロパティを含む value オブジェクトにあります。

プロパティ名 用途
commandId ユーザーによって呼び出されるコマンドの名前。アプリ マニフェストで宣言されているコマンドのいずれかと一致します。
parameters パラメーターの配列: 各パラメーター オブジェクトには、パラメーター名と、ユーザーによって提供されるパラメーター値が含まれます。
queryOptions 改ページ パラメーター:
skip: このクエリのスキップ数
count: 返す要素の数

要求の例

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

外部サービスを検索する代わりに (または)、compose メッセージ ボックスに挿入された URL を使用してサービスにクエリを実行し、カードを返すことができます。 次のスクリーンショットでは、ユーザーが Azure DevOps の作業項目の URL を貼り付け、メッセージ拡張機能がカードに解決しました。

リンクの展開の例を示すスクリーンショット。

メッセージ拡張機能がこのようにリンクを操作できるようにするには、最初に、例のように配列を messageHandlers アプリ マニフェストに追加する必要があります。

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

アプリ マニフェストをリッスンするドメインを追加したら、次の呼び出し要求に 応答 するようにボット コードを変更する必要があります。

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

アプリが複数の項目を返す場合は、最初の項目のみが使用されます。

ユーザーの要求に応答する

ユーザーがクエリを実行すると、Teams はサービスに同期 HTTP 要求を発行します。 この間、コードは要求に対する HTTP 応答を提供するために 5 秒です。 この間、サービスは、別の参照、または要求を処理するために必要なその他のビジネス ロジックを実行できます。

サービスは、ユーザー クエリに一致する結果で応答する必要があります。 応答は、 の HTTP 状態コードと、次の 200 OK 本文を持つ有効な application/json オブジェクトを示す必要があります。

プロパティ名 用途
composeExtension 最上位レベルの応答エンベロープ。
composeExtension.type 応答の種類。 次の種類がサポートされています。
result: 検索結果の一覧を表示します
auth: ユーザーに認証を求めるメッセージ
config: メッセージ拡張機能の設定をユーザーに求めるメッセージ
message: テキスト形式のメッセージを表示する
composeExtension.attachmentLayout 添付ファイルのレイアウトを指定します。 型 resultの応答に使用されます。
現在、次の種類がサポートされています。
list: サムネイル、タイトル、テキスト フィールドを含むカード オブジェクトの一覧
grid: サムネイル画像のグリッド
composeExtension.attachments 有効な添付ファイル オブジェクトの配列。 型 resultの応答に使用されます。
現在、次の種類がサポートされています。
application/vnd.microsoft.card.thumbnail
application/vnd.microsoft.card.hero
application/vnd.microsoft.teams.card.o365connector
application/vnd.microsoft.card.adaptive
composeExtension.suggestedActions 推奨されるアクション。 型 auth または configの応答に使用されます。
composeExtension.text 表示するメッセージ。 型 messageの応答に使用されます。

応答カードの種類とプレビュー

次の添付ファイルの種類がサポートされています。

詳細については、概要については、「 カード 」を参照してください。

サムネイルとヒーローのカードの種類を使用する方法については、「カードの追加とアクションのカード」を参照してください。

Microsoft 365 グループのコネクタ カードの詳細については、「Microsoft 365 グループにコネクタ カードを使用する」を参照してください。

結果の一覧が Microsoft Teams UI に表示され、各項目のプレビューが表示されます。 プレビューは、次の 2 つの方法のいずれかで生成されます。

  • オブジェクト内で preview プロパティを attachment 使用する。 添付ファイルにはpreview、ヒーローまたはサムネイルのカードのみを指定できます。
  • 添付ファイルの基本的な titletext、および image プロパティから抽出されます。 これらは、 プロパティが設定されておらず、 preview これらのプロパティが使用可能な場合にのみ使用されます。

プレビュー プロパティを設定するだけで、結果の一覧にMicrosoft 365 グループのアダプティブまたはコネクタ カードのプレビューを表示できます。 これは、結果が既にヒーロー カードまたはサムネイル カードである場合は必要ありません。 プレビュー添付ファイルを使用する場合は、ヒーローまたはサムネイル カードである必要があります。 preview プロパティが指定されていない場合、カードのプレビューは失敗し、何も表示されません。

応答の例

次の例は、Microsoft 365 グループ用コネクタとアダプティブ型の 2 つの結果で、異なるカード形式が混在する応答を示しています。 応答には 1 つのカード形式を使用する必要がある場合があります。前述のように、コレクション内の各要素のプロパティでattachmentsプレビューをヒーローまたはサムネイル形式で明示的に定義する必要がある方法previewが示されています。

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

既定のクエリ

マニフェストで を にtrue設定initialRunした場合、Microsoft Teams は、ユーザーが最初にメッセージ拡張機能を開いたときに "既定" クエリを発行します。 サービスは、事前設定された結果のセットを使用して、このクエリに応答できます。 これは、最近表示されたアイテム、お気に入り、またはユーザー入力に依存しないその他の情報を表示する場合に役立ちます。

既定のクエリは、文字列値が であるパラメーター initialRun を使用する場合を除き、通常のユーザー クエリと同じ構造を true持ちます。

既定のクエリの要求の例

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

ユーザーを識別する

サービスに対するすべての要求には、要求を実行したユーザーの難読化された ID と、ユーザーの表示名とオブジェクト ID Microsoft Entraが含まれます。

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

aadObjectIdid値は、認証された Teams ユーザーの値であることが保証されます。 これらは、資格情報またはサービス内のキャッシュされた状態を検索するためのキーとして使用できます。 さらに、各要求には、ユーザーのMicrosoft Entra テナント ID が含まれています。これは、ユーザーのorganizationを識別するために使用できます。 該当する場合、要求には、要求の送信元のチーム ID とチャネル ID も含まれます。

認証

サービスでユーザー認証が必要な場合は、ユーザーがメッセージ拡張機能を使用する前にユーザーにサインインする必要があります。 ユーザーにサインインするボットまたはタブを作成した場合は、このセクションをよく理解している必要があります。

シーケンスは次のとおりです。

  1. ユーザーがクエリを発行するか、既定のクエリがサービスに自動的に送信されます。
  2. サービスは、Teams ユーザー ID を検査して、ユーザーが最初に認証されたかどうかを確認します。
  3. ユーザーが認証されていない場合は、認証 URL を含む推奨されるアクションをopenUrl含む応答を返しますauth
  4. Microsoft Teams クライアントは、指定された認証 URL を使用して Web ページをホストするポップアップ ウィンドウを起動します。
  5. ユーザーがサインインしたら、ウィンドウを閉じ、Teams クライアントに "認証コード" を送信する必要があります。
  6. その後、Teams クライアントは、手順 5 で渡された認証コードを含むクエリをサービスに再発行します。 サービスは、手順 6 で受け取った認証コードが手順 5 の認証コードと一致することを確認する必要があります。これにより、悪意のあるユーザーがサインイン フローのなりすましや侵害を試みないようにします。 これにより、安全な認証シーケンスを終了させるための 「ループを閉じる」 効果があります。

サインイン アクションで応答する

認証されていないユーザーにサインインを求めるには、認証 URL を含む openUrl 型の推奨アクションで応答します。

サインイン アクションの応答の例

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

注:

サインイン エクスペリエンスを Teams ポップアップでホストするには、URL のドメイン部分がアプリの有効なドメインの一覧に含まれている必要があります。 詳細については、「マニフェスト スキーマのvalidDomains」 を参照してください。

サインイン フローを開始する

サインインは応答性が高く、ポップアップ ウィンドウ内に収まる必要があります。 メッセージ パッシングを使用する Microsoft Teams JavaScript クライアント SDK と統合する必要があります。

Teams 内で実行されている他の埋め込みエクスペリエンスと同様に、ウィンドウ内のコードは最初に を呼び出す microsoftTeams.initialize()必要があります。 コードが OAuth フローを実行する場合は、Teams ユーザー ID をウィンドウに渡し、OAuth サインイン URL の URL に渡すことができます。

サインイン フローを完了する

サインイン要求が完了し、ページにリダイレクトされたら、次の手順を実行する必要があります。

  1. セキュリティ コードを生成します。 (乱数を指定できます)。このコードは、OAuth 2.0 トークンなどのサインインによって取得された資格情報と共に、サービスにキャッシュする必要があります。
  2. microsoftTeams.authentication.notifySuccess を呼び出して、セキュリティ コードを渡します。

この時点で、ウィンドウが閉じられ、コントロールが Teams クライアントに渡されます。 クライアントは、 プロパティのセキュリティ コードと共に元のユーザー クエリを state 再発行できるようになりました。 コードでは、セキュリティ コードを使用して、前に保存した資格情報を検索して認証シーケンスを完了し、ユーザー要求を完了できます。

再発行された要求の例

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

SDK のサポート

.NET

Bot Builder SDK for .NET でクエリを受信して処理するには、受信アクティビティのアクションの種類をチェックinvokeしてから、NuGet パッケージ Microsoft.Bot.Connector.Teams のヘルパー メソッドを使用して、メッセージ拡張アクティビティであるかどうかを判断できます。

.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

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 Samples (Bot Framework のサンプル)