本指南将逐步介绍如何开发 Actions 项目 使用 Orders API 进行预订。
交易流程
当 Actions 项目处理预留时,它会 采用以下流程:
- 验证交易要求(可选)- 使用交易 需求小助手,确保能 用户能否进行交易。
- 建立订单 - 引导用户完成 "购物车组装"在这里构建预留的详细信息
- 提议订单 -“购物车”页面则提议预订“订单”更改为 以便确认其正确无误。如果预订得到确认 收到包含预留详情的响应
- 敲定订单并发送收据 - 订单已确认后,更新 并向用户发送收据。
- 发送订单更新 - 在预订的整个有效期内, 将 PATCH 请求发送到 Orders API。
限制和查看指南
请注意,使用 和 Orders API。我们最多可能需要 6 周时间来审核 Action 因此在规划发布时间表时,请将这部分时间考虑在内。 为了简化审核流程,请确保您遵守 交易政策和准则 然后再提交 Action 以供审核。
您只能在以下国家/地区部署使用 Orders API 的 Action:
澳大利亚 巴西 加拿大 印度尼西亚 |
日本 墨西哥 卡塔尔 俄罗斯 |
新加坡 瑞士 泰国 土耳其 英国 美国 |
构建您的项目
有关交易对话的详尽示例,请参阅我们的事务处理 Node.js 中的示例。
设置
创建 Action 时,你必须指定要执行交易 在 Actions 控制台中操作。
如需设置项目和执行方式,请执行以下操作:
- 创建新项目或导入现有项目。
- 导航到部署 >目录信息。
在其他信息 >交易 >选中 使用 Transaction API 执行实体商品的交易?”。
验证交易要求(可选)
用户表示想要设置预订后,您应该立即选中 他们能够请求预订例如,在被调用时,您的 Action 可能会 询问:“要预订座位吗?”如果用户说“是”,您应该 确保他们可以继续操作,并给他们机会来修正所有设置 阻止客户继续处理交易为此,您应该 过渡到执行事务要求检查的场景。
创建交易要求检查场景
- 在 Scenes 标签页中,添加一个名为
TransactionRequirementsCheck
。 - 在槽填充下,点击 + 以添加新槽。
- 在选择类型下,选择
actions.type.TransactionRequirementsCheckResult
作为广告位类型 - 在槽名称字段中,将槽命名为
TransactionRequirementsCheck
。 - 选中自定义槽值回写复选框(默认处于启用状态)。
点击保存。
事务要求检查会产生以下结果之一:
- 如果满足这些要求,系统就会成功设置会话参数 您可以继续构建用户订单。
- 如果不能满足一项或多项要求,则会话参数为
带有失败条件的集合。在这种情况下,您应围绕
或结束对话。
- 如果用户可以更正导致失败状态的任何错误, 系统会提示他们在设备上解决这些问题。如果 对话是在纯语音平台上进行的, 向用户的电话发起调用
处理交易要求检查结果
- 从 Scenes 标签页中,选择您新创建的场景
TransactionRequirementsCheck
个场景。 - 在条件下,点击 + 以添加新条件。
在文本字段中,输入以下条件语法,以检查 成功条件:
scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
将光标悬停在您刚刚添加的条件上,然后点击向上箭头 并将其放置在
if scene.slots.status == "FINAL"
之前。启用 Send prompts,并提供简单的提示让用户知道 他们已准备好进行交易:
candidates:
- first_simple:
variants:
- speech: >-
Looks like you're good to go!.在过渡下选择其他场景,以便用户继续操作 对话并继续进行交易。
选择条件
else if scene.slots.status == "FINAL"
。启用 Send prompts,并提供简单的提示让用户知道 他们无法进行交易:
candidates:
- first_simple:
variants:
- speech: Transaction requirements check failed.在转换下,选择结束对话以结束对话 如果用户无法进行交易。
创建订单
获得所需的用户信息后,即可构建“购物车” 组装"引导用户进行预订。每个 Action 的购物车装配流程将视情况略有不同 服务。
在基本的购物车组装体验中,用户从列表中选择要添加的选项 但您可以设计对话来简化 用户体验。例如,打造购物车组装体验, 通过简单的“是”或“非”问题来安排每月预订。 您还可以向用户显示“推荐”的轮播界面或列表卡片 预留。
我们建议使用富响应来 不仅要直观地呈现用户的选项 而且要妥善设计对话 用户只需使用语音即可构建购物车。一些最佳实践和 购物车组装体验示例,请参阅设计准则。
创建一个订单
在整个对话过程中,收集用户的预订详情,然后
构建一个 Order
对象。
您的 Order
必须至少包含以下内容:
buyerInfo
- 购买用户的相关信息。transactionMerchant
- 协助完成订单的商家的相关信息。contents
- 列为lineItems
的订单的实际内容。
请参阅 Order
构建您的购物车所需的响应文档。请注意,您可能需要将
具体取决于预留。
以下示例代码展示了一个完整的预订订单,其中包括可选字段:
const order = {
createTime: '2019-09-24T18:00:00.877Z',
lastUpdateTime: '2019-09-24T18:00:00.877Z',
merchantOrderId: orderId, // A unique ID String for the order
userVisibleOrderId: orderId,
transactionMerchant: {
id: 'http://www.example.com',
name: 'Example Merchant',
},
contents: {
lineItems: [
{
id: 'LINE_ITEM_ID',
name: 'Dinner reservation',
description: 'A world of flavors all in one destination.',
reservation: {
status: 'PENDING',
userVisibleStatusLabel: 'Reservation is pending.',
type: 'RESTAURANT',
reservationTime: {
timeIso8601: '2020-01-16T01:30:15.01Z',
},
userAcceptableTimeRange: {
timeIso8601: '2020-01-15/2020-01-17',
},
partySize: 6,
staffFacilitators: [
{
name: 'John Smith',
},
],
location: {
zipCode: '94086',
city: 'Sunnyvale',
postalAddress: {
regionCode: 'US',
postalCode: '94086',
administrativeArea: 'CA',
locality: 'Sunnyvale',
addressLines: [
'222, Some other Street',
],
},
},
},
},
],
},
buyerInfo: {
email: 'janedoe@gmail.com',
firstName: 'Jane',
lastName: 'Doe',
displayName: 'Jane Doe',
},
followUpActions: [
{
type: 'VIEW_DETAILS',
title: 'View details',
openUrlAction: {
url: 'http://example.com',
},
},
{
type: 'CALL',
title: 'Call us',
openUrlAction: {
url: 'tel:+16501112222',
},
},
{
type: 'EMAIL',
title: 'Email us',
openUrlAction: {
url: 'mailto:person@example.com',
},
},
],
termsOfServiceUrl: 'http://www.example.com'
};
创建顺序和展示选项
const orderOptions = {
'requestDeliveryAddress': false,
};
const presentationOptions = {
'actionDisplayName': 'RESERVE'
};
在会话参数中保存订单数据
在 fulfillment 中,将订单数据保存到会话参数中。顺序 对象将用于同一会话的各个场景。
conv.session.params.order = {
'@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
order: order,
orderOptions: orderOptions,
presentationOptions: presentationOptions
};
提议订单
创建预订订单后,您必须将其呈现给用户 确认或拒绝为此,您应该过渡到执行事务的场景 决策。
创建交易决策场景
- 在 Scenes 标签页中,添加一个名为
TransactionDecision
的新场景。 - 在槽填充下,点击 + 以添加新槽。
- 在选择类型下,选择
actions.type.TransactionDecisionValue
作为 广告位类型。 - 在槽名称字段中,将槽命名为
TransactionDecision
。 - 选中自定义槽值回写复选框(默认处于启用状态)。
- 在配置槽下,从下拉菜单中选择使用会话参数。
- 在配置槽下,输入用于配置槽的会话参数的名称
将订单存储到文本字段中(即
$session.params.order
)。 点击保存。
为了尝试填充 TransactionDecisionValue
槽,Google 助理启动
一种内置体验,您传递的 Order
会直接渲染到
“购物车预览卡片”用户可以说“安排预订”、拒绝交易
或请求更改预留详情。
此时,用户也可以请求更改订单。在这种情况下, 应确保您的履单可以处理 完成购物车组装体验
处理交易决策结果
当 TransactionDecisionValue
槽被填充时,系统会针对
交易决策将存储在一个会话参数中。该值包含
以下:
ORDER_ACCEPTED
、ORDER_REJECTED
、CART_CHANGE_REQUESTED
USER_CANNOT_TRANSACT
。
如需处理事务决策结果,请执行以下操作:
- 从 Scenes 标签页中,选择您新创建的
TransactionDecision
场景。 - 在条件下,点击 + 以添加新条件。
在文本字段中,输入以下条件语法,以检查 成功条件:
scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
将光标悬停在您刚刚添加的条件上,然后点击向上箭头 并将其放置在
if scene.slots.status == "FINAL"
之前。启用 Send prompts,并提供简单的提示让用户知道 预订完成时:
candidates:
- first_simple:
variants:
- speech: >-
Transaction completed! Your reservation
$session.params.TransactionDecision.order.merchantOrderId is all
set!在转换下,选择结束对话以结束对话。
在条件下,点击 + 以添加新条件。
在文本字段中,输入以下条件语法,以检查 失败的情况:
scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
将光标悬停在您刚刚添加的条件上,然后点击向上箭头 并将其放置在
if scene.slots.status == "FINAL"
之前。启用 Send prompts,并提供一条简单提示让用户知道 订单已被拒绝:
candidates:
- first_simple:
variants:
- speech: Looks like you don't want to set up a reservation. Goodbye.在转换下,选择结束对话以结束对话。
选择条件
else if scene.slots.status == "FINAL"
。启用 Send prompts,并提供简单的提示让用户知道 他们无法进行交易:
candidates:
- first_simple:
variants:
- speech: >-
Transaction failed with status
$session.params.TransactionDecision.transactionDecision在转换下,选择结束对话以结束对话 如果用户无法进行交易。
完成预订并发送收据
当 TransactionDecisionValue
槽返回 ORDER_ACCEPTED
的结果时,
您必须立即执行安排
(例如将其保留在您自己的数据库中)。
发送简单的回复,让对话继续下去。用户会收到 “收起的收据卡片”连同您的回复一起显示
要发送初始订单更新,请执行以下操作:
- 从 Scenes 标签页中,选择您的
TransactionDecision
场景。 在条件下,选择用于检查成功结果的条件。
ORDER_ACCEPTED
:scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
对于此条件,请启用 Call your webhook, 并提供 intent 处理程序名称,例如
update_order
。在网络钩子代码中,添加一个用于发送初始订单更新的 intent 处理程序:
app.handle('update_order', conv => {
const currentTime = new Date().toISOString();
let order = conv.session.params.TransactionDecision.order;
conv.add(new OrderUpdate({
'updateMask': {
'paths': [
'reservation.status',
'reservation.user_visible_status_label',
'reservation.confirmation_code'
]
},
'order': {
'merchantOrderId': order.merchantOrderId,
'lastUpdateTime': currentTime,
'reservation': {
'status': 'CONFIRMED',
'userVisibleStatusLabel': 'Reservation confirmed',
'confirmationCode': '123ABCDEFGXYZ',
},
},
'reason': 'Reason string'
}));
});
发送订单更新
预留状态在其整个生命周期内不断变化。向用户发送 通过发送到 Orders API 的 HTTP PATCH 请求更新预留订单,包括 订单状态和详情
设置向 Orders API 发出的异步请求
对 Orders API 的订单更新请求已获得访问权限授权
令牌。如需 PATCH 对 Orders API 的订单更新,请下载 JSON
与您的 Actions 控制台项目关联的服务账号密钥,然后交换
不记名令牌的服务账号密钥,该令牌可以传递到
Authorization
标头。
如需检索您的服务账号密钥,请执行以下步骤:
- 在 Google Cloud 控制台中,执行以下操作: 转到菜单 ☰ >API 和服务 >凭据 >创建凭据 >服务账号密钥。
- 在服务账号下,选择新的服务账号。
- 将服务账号设置为
service-account
。 - 将角色设置为项目 >所有者。
- 将密钥类型设置为 JSON。
- 选择创建。
- 系统会将一个专用 JSON 服务账号密钥下载到您的本地机器。
在订单更新代码中,使用服务密钥换取不记名令牌 使用 Google API 客户端库 "https://www.googleapis.com/auth/actions.order.developer" 作用域。您可以 有关 API 客户端库的安装步骤和示例 GitHub 页面。
在我们的 Node.js 示例中引用 order-update.js
获取密钥交换示例。
发送订单更新
在用您的服务账号密钥交换 OAuth 不记名令牌之后, 订单更新,作为对 Orders API 的授权 PATCH 请求。
Orders API 网址:
PATCH https://actions.googleapis.com/v3/orders/${orderId}
在请求中提供以下标头:
- 将
"Authorization: Bearer token"
替换为 OAuth 不记名令牌 您的服务账号密钥。 "Content-Type: application/json"
。
PATCH 请求应采用以下格式的 JSON 正文:
{ "orderUpdate": OrderUpdate }
OrderUpdate
对象包含以下顶级字段:
updateMask
- 要更新的订单的字段。要更新 预订状态 将值设置为reservation.status, reservation.userVisibleStatusLabel
。order
- 更新的内容。如果您要更新 预留的内容,将该值设置为更新后的Order
对象。 如果您只想更新预留的状态(例如,"PENDING"
到"FULFILLED"
),该对象包含 以下字段:merchantOrderId
- 您在Order
对象中设置的 ID。lastUpdateTime
- 此更新的时间戳。purchase
- 包含以下内容的对象: <ph type="x-smartling-placeholder">- </ph>
status
- 订单的状态,显示为ReservationStatus
。 例如“CONFIRMED
”或“CANCELLED
”。userVisibleStatusLabel
- 面向用户的标签,用于提供 订单状态,例如“您的预订已确认”。
userNotification
(选填)-userNotification
对象。注意事项 添加此对象并不能保证 用户的设备
以下示例代码显示了一个示例 OrderUpdate
,它会更新
FULFILLED
:
// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request-promise' module for sending an HTTP POST request.
const request = require('request-promise');
// Import the OrderUpdate class from the client library.
const {OrderUpdate} = require('@assistant/conversation');
// Import the service account key used to authorize the request.
// Replacing the string path with a path to your service account key.
// i.e. const serviceAccountKey = require('./service-account.json')
// Create a new JWT client for the Actions API using credentials
// from the service account key.
let jwtClient = new google.auth.JWT(
serviceAccountKey.client_email,
null,
serviceAccountKey.private_key,
['https://www.googleapis.com/auth/actions.order.developer'],
null,
);
// Authorize the client
let tokens = await jwtClient.authorize();
// Declare the ID of the order to update.
const orderId = '<UNIQUE_MERCHANT_ORDER_ID>';
// Declare order update
const orderUpdate = new OrderUpdate({
updateMask: {
paths: [
'contents.lineItems.reservation.status',
'contents.lineItems.reservation.userVisibleStatusLabel'
]
},
order: {
merchantOrderId: orderId, // Specify the ID of the order to update
lastUpdateTime: new Date().toISOString(),
contents: {
lineItems: [
{
reservation: {
status: 'FULFILLED',
userVisibleStatusLabel: 'Reservation fulfilled',
},
}
]
},
},
reason: 'Reservation status was updated to fulfilled.',
});
// Set up the PATCH request header and body,
// including the authorized token and order update.
let options = {
method: 'PATCH',
uri: `https://actions.googleapis.com/v3/orders/${orderId}`,
auth: {
bearer: tokens.access_token,
},
body: {
header: {
isInSandbox: true,
},
orderUpdate,
},
json: true,
};
// Send the PATCH request to the Orders API.
try {
await request(options);
} catch (e) {
console.log(`Error: ${e}`);
}
设置预留状态
订单更新的 ReservationStatus
必须说明订单的当前状态。在您的更新的order.ReservationStatus
中
字段中,请使用以下某个值:
PENDING
- 预留“已创建”被您的 Action 触发,但需要 进行额外的处理CONFIRMED
- 此预订已在时间安排后端中确认。CANCELLED
- 用户取消了预订。FULFILLED
- 服务完成用户的预订。CHANGE_REQUESTED
- 用户请求更改预订,则更改 处理中。REJECTED
- 如果无法处理或其他情况 确认预留。
发送与您商家相关的每个状态的订单更新
预留。例如,如果您的预订需要手动处理
在收到预订后确认预订,发送 PENDING
订单更新,直到
系统会完成额外的处理并非每个预留都需要每个状态值。
测试您的项目
测试项目时,你可以在 Actions 控制台中启用沙盒模式 在不向付款方式收取任何费用的情况下测试您的 Action。 如需启用沙盒模式,请按以下步骤操作:
- 在 Actions 控制台中,点击导航栏中的 Test。
- 点击设置。
- 启用 Development Sandbox 选项。
对于实际交易,您还可以将字段 isInSandbox
设置为 true
(位于
您的样本。此操作等同于在
Actions 控制台。如需查看使用 isInSandbox
的代码段,请参阅
发送订单更新部分。
问题排查
如果您在测试期间遇到任何问题,请参阅我们的问题排查步骤 。