如需在生产系统中使用 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 标头添加到网络钩子请求中。通常,您只需提供一个键为 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 状态代码:
400Bad Request401Unauthorized403Forbidden404Not found500Server fault503Service 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 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。