如需在生产系统中使用 fulfillment,您应实现并部署网络钩子服务。如需处理 fulfillment,您的网络钩子服务需要接受 JSON 请求并返回本指南中指定的 JSON 响应。fulfillment 概览文档中介绍了关于 fulfillment 和网络钩子的详细处理流程。
网络钩子服务要求
您的网络钩子服务必须满足以下要求:
- 它必须处理 HTTPS 请求。不支持 HTTP。如果您使用计算或无服务器计算解决方案在 Google Cloud Platform 上托管网络钩子服务,请参阅使用 HTTPS 服务的产品文档。对于其他托管项,请参阅获取您网域的 SSL 证书。
- 其请求的网址须可公开访问。
- 它必须使用 JSON
WebhookRequest
正文处理 POST 请求。 - 它必须使用 JSON
WebhookResponse
正文来响应WebhookRequest
请求。
身份验证
请务必保护您的网络钩子服务,确保只有您或您的 Dialogflow 代理才有权发出请求。Dialogflow 支持以下身份验证机制:
术语 | 定义 |
---|---|
登录用户名和密码 | 对于 webhook 设置,您可以指定可选的登录用户名和密码值。如果已提供,Dialogflow 会向网络钩子请求添加授权 HTTP 标头。此标头的格式为:"authorization: Basic <base 64 encoding of the string username:password>" 。 |
身份验证标头 | 对于 webhook 设置,您可以指定可选的 HTTP 标头键值对。如果已提供,Dialogflow 会将这些 HTTP 标头添加到 webhook 请求中。通常,提供一个键值为 authorization 的对即可。 |
Cloud Functions 内置身份验证 | 使用 Cloud Functions 时,您可以使用内置身份验证。如需使用此类身份验证,请勿提供登录用户名、登录密码或授权标头。如果您提供其中任何一个字段,系统会使用这些字段进行身份验证,而不是使用内置身份验证。 |
服务身份令牌 | 您可以使用服务身份令牌进行身份验证。如果您未提供登录用户名、登录密码或键值为 authorization 的标头,Dialogflow 会自动假定应使用服务身份令牌,并向 webhook 请求添加授权 HTTP 标头。此标头的格式为:"authorization: Bearer <identity token>" 。 |
双向 TLS 身份验证 | 请参阅双向 TLS 身份验证文档。 |
网络钩子请求
当为 fulfillment 配置的意图匹配时,Dialogflow 会向您的网络钩子服务发送 HTTPS POST 网络钩子请求。此请求的正文是一个 JSON 对象,其中包含有关匹配意图的信息。
除了最终用户查询之外,许多集成还会发送一些有关最终用户的信息。例如,用于唯一标识用户的 ID。您可以通过网络钩子请求中的 originalDetectIntentRequest
字段访问此信息,此信息包含从集成平台发送的信息。
如需了解详情,请参阅 WebhookRequest
参考文档。
以下是请求示例:
{ "responseId": "response-id", "session": "projects/project-id/agent/sessions/session-id", "queryResult": { "queryText": "End-user expression", "parameters": { "param-name": "param-value" }, "allRequiredParamsPresent": true, "fulfillmentText": "Response configured for matched intent", "fulfillmentMessages": [ { "text": { "text": [ "Response configured for matched intent" ] } } ], "outputContexts": [ { "name": "projects/project-id/agent/sessions/session-id/contexts/context-name", "lifespanCount": 5, "parameters": { "param-name": "param-value" } } ], "intent": { "name": "projects/project-id/agent/intents/intent-id", "displayName": "matched-intent-name" }, "intentDetectionConfidence": 1, "diagnosticInfo": {}, "languageCode": "en" }, "originalDetectIntentRequest": {} }
网络钩子响应
一旦网络钩子收到网络钩子请求,其需要发送一个网络钩子响应。此响应的正文为 JSON 对象,其包含以下信息:
您的响应会受到以下限制:
- 对于 Google 助理应用,响应必须在 10 秒内发生;对于其他所有应用,响应必须在 5 秒内发生,否则请求会超时。
- 响应大小不得超过 64 KiB。
如需了解详情,请参阅 WebhookResponse
参考文档。
文本响应
文本响应示例:
{ "fulfillmentMessages": [ { "text": { "text": [ "Text response from webhook" ] } } ] }
卡片响应
卡片响应示例:
{ "fulfillmentMessages": [ { "card": { "title": "card title", "subtitle": "card text", "imageUri": "https://example.com/images/example.png", "buttons": [ { "text": "button text", "postback": "https://example.com/path/for/end-user/to/follow" } ] } } ] }
Google 助理响应
Google 助理响应示例:
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "this is a Google Assistant response" } } ] } } } }
Context
设置输出上下文的示例:
{ "fulfillmentMessages": [ { "text": { "text": [ "Text response from webhook" ] } } ], "outputContexts": [ { "name": "projects/project-id/agent/sessions/session-id/contexts/context-name", "lifespanCount": 5, "parameters": { "param-name": "param-value" } } ] }
Event
调用自定义事件的示例:
{ "followupEventInput": { "name": "event-name", "languageCode": "en-US", "parameters": { "param-name": "param-value" } } }
会话实体
设置会话实体的示例:
{ "fulfillmentMessages": [ { "text": { "text": [ "Choose apple or orange" ] } } ], "sessionEntityTypes":[ { "name":"projects/project-id/agent/sessions/session-id/entityTypes/fruit", "entities":[ { "value":"APPLE_KEY", "synonyms":[ "apple", "green apple", "crabapple" ] }, { "value":"ORANGE_KEY", "synonyms":[ "orange" ] } ], "entityOverrideMode":"ENTITY_OVERRIDE_MODE_OVERRIDE" } ] }
自定义负载
提供自定义载荷的示例:
{ "fulfillmentMessages": [ { "payload": { "facebook": { // for Facebook Messenger integration "attachment": { "type": "", "payload": {} } }, "slack": { // for Slack integration "text": "", "attachments": [] }, "richContent": [ // for Dialogflow Messenger integration [ { "type": "image", "rawUrl": "https://example.com/images/logo.png", "accessibilityText": "Example logo" } ] ], // custom integration payload here } } ] }
启用和管理 fulfillment
如需通过控制台为您的代理启用和管理 fulfillment,请执行以下操作:
- 前往 Dialogflow ES 控制台。
- 选择一个代理。
- 选择左侧边栏菜单中的 Fulfillment。
- 将网路钩子字段切换为已启用。
- 在表单中提供网络钩子服务的详细信息。如果您的网络钩子不需要身份验证,请将身份验证字段留空。
- 点击页面底部的保存。
要使用 API 为代理启用和管理 fulfillment,请参阅代理参考。getFulfillment
和 updateFulfillment
方法可用于管理 fulfillment 设置。
如需通过控制台为意图启用 fulfillment,请执行以下操作:
- 在左侧边栏菜单中选择意图 (Intents)。
- 选择一个意图。
- 向下滚动到 Fulfillment 部分。
- 开启为此意图启用 webhook 调用。
- 点击保存。
如需使用 API 为意图启用 fulfillment,请参阅意图参考。将 webhookState
字段设置为 WEBHOOK_STATE_ENABLED
。
网络钩子错误
如果您的网络钩子服务发生错误,则会返回以下某个 HTTP 状态代码:
400
Bad Request401
Unauthorized403
Forbidden404
Not found500
Server fault503
Service Unavailable
在以下任何一种错误情况下,Dialogflow 都会使用为当前匹配的意图配置的内置响应来响应最终用户:
- 响应已超时。
- 收到错误状态代码。
- 无效响应。
- 网络钩子服务不可用。
此外,如果意图匹配由检测意图 API 调用触发,则检测意图响应中的 status
字段包含网络钩子错误信息。例如:
"status": {
"code": 206,
"message": "Webhook call failed. <details of the error...>"
}
自动重试
Dialogflow ES 包含内部机制,可在发生某些 webhook 错误时自动重试,以提高稳健性。系统只会重试非终端错误(例如超时或连接错误)。
为了降低重复调用的可能性,请执行以下操作:
- 设置更长的 webhook 超时阈值。
- 支持 webhook 逻辑中的幂等性或去重。
使用 Cloud Functions
您可以通过多种方式使用 Cloud Functions 进行履行。Dialogflow 内嵌编辑器与 Cloud Functions 集成。使用内嵌编辑器创建和修改网络钩子代码时,Dialogflow 会与 Cloud Functions 函数建立安全连接。
您还可以选择使用内嵌编辑器创建的 Cloud Functions 函数(可能是因为您想要使用 Node.js 以外的语言)。如果 Cloud Functions 函数与您的代理位于同一项目中,则代理可以调用您的网络钩子,而无需任何特殊配置。
但是,在下面两种情况下,您必须手动设置此集成:
- 您的代理项目必须存在具有以下地址的 Dialogflow Service Agent 服务账号:
当您为项目创建第一个代理时,系统通常会自动创建这个特殊的服务账号及关联的密钥。如果您的代理是 2021 年 5 月 10 日之前创建的,则您可能需要使用以下代码触发创建此特殊服务账号:service-agent-project-number@gcp-sa-dialogflow.iam.gserviceaccount.com
- 为项目创建新的代理。
- 执行以下命令:
gcloud beta services identity create --service=dialogflow.googleapis.com --project=agent-project-id
- 如果网络钩子函数位于与代理不同的项目中,则必须提供 Cloud Functions Invoker IAM 角色 Dialogflow 服务代理服务账号。
服务身份令牌
Dialogflow 调用网络钩子时,会通过请求提供 Google 身份令牌。任何网络钩子都可以选择性地使用 Google 客户端库或 github.com/googleapis/google-auth-library-nodejs 等开源库验证令牌。例如,您可以按以下方式验证 ID 令牌的 email
:
service-agent-project-number@gcp-sa-dialogflow.iam.gserviceaccount.com
示例
以下示例展示了如何接收 WebhookRequest
以及发送 WebhookResponse
。这些示例引用了在快速入门中创建的意图。
Go
如需向 Dialogflow 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
import ( "encoding/json" "fmt" "log" "net/http" ) type intent struct { DisplayName string `json:"displayName"` } type queryResult struct { Intent intent `json:"intent"` } type text struct { Text []string `json:"text"` } type message struct { Text text `json:"text"` } // webhookRequest is used to unmarshal a WebhookRequest JSON object. Note that // not all members need to be defined--just those that you need to process. // As an alternative, you could use the types provided by // the Dialogflow protocol buffers: // https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookRequest type webhookRequest struct { Session string `json:"session"` ResponseID string `json:"responseId"` QueryResult queryResult `json:"queryResult"` } // webhookResponse is used to marshal a WebhookResponse JSON object. Note that // not all members need to be defined--just those that you need to process. // As an alternative, you could use the types provided by // the Dialogflow protocol buffers: // https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookResponse type webhookResponse struct { FulfillmentMessages []message `json:"fulfillmentMessages"` } // welcome creates a response for the welcome intent. func welcome(request webhookRequest) (webhookResponse, error) { response := webhookResponse{ FulfillmentMessages: []message{ { Text: text{ Text: []string{"Welcome from Dialogflow Go Webhook"}, }, }, }, } return response, nil } // getAgentName creates a response for the get-agent-name intent. func getAgentName(request webhookRequest) (webhookResponse, error) { response := webhookResponse{ FulfillmentMessages: []message{ { Text: text{ Text: []string{"My name is Dialogflow Go Webhook"}, }, }, }, } return response, nil } // handleError handles internal errors. func handleError(w http.ResponseWriter, err error) { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "ERROR: %v", err) } // HandleWebhookRequest handles WebhookRequest and sends the WebhookResponse. func HandleWebhookRequest(w http.ResponseWriter, r *http.Request) { var request webhookRequest var response webhookResponse var err error // Read input JSON if err = json.NewDecoder(r.Body).Decode(&request); err != nil { handleError(w, err) return } log.Printf("Request: %+v", request) // Call intent handler switch intent := request.QueryResult.Intent.DisplayName; intent { case "Default Welcome Intent": response, err = welcome(request) case "get-agent-name": response, err = getAgentName(request) default: err = fmt.Errorf("Unknown intent: %s", intent) } if err != nil { handleError(w, err) return } log.Printf("Response: %+v", response) // Send response if err = json.NewEncoder(w).Encode(&response); err != nil { handleError(w, err) return } }
Java
如需向 Dialogflow 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Node.js
如需向 Dialogflow 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Python
如需向 Dialogflow 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。