生成基于 API 的消息扩展
注意
基于 API 的消息扩展仅支持搜索命令。
基于 API 的消息扩展是 Microsoft Teams 应用功能,可将外部 API 直接集成到 Teams 中,从而增强应用的可用性并提供无缝的用户体验。 基于 API 的消息扩展支持搜索命令,可用于从 Teams 中的外部服务提取和显示数据,通过减少在应用程序之间切换的需要来简化工作流。
在开始之前,请确保满足以下要求:
1. OpenAPI 说明 (OAD)
确保遵循以下有关 OpenAPI 说明 (OAD) 文档的准则:
- 支持 OpenAPI 版本 2.0 和 3.0.x。
- JSON 和 YAML 是支持的格式。
- 请求正文(如果存在)必须为 application/Json。
- 为
servers.url
属性定义 HTTPS 协议服务器 URL。 - 仅支持 POST 和 GET HTTP 方法。
- OpenAPI 说明文档必须具有
operationId
。 - 仅允许一个不带默认值的必需参数。
- 具有默认值的必需参数被视为可选参数。
- 用户不得为标头或 Cookie 输入参数。
- 操作不得具有不带默认值的必需标头或 Cookie 参数。
- 确保 OpenAPI 说明文档中没有远程引用。
- 不支持为请求构造数组;但是,支持 JSON 请求正文中的嵌套对象。
- Teams 不支持
oneOf
、、anyOf
allOf
和not
(swagger.io) 构造。
以下代码是 OpenAPI 说明文档的示例:
openapi: 3.0.1
info:
title: OpenTools Plugin
description: A plugin that allows the user to find the most appropriate AI tools for their use cases, with their pricing information.
version: 'v1'
servers:
- url: https://gptplugin.opentools.ai
paths:
/tools:
get:
operationId: searchTools
summary: Search for AI Tools
parameters:
- in: query
name: search
required: true
schema:
type: string
description: Used to search for AI tools by their category based on the keywords. For example, ?search="tool to create music" will give tools that can create music.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/searchToolsResponse'
"400":
description: Search Error
content:
application/json:
schema:
$ref: '#/components/schemas/searchToolsError'
components:
schemas:
searchToolsResponse:
required:
- search
type: object
properties:
tools:
type: array
items:
type: object
properties:
name:
type: string
description: The name of the tool.
opentools_url:
type: string
description: The URL to access the tool.
main_summary:
type: string
description: A summary of what the tool is.
pricing_summary:
type: string
description: A summary of the pricing of the tool.
categories:
type: array
items:
type: string
description: The categories assigned to the tool.
platforms:
type: array
items:
type: string
description: The platforms that this tool is available on.
description: The list of AI tools.
searchToolsError:
type: object
properties:
message:
type: string
description: Message of the error.
有关详细信息,请参阅 OpenAPI 结构。
2.应用清单
确保遵循以下应用清单指南:
将应用清单版本设置为
1.17
。设置为
composeExtensions.composeExtensionType
apiBased
。定义为
composeExtensions.apiSpecificationFile
文件夹中 OpenAPI 说明文件的相对路径。 这会将应用清单链接到 API 规范。定义为
apiResponseRenderingTemplateFile
响应呈现模板的相对路径。 这将指定用于呈现 API 响应的模板的位置。每个命令都必须具有指向响应呈现模板的链接。 这会将每个命令连接到其相应的响应格式。
Commands.id
应用清单中的 属性必须与 OpenAPI 说明中的 匹配operationId
。如果所需的参数没有默认值,则应用清单中的命令
parameters.name
必须与 OpenAPI 说明文档中的 匹配parameters.name
。如果没有必需的参数,则应用清单中的命令
parameters.name
必须与 OpenAPI 说明中的 可选parameters.name
匹配。确保每个命令的参数与 OpenAPI 规范中为操作定义的参数名称完全匹配。
必须为每个命令定义 响应呈现模板 ,该命令用于转换来自 API 的响应。
完整说明不得超过 128 个字符。
{ "$schema": "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json", + "manifestVersion": "devPreview", "version": "1.0.0", "id": "04805b4b-xxxx-xxxx-xxxx-4dbc1cac8f89", "packageName": "com.microsoft.teams.extension", "developer": { "name": "Teams App, Inc.", "websiteUrl": "https://www.example.com", "privacyUrl": "https://www.example.com/termofuse", "termsOfUseUrl": "https://www.example.com/privacy" }, "icons": { "color": "color.png", "outline": "outline.png" }, "name": { "short": "AI tools", "full": "AI tools" }, "description": { "short": "AI tools", "full": "AI tools" }, "accentColor": "#FFFFFF", "composeExtensions": [ { + "composeExtensionType": "apiBased", + "authorization": { + "authType": "apiSecretServiceAuth ", + "apiSecretServiceAuthConfiguration": { + "apiSecretRegistrationId": "96270b0f-7298-40cc-b333-152f84321813" + } + }, + "apiSpecificationFile": "aitools-openapi.yml", "commands": [ { "id": "searchTools", "type": "query", "context": [ "compose", "commandBox" ], "title": "search for AI tools", "description": "search for AI tools", "parameters": [ { "name": "search", "title": "search query", "description": "e.g. search='tool to create music'" } ], + "apiResponseRenderingTemplateFile": "response-template.json" } ] } ], "validDomains": [] }
参数
名称 | 说明 |
---|---|
composeExtensions.composeExtensionType |
撰写扩展类型。 将值更新为 apiBased 。 |
composeExtensions.authorization |
基于 API 的消息扩展的授权相关信息 |
composeExtensions.authorization.authType |
可能授权类型的枚举。 支持的值为 none 、 apiSecretServiceAuth 和 microsoftEntra 。 |
composeExtensions.authorization.apiSecretServiceAuthConfiguration |
对象捕获执行服务身份验证所需的详细信息。仅当身份验证类型为 apiSecretServiceAuth 时适用。 |
composeExtensions.authorization.apiSecretServiceAuthConfiguration.apiSecretRegistrationId |
开发人员通过开发人员门户提交 API 密钥时返回的注册 ID。 |
composeExtensions.apiSpecificationFile |
引用应用包中的 OpenAPI 说明文件。 类型为 apiBased 时包括 。 |
composeExtensions.commands.id |
分配给搜索命令的唯一 ID。 用户请求包含此 ID。 ID 必须与 OpenAPI 说明中提供的 匹配 OperationId 。 |
composeExtensions.commands.context |
定义消息扩展入口点的数组。 默认值为 compose 和 commandBox 。 |
composeExtensions.commands.parameters |
定义命令的参数的静态列表。 名称必须映射到 parameters.name OpenAPI 说明中的 。 如果要引用请求正文架构中的属性,则该名称必须映射到 properties.name 或 查询参数。 |
composeExtensions.commands.apiResponseRenderingTemplateFile |
用于格式化从开发人员 API 到自适应卡片响应的 JSON 响应的模板。 [必需] |
有关详细信息,请参阅 composeExtensions。
3. 响应呈现模板
注意
Teams 支持最高版本 1.5 的自适应卡片,自适应卡片Designer支持最高版本 1.6。
- 在 属性中
$schema
定义架构引用 URL,以建立模板的结构。 - 支持的值
responseLayout
grid
和list
,确定响应的视觉呈现方式。 jsonPath
当自适应卡片的数据不是根对象时,建议对数组使用 。 例如,如果数据嵌套在 下productDetails
,则 JSON 路径为productDetails
。- 定义为
jsonPath
API 响应中相关数据或数组的路径。 如果路径指向数组,则数组中的每个条目都与自适应卡片模板绑定,并作为单独的结果返回。 [可选] - 获取 用于验证响应呈现模板的示例响应。 这可用作一个测试,以确保模板按预期工作。
- 使用 Fiddler 或 Postman 等工具 调用 API 并确保请求和响应有效。 此步骤对于排查和确认 API 正常运行至关重要。
- 可以使用自适应卡片Designer将 API 响应绑定到响应呈现模板并预览自适应卡片。 在 卡片有效负载编辑器 中插入模板,并在示例 数据编辑器中插入示例响应条目。
以下代码是响应呈现模板的示例:
响应呈现模板示例
{
"version": "1.0",
"jsonPath": "repairs",
"responseLayout": "grid",
"responseCardTemplate": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "Container",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Title: ${if(title, title, 'N/A')}",
"wrap": true
},
{
"type": "TextBlock",
"text": "Description: ${if(description, description, 'N/A')}",
"wrap": true
},
{
"type": "TextBlock",
"text": "Assigned To: ${if(assignedTo, assignedTo, 'N/A')}",
"wrap": true
},
{
"type": "Image",
"url": "${image}",
"size": "Medium",
"$when": "${image != null}"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"url": "${if(image, image, '')}",
"size": "Medium"
}
]
}
]
},
{
"type": "FactSet",
"facts": [
{
"title": "Repair ID:",
"value": "${if(id, id, 'N/A')}"
},
{
"title": "Date:",
"value": "${if(date, date, 'N/A')}"
}
]
}
]
}
]
},
"previewCardTemplate": {
"title": "Title: ${if(title, title, 'N/A')}",
"subtitle": "Description: ${if(description, description, 'N/A')}",
"text": "Assigned To: ${if(assignedTo, assignedTo, 'N/A')}",
"image": {
"url": "${image}",
"$when": "${image != null}"
}
}
}
预览卡
扩展的自适应卡片
参数
属性 | 类型 | 说明 | 必需 |
---|---|---|---|
version |
string |
当前响应呈现模板的架构版本。 | 是 |
jsonPath |
string |
responseCardTemplate 和 previewCardTemplate 应应用到的结果中相关节的路径。 如果未设置,则根对象被视为相关部分。 如果相关部分是数组,则每个条目将映射到 responseCardTemplate 和 previewCardTemplate。 | 否 |
responseLayout |
responseLayoutType |
指定消息扩展浮出控件中结果的布局。 支持的类型为 list 和 grid 。 |
是 |
responseCardTemplate |
adaptiveCardTemplate |
用于从结果条目创建自适应卡片的模板。 | 是 |
previewCardTemplate |
previewCardTemplate |
用于从结果条目创建预览卡的模板。 生成的预览卡显示在消息扩展浮出控件菜单中。 | 是 |
Json 路径
JSON 路径是可选的,但应用于数组,或者用作自适应卡数据的对象不是根对象。 JSON 路径应遵循 Newtonsoft 定义的格式。 如果 JSON 路径指向数组,则该数组中的每个条目都与自适应卡模板绑定,并返回为单独的结果。
例子假设你具有以下产品列表的 JSON,并且你希望为每个条目创建卡结果。
{
"version": "1.0",
"title": "All Products",
"warehouse": {
"products": [
...
]
}
}
可以看到,结果数组位于“products”下,嵌套在“warehouse”下,因此 JSON 路径为“warehouse.products”。
使用 https://adaptivecards.io/designer/ 通过将模板插入卡片有效负载编辑器来预览自适应卡,并从数组或对象获取示例响应条目,并将其插入右侧的“相同数据”编辑器中。 确保卡正确呈现,并且符合你的喜好。 请注意,Teams 支持最高版本 1.5 的卡片,而设计器支持 1.6。
架构映射
OpenAPI 说明文档中的属性映射到自适应卡片模板,如下所示:
string
、number
、integer
类型boolean
将转换为 TextBlock。例子
源架构:
string
、number
、integer
和boolean
name: type: string example: doggie
目标架构:
Textblock
{ "type": "TextBlock", "text": "name: ${if(name, name, 'N/A')}", "wrap": true }
array
:数组转换为自适应卡内的容器。例子
源架构:
array
type: array items: required: - name type: object properties: id: type: integer category: type: object properties: name: type: string
目标架构:
Container
{ "type": "Container", "$data": "${$root}", "items": [ { "type": "TextBlock", "text": "id: ${if(id, id, 'N/A')}", "wrap": true }, { "type": "TextBlock", "text": "category.name: ${if(category.name, category.name, 'N/A')}", "wrap": true } ] }
object
:对象转换为自适应卡片中的嵌套属性。例子
源架构:
object
components: schemas: Pet: category: type: object properties: id: type: integer name: type: string
目标架构:自适应卡片中的嵌套属性
{ "type": "TextBlock", "text": "category.id: ${if(category.id, category.id, 'N/A')}", "wrap": true }, { "type": "TextBlock", "text": "category.name: ${if(category.name, category.name, 'N/A')}", "wrap": true }
image
:如果属性是图像 URL,则它将转换为自适应卡片中的 Image 元素。例子
源架构:
image
image: type: string format: uri description: The URL of the image of the item to be repaired
目标架构:
"Image"
{ "type": "Image", "url": "${image}", "$when": "${image != null}" }
身份验证
可以在基于 API 的消息扩展中实现身份验证,以提供对应用程序的安全和无缝访问。 如果消息扩展需要身份验证,请在应用清单的 下composeExtensions
添加 authorization
属性,并通过在 下authorization
设置 authType
属性来定义应用程序的身份验证类型。 若要为消息扩展启用身份验证,请使用以下任一身份验证方法更新应用清单:
没有
如果消息扩展不需要用户进行任何身份验证即可访问 API,则可以在基于 API 的消息扩展中更新 none
为 的值 authorization
。
"authorization": {
"authType": "none"
}
},
机密服务身份验证
API 机密服务身份验证是应用使用 API 进行身份验证的安全方法。 可以通过 Teams 开发人员门户 注册 API 密钥 ,并生成 API 密钥注册 ID。 使用 具有 属性的 apiSecretServiceAuthConfiguration
对象apiSecretRegistrationId
更新应用清单。 此属性应包含通过门户提交 API 密钥时返回的引用 ID。
启动 API 请求时,系统会从安全存储位置检索 API 密钥,并使用持有者令牌方案将其包含在授权标头中。 API 终结点在收到请求后验证 API 密钥的有效性。 如果验证成功,终结点将处理请求并返回所需的响应,确保只有经过身份验证的请求才能访问 API 的资源。
注册 API 密钥
通过 API 密钥注册,可以保护身份验证背后的 API,并在消息扩展中使用。 可以注册 API 密钥,并指定可以访问 API 的域、租户和应用,并提供对 API 调用进行身份验证所需的机密。 然后,可以将 API 密钥 ID 粘贴到简化的消息扩展中,API 密钥 ID 为身份验证背后的 API 调用启用身份验证。
若要注册 API 密钥,请执行以下步骤:
转到 “工具 API>密钥注册”。
选择“ + 新建 API 密钥”。
在 “API 密钥注册 ”页的 “注册 API 密钥”下,更新以下内容:
说明:API 密钥的说明。
添加域:更新 API 终结点的基路径。 路径必须是安全的 HTTPS URL,包括完全限定的域名,并且可以选择性地包含特定路径。 例如,
https://api.yelp.com
。
在 “设置目标租户”下,选择以下任一项:
- 家庭租赁
- 任何租户
选项 何时使用 说明 家庭租户 在租户中开发应用并将应用测试为组织生成的自定义应用或自定义应用时。 API 密钥仅在注册 API 的租户中可用。 任何租户 完成应用测试并想要跨不同租户启用应用后。 在将应用包提交到合作伙伴中心之前,请确保将目标租户更新为 “任何租户 ”。 应用在 Teams 应用商店中可用后,可以在其他租户中使用 API 密钥。 在 “设置 Teams 应用”下,选择以下任一项:
- 任何 Teams 应用
- 现有 Teams 应用 ID
选项 何时使用 说明 任何 Teams 应用 在租户中开发应用并将应用测试为组织生成的自定义应用或自定义应用时。 API 密钥可用于任何 Teams 应用。 当为组织生成的自定义应用或自定义应用在应用上传后生成了 ID 时,此功能非常有用。 现有 Teams 应用 ID 在租户中作为为组织构建的自定义应用或自定义应用完成测试后。更新 API 密钥注册并选择“ 现有 Teams 应用 ”,并输入应用的清单 ID。 “ 现有 Teams 应用 ”选项将 API 机密注册绑定到特定的 Teams 应用。 选择“ + 添加机密”。 此时会显示 “添加 API 密钥 ”对话框。
输入机密的值,然后选择“ 保存”。
注意
- 每个 API 密钥注册最多可以保留两个机密。 如果一个密钥泄露,可以立即将其删除,并允许 Teams 切换到第二个密钥。
- 机密值必须至少包含 10 个字符,最多 128 个字符。
- 如果第一个键导致 401 错误,Teams 会自动尝试使用第二个密钥。 它有助于为用户提供不间断的服务,并消除创建新机密期间的任何潜在停机时间。
将生成 API 密钥注册 ID 。
复制并保存 API 密钥注册 ID,并将其更新为应用清单中 属性的值 apiSecretRegistrationId
。
更新应用清单
可以通过配置静态 API 密钥来授权传入服务的请求。 API 密钥将安全地存储并添加到 API 调用。 apiSecretServiceAuthConfiguration
通过 Teams 开发人员门户提交 API 密钥时,添加具有 apiSecretRegistrationId
属性的对象,该属性包含引用 ID。 有关详细信息,请参阅 composeExtensions.commands。
"composeExtensions": [
{
"composeExtensionType": "apiBased",
"authorization": {
"authType": "apiSecretServiceAuth",
"apiSecretServiceAuthConfiguration": {
"apiSecretRegistrationId": "9xxxxb0f-xxxx-40cc-xxxx-15xxxxxxxxx3"
}
},
Microsoft Entra
microsoftEntra
身份验证方法使用应用用户的 Teams 标识向他们提供对应用的访问权限。 登录到 Teams 的用户无需在 Teams 环境中再次登录到你的应用。 Teams 应用只需获得应用用户的同意,即可从Microsoft Entra ID检索其访问详细信息。 应用用户同意后,他们甚至可以从其他设备访问应用,而无需再次验证。
先决条件
在开始之前,请确保具有以下各项:
- 具有活动订阅的 Azure 帐户。
- 基本熟悉Microsoft Entra ID和 Teams 应用开发。
下图显示了当 Teams 应用用户尝试访问 API-bsed 消息扩展应用时 SSO 的工作原理:
- 用户从 Teams 中的消息扩展调用基于 API 的消息扩展应用,并请求一个需要身份验证的命令。
- 应用使用应用 ID 和所需范围 (access_as_user) 向 Teams 后端服务发送请求。
- Teams 后端服务会检查用户是否同意应用和范围。 否则,它会向用户显示一个同意屏幕,并请求权限。
- 如果用户同意,Teams 后端服务会为用户和应用生成访问令牌,并将其发送到请求的授权标头中的应用。
- 应用验证令牌。 用户可以从令牌中提取用户信息,例如名称、电子邮件和对象 ID。
- 应用可以使用令牌来调用自己的 API。
- 应用在 Teams 中将响应返回给用户。
若要为基于 API 的消息扩展启用 microsoftEntra
身份验证方法,请执行以下步骤:
在 Microsoft Entra ID 中注册新应用
在 Web 浏览器上打开 Azure 门户。
选择 应用注册 图标。
将显示 应用注册 页。
选择 + 新建注册 图标。
将显示注册应用程序页。
输入要显示给应用用户的应用名称。 如果需要,可以在稍后阶段更改名称。
选择可以访问应用的用户帐户的类型。 可以从组织目录中的单个或多租户选项中进行选择,或仅限制对个人 Microsoft 帐户的访问。
支持的帐户类型的选项
选项 选择此选项可... 此组织目录中的帐户仅 (Microsoft - 单租户) 生成仅供租户中(或来宾)用户使用的应用程序。
此应用通常称为为组织 (LOB 应用) 构建的自定义应用,是Microsoft 标识平台中的单租户应用程序。任何组织目录中的帐户 (任何Microsoft Entra ID租户 - 多租户) 允许任何Microsoft Entra租户中的用户使用应用程序。 例如,如果要生成 SaaS 应用程序,并且打算将其提供给多个组织,则此选项适用。
这种类型的应用在Microsoft 标识平台称为多租户应用程序。任何组织目录中的帐户 (任何Microsoft Entra ID租户 - 多租户) 和个人 Microsoft 帐户 (,例如 Skype、Xbox) 面向最广泛的客户集。
通过选择此选项,你将注册一个多租户应用程序,该应用程序可以支持具有个人 Microsoft 帐户的应用用户。仅限个人 Microsoft 帐户 仅为拥有个人 Microsoft 帐户的用户生成应用程序。 注意
无需输入 重定向 URI 即可为基于 API 的消息扩展应用启用 SSO。
选择“注册”。 浏览器上弹出一条消息,指出应用已创建。
将显示具有应用 ID 和其他配置的页面。
记下并保存 应用程序 (客户端中的应用 ID) ID ,以便稍后更新应用清单。
你的应用已在 Microsoft Entra ID 中注册。 现在,你已获得基于 API 的消息扩展应用的应用 ID。
配置访问令牌的范围
创建新的应用注册后,配置范围 (权限) 选项,以便将访问令牌发送到 Teams 客户端,以及授权受信任的客户端应用程序启用 SSO。
若要配置范围并授权受信任的客户端应用程序,需要:
- 添加应用程序 ID URI:为应用配置范围 (权限) 选项。 公开 Web API 并配置应用程序 ID URI。
- 配置 API 范围:定义 API 的范围,以及可以同意范围的用户。 你只能允许管理员提供对更高特权权限的同意。
- 配置授权客户端应用程序:为要预授权的应用程序创建授权客户端 ID。 它允许应用用户访问你配置的应用范围(权限),而无需任何进一步的同意。 仅预授权你信任的客户端应用程序,因为应用用户没有机会拒绝同意。
应用程序 ID URI。
从左窗格中选择“管理>公开 API”。
随即显示“公开 API”页。
选择“ 添加 ”,以以 的形式
api://{AppID}
生成应用程序 ID URI。将显示用于设置应用程序 ID URI 的部分。
按此处介绍的格式输入 应用程序 ID URI 。
- 应用程序 ID URI 预填充了应用 ID (GUID) 格式
api://{AppID}
。 - 应用程序 ID URI 格式必须为:
api://fully-qualified-domain-name.com/{AppID}
。 - 在
api://
和{AppID}
之间出入fully-qualified-domain-name.com
(即 GUID)。 例如,api://example.com/{AppID}。
重要
敏感信息:应用程序 ID URI 记录为身份验证过程的一部分,不得包含敏感信息。
具有多种功能的应用的应用程序 ID URI:如果要生成基于 API 的消息扩展,请输入应用程序 ID URI 作为
api://fully-qualified-domain-name.com/{YourClientId}
,其中 {YourClientId} 是Microsoft Entra应用 ID。域名的格式:对域名使用小写字母。 请勿使用大写。
例如,若要创建具有资源名称的应用服务或 Web 应用,请执行以下操作
demoapplication
:如果使用了基本资源名称 URL 将为... 支持格式... demoapplication https://demoapplication.example.net
所有平台 DemoApplication https://DemoApplication.example.net
仅限桌面、Web 和 iOS。 Android 不支持它。 使用小写选项 demoapplication 作为基资源名称。
- 应用程序 ID URI 预填充了应用 ID (GUID) 格式
选择“保存”。
浏览器上弹出一条消息,指出应用程序 ID URI 已更新。
应用程序 ID URI 显示在页面上。
记下并保存应用程序 ID URI,以便稍后更新应用清单。
配置 API 范围
注意
基于 API 的消息扩展仅支持 access_as_user 范围。
在此 API 部分定义的“作用域”中选择“+ 添加作用域”。
将显示 “添加范围 ”页。
输入配置范围的详细信息。
- 输入范围名称。 此字段是必需的。
- 选择可以对此范围表示同意的用户。 默认选项为 仅限管理员。
- 输入管理员同意显示名称。 此字段是必需的。
- 输入管理员同意的说明。 此字段是必需的。
- 输入 用户同意显示名称。
- 输入用户同意说明。
- 为状态选择“启用”选项。
- 选择“添加作用域”。
浏览器上弹出一条消息,指出已添加范围。
定义的新范围显示在页面上。
配置授权的客户端应用程序
将“公开 API ”页移动到“授权客户端应用程序”部分,然后选择“+ 添加客户端应用程序”。
将显示“添加客户端应用程序”页。
为要为应用的 Web 应用程序授权的应用程序输入相应的 Microsoft 365 客户端 ID。
注意
- 适用于 Teams 的移动、桌面和 Web 应用程序的 Microsoft 365 客户端 ID 是必须添加的实际 ID。
- 对于基于 Teams API 的消息扩展应用,需要 Web 或 SPA,因为 Teams 中不能有移动或桌面客户端应用程序。
选择以下客户端 ID 之一:
使用客户端 ID 用于授权... 1fec8e78-bce4-4aaf-ab1b-5451cc387264 Teams 移动或桌面应用程序 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 Teams Web 应用程序 选择在 授权范围内 为应用创建的应用程序 ID URI,将范围添加到公开的 Web API。
选择“添加应用程序”。
浏览器上弹出一条消息,指出已添加授权的客户端应用。
授权应用的客户端 ID 显示在页面上。
注意
可以授权多个客户端应用程序。 重复此过程的步骤以配置另一个已授权的客户端应用程序。
已成功配置应用范围、权限和客户端应用程序。 确保记下并保存应用程序 ID URI。 接下来,配置访问令牌版本。
更新应用清单
注意
webApplicationInfo
应用清单 1.5 或更高版本支持。
更新应用清单文件中的以下属性:
webApplicationInfo
:为应用启用 SSO,以帮助应用用户无缝访问基于 API 的消息扩展应用。 部分,其中包含有关应用的关键详细信息。 在 Microsoft Entra ID 中注册的应用程序 ID URI 配置了公开的 API 的范围。 在 中resource
配置应用的子域 URI,以确保 使用的getAuthToken()
身份验证请求来自应用清单中给定的域。 有关详细信息,请参阅 webApplicationInfo。microsoftEntraConfiguration
:为应用启用单一登录身份验证。 将supportsSingleSignOn
属性配置为true
以支持 SSO,并减少对多个身份验证的需求。
配置应用清单:
打开基于 API 的消息扩展应用项目。
打开应用清单文件夹。
注意
- 应用清单文件夹应位于项目的根目录中。 有关详细信息,请参阅 创建 Microsoft Teams 应用包。
- 有关如何创建manifest.json的详细信息,请参阅 应用清单架构。
打开
manifest.json
文件将以下代码片段添加到应用清单文件:
webApplicationInfo
"webApplicationInfo": { "id": "{Microsoft Entra AppId}", "resource": "api://subdomain.example.com/{Microsoft Entra AppId}" }
其中,
{Microsoft Entra AppId}
是在 Microsoft Entra ID 中注册应用时创建的应用 ID。 这是 GUID。subdomain.example.com
是在 Microsoft Entra ID 中创建范围时注册的应用程序 ID URI。
MicrosoftEntraConfiguration
"authorization": { "authType": "microsoftEntra", “microsoftEntraConfiguration”: { “supportsSingleSignOn”: true } },
更新以下属性中的子域 URL:
contentUrl
configurationUrl
保存应用清单文件。
有关详细信息,请参阅 composeExtensions.commands。
身份验证令牌
当消息扩展在身份验证期间调用 API 时,它会收到一个请求,其中包含用户的身份验证令牌 (AED 令牌) 。 然后,消息扩展会将令牌添加到传出 HTTP 请求的授权标头中。 标头格式为 Authorization: Bearer <token_value>
。 例如,当消息扩展对需要身份验证的服务进行 API 调用时。 扩展按如下所示构造 HTTP 请求:
GET /api/resource HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
在基于 API 的消息扩展获取具有令牌的请求标头后,请执行以下步骤:
身份验证:验证受众、范围、颁发者和签名声明的令牌,以检查令牌是否适用于你的应用。
下面是包含标头和响应的 JSON Web 令牌 (JWT) 的示例:
{ "typ": "JWT", "rh": "0.AhoAv4j5cvGGr0GRqy180BHbR6Rnn7s7iddIqxdA7UZsDxYaABY.", "alg": "RS256", "kid": "q-23falevZhhD3hm9CQbkP5MQyU" }.{ "aud": "00000002-0000-0000-c000-000000000000", "iss": "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0", "iat": 1712509315, "nbf": 1712509315, "exp": 1712513961, "aio": "Y2NgYEjJqF0stqv73u41a6ZmxPEvBgA=", "azp": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", "azpacr": "0", "name": "John Doe", "oid": "00000000-0000-0000-0000-000000000000", "preferred_username": "john.doe@contoso.com", "rh": "I", "scp": "access_as_user", "sub": "e4uM7JgAEm08GBuasSltQjvPuMX1fR5TqxopJpqZJB8", "tid": "12345678-aaaa-bbbb-cccc-9876543210ab", "uti": "h7DMQwSPAEeiEe62JJUGAA", "ver": "2.0" }
使用令牌:从令牌中提取用户信息,例如名称、电子邮件和对象 ID,并使用令牌调用消息扩展应用自己的 API。
注意
API 接收一个Microsoft Entra令牌,其范围设置为
access_as_user
Azure 门户 中注册。 但是,令牌无权调用任何其他下游 API,例如 Microsoft Graph。
疑难解答
如果在将应用上传到团队时收到 清单分析失败 错误消息,请使用 Teams 应用验证程序 验证应用包,包括应用清单和 OpenAPI 规范文件。 查看 应用清单 和 OpenAPI 说明文档 要求,以解决错误或警告,并尝试上传应用。
如果在 Teams 中运行应用时遇到任何问题,请使用以下故障排除步骤来识别并解决问题:
网络:选择开发人员工具中的“网络”选项卡以检查网络活动
打开 Teams Web 客户端。
使用 Microsoft 365 凭据登录。
转到聊天,并运行消息扩展应用。
在右上角,选择“设置和更多 (...) ”。转到“更多工具>开发人员工具。
选择“网络”。 选择 筛选器 选项,并在搜索字段中输入 invoke 。
从列表中选择错误。
在右窗格中,选择“ 响应 ”选项卡。
将显示表示来自服务或 API 的错误响应的 JSON 对象。 它包含具有
standardizedError
errorCode
、errorSubCode
和errorDescription
的对象,这些对象具有有关错误的更多详细信息。
常见 HTTP 错误响应:
- 如果请求参数缺失或格式不正确,则可能会出现 400 错误请求错误。
- “401 未授权”或“403 禁止访问”错误表示 API 密钥存在问题,例如缺少或未经授权。
- 500 内部服务器错误指示由于服务器端问题,服务不知道如何响应。
使用工具进行故障排除:如果网络跟踪中的信息不足,可以按照 OpenAPI 说明文档构造请求,并在必要时使用 Swagger 编辑器 或 Postman 等工具来测试请求,包括 API 密钥的授权标头。
如果无法解决这些错误,建议联系 Microsoft Teams 产品支持 部门以获取进一步的帮助。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈