如何使用用户选择的内容构建建议订单?
How to build proposed order with what the user has selected?
我正在构建一个 AOG(对 google 的操作)项目,它将执行基本的交易功能。由于我对 AOG 还是有点陌生,所以我完全不知道如何获取用户选择的内容(无论是旋转木马、基本卡片等)并将他们选择的参数 value/key 传递给在他们完成交易之前建议的订单或订单预览。
这基本上是我尝试过的(这不是实际的代码,因为它相当长,但它仍然理解了这个想法)
app.intent('delivery_address_complete', (conv) => {
const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE');
if (arg.userDecision ==='ACCEPTED') {
conv.ask('Ok, what would you like to order?');
conv.ask(new Suggestions(intentSuggestions));
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
SELECTION_KEY_COFFEE: {
synonyms: [
'Coffee'
],
title: 'Coffee',
description: 'Sweet cream and sugar coffee.',
image: new Image({
url: IMG_URL_COFFEE,
alt: 'Image alternate text',
}),
},
}));
}
});
const yesOrno = [
'Yes',
'No'
];
app.intent('actions.intent.OPTION', (conv ) => {
conv.ask('Okay, are you ready to proceed?');
conv.ask(new Suggestions(yesOrno));
});
app.intent('transaction_decision_action', (conv) => {
const order = {
id: UNIQUE_ORDER_ID,
cart: {
merchant: {
id: 'coffee',
name: 'Coffee Store',
},
lineItems: [
{
name: 'My Memoirs',
id: 'coffee_1',
price: {
amount: {
currencyCode: 'USD',
nanos: 990000000,
units: 3,
},
type: 'ACTUAL',
},
quantity: 1,
subLines: [
{
note: 'coffee',
},
],
type: 'REGULAR',
},
otherItems: [
{
name: 'Subtotal',
id: 'subtotal',
price: {
amount: {
currencyCode: 'USD',
nanos: 220000000,
units: 32,
},
type: 'ESTIMATE',
},
type: 'SUBTOTAL',
},
{
name: 'Tax',
id: 'tax',
price: {
amount: {
currencyCode: 'USD',
nanos: 780000000,
units: 2,
},
type: 'ESTIMATE',
},
type: 'TAX',
},
],
totalPrice: {
amount: {
currencyCode: 'USD',
nanos: 0,
units: 35,
},
type: 'ESTIMATE',
},
};
请注意:这主要是伪代码,因此如果出现收费过高或价格不合理等问题,这不是我要解决的问题。
我如何获取用户通过任何方法选择的内容,并将其显示在订单预览或建议订单中?我不需要任何有关制作旋转木马或基本卡片等的帮助。只是如何将这个选中的信息获取到订单预览中。
更具体地说:
- 我可以创建一个所需的
order
对象,并且我知道如何将它作为 ProposedOrder
对象的一部分发送给 Google(然后发送给用户)成为 TransactionDecision
对象的一部分。 (上面代码中的 "transaction_decision_action" Intent 处理程序。)
- 我不明白的是如何根据用户所说的内容或通过选择轮播或我向他们展示的列表项来构建
order
。 (例如,我在上面的 "actions.intent.OPTION" Intent 处理程序中做什么?)
编辑: 这也可能会消除任何混淆。这是我正在尝试做的事情的视频表示(在下面的评论中提到):
- youtube.com/watch?v=LlgMcJBnNN8 从 1:02 到 1:29 我知道该怎么做,我很困惑(在视频示例中)他们是如何获得 'turkey sandwich'并且 'Green smoothie' 添加到 1:35 处的订单预览来自轮播选择
您要做的就是 Google 所指的 building the order。正如它指出的那样 link
Once you have the user information you need, you'll build a "cart
assembly" experience that guides the user to build an order. Every
Action will likely have a slightly different cart assembly flow as
appropriate for your product or service.
You could build a cart assembly experience that enables the user to
re-order their most recent purchase via a simple yes or no question.
You could also present the user a carousel or list card of the top
"featured" or "recommended" items. We recommend using rich responses
to present the user's options visually, but also design the
conversation such that the user can build their cart using only their
voice.
For more information on how to build a high-quality cart assembly
experience, see the Transactions Design Guidelines.
所以没有一种方法可以完成您的要求。但是,有一些提示可以帮助您构建 proposed order.
管理订单
您需要做的最重要的事情是在整个过程中跟踪用户订购的所有东西。您可以通过多种方式存储此信息:
- 在 Dialogflow 上下文中
- 在用户会话存储中
- 在会话的数据库或数据存储中
简而言之,您必须使用当前的任何方式来存储会话信息。以下所有信息均假定您已选择某种方式来执行此操作。
由于所有内容都将成为 lineItems
之一,一个简单的解决方案是边构建这个数组,然后您可以直接将数组复制到订单对象中。另一种方法是仅存储项目 ID 列表,然后在我们构建订单时填充其余信息。
对于这个例子,我们将采用后一种方案(因为它更容易显示)并使用 actions-on-google 库将其存储在会话存储对象中。
所以对于初学者来说,当我们开始操作时,或者当我们知道我们将接受订单时,我们需要使用类似
的东西来初始化我们正在订购的项目列表
conv.user.data.items = [];
现在我们有了初始项目列表,我们可以探索添加到此列表的不同方法。
添加项目:"my regular"
对于某些类型的订单,用户能够说 "I'll have my usual" 可能是有意义的。在这种情况下,我们需要一个 Intent 来处理这个短语(或处理 "yes" 对我们提示的响应),以及一个 Intent Handler 来查找用户的常规订单并将其添加到项目中。也许是这样的:
app.intent('order.usual', conv => {
// Get their user profile from our database
// The "loadUser" function is up to you, and has little to do with AoG
return loadUser( conv )
.then( user => {
// Add each item in their usual order to the current items
let usualOrder = user.usualOrder;
usualOrder.forEach( item => conv.user.data.items.push( item ) );
// Send a message back to the user
conv.add( "You got it! Do you want anything else?" );
});
});
从列表中添加项目
如果您向用户展示了可能项目的旋转木马或列表,您的生活就会轻松一些(尽管您目前可能不这么认为)。您确实需要设置一个 Dialogflow Intent 来处理 actions_intent_OPTION
事件(在本例中我将其称为 order.option
)。
在此处理程序中,我们假设您用于该选项的密钥也恰好是项目 ID,因此您可以将其添加到列表中
app.intent('order.option', (conv, params, option) => {
// The item is the option sent
let item = option;
// Add the item to the list of items
conv.user.data.items.push( item );
// Send a message back to the user
conv.add( "I've put that in your cart. Anything else?" );
});
按名称添加项目
但请记住,用户可以随时向任何方向进行对话。因此,他们可能会要求您当前未在轮播中显示的项目。处理此问题的最佳方法是在 Dialogflow 中创建一个实体类型(我将其称为 item
,作为示例)
然后是一个 Intent,它捕获一些表达用户要求添加它们的短语(我将其称为 order.name
并且它有一个用户必须包含的 itemName
参数)。
[
在处理程序中,您需要获取他们所说的姓名,查找商品是什么,并将其添加到他们订购的商品列表中。
app.intent('order.name', (conv, params) => {
// Get the name
let itemName = params['itemName'];
// Look it up to find out what they ordered
// You need to implement the itemFromName function
return itemFromName( itemName )
.then( item => {
// Add the item
conv.user.data.items.push( item );
// And reply
conv.add( "You got it! Anything else?" );
});
});
完成构建订单
一旦你收集完他们想要的所有东西,你的 Intent Handler 应该把顺序放在一起,从我们一直放在一起的 conv.user.data.items
数组中组装 lineItems
的完整列表,计算税收、总计和 order
.
的所有其他部分
然后我们需要 propose the order 通过发送包含我们在 proposedOrder
参数中的订单的 TransactionDecision 对象。聪明,不是吗?可能是这样的:
app.intent('review', conv => {
// Get the items the user has saved
let items = conv.user.data.items;
// Turn these into more complete lineItems
// You will need to provide the "itemToLineItem" function
let lineItems = items.map( itemToLineItem );
// Get some other objects we need
// You'll need to define these functions, too
let orderId = generateOrderId();
let subtotal = computeSubtotal( lineItems );
let tax = computeTax( lineItems );
let total = computerTotal( subtotal, tax );
// Build the order object
let order = buildOrder( lineItems, subtotal, tax, total );
conv.ask(new TransactionDecision({
orderOptions: {
requestDeliveryAddress: false,
},
paymentOptions: {
googleProvidedOptions: {
prepaidCardDisallowed: false,
supportedCardNetworks: ['VISA', 'AMEX'],
// These will be provided by payment processor,
// like Stripe, Braintree, or Vantiv.
tokenizationParameters: {
tokenizationType: 'PAYMENT_GATEWAY',
parameters: {
'gateway': 'stripe',
'stripe:publishableKey': (conv.sandbox ? 'pk_test_key' : 'pk_live_key'),
'stripe:version': '2017-04-06'
},
},
},
},
proposedOrder: order,
}));
});
我将大部分内容分解为一个函数,因为除了订单格式(您在示例中说明)之外,它们没有任何具体内容。您真的可以随心所欲地构建它。
结论
您需要做的很多事情都可以归结为
- 收集用户想点什么的信息,主要是存储这些商品的ID
- 将这个项目列表变成完整的订单对象
- 正在发送此订单以供用户查看
我正在构建一个 AOG(对 google 的操作)项目,它将执行基本的交易功能。由于我对 AOG 还是有点陌生,所以我完全不知道如何获取用户选择的内容(无论是旋转木马、基本卡片等)并将他们选择的参数 value/key 传递给在他们完成交易之前建议的订单或订单预览。
这基本上是我尝试过的(这不是实际的代码,因为它相当长,但它仍然理解了这个想法)
app.intent('delivery_address_complete', (conv) => {
const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE');
if (arg.userDecision ==='ACCEPTED') {
conv.ask('Ok, what would you like to order?');
conv.ask(new Suggestions(intentSuggestions));
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
SELECTION_KEY_COFFEE: {
synonyms: [
'Coffee'
],
title: 'Coffee',
description: 'Sweet cream and sugar coffee.',
image: new Image({
url: IMG_URL_COFFEE,
alt: 'Image alternate text',
}),
},
}));
}
});
const yesOrno = [
'Yes',
'No'
];
app.intent('actions.intent.OPTION', (conv ) => {
conv.ask('Okay, are you ready to proceed?');
conv.ask(new Suggestions(yesOrno));
});
app.intent('transaction_decision_action', (conv) => {
const order = {
id: UNIQUE_ORDER_ID,
cart: {
merchant: {
id: 'coffee',
name: 'Coffee Store',
},
lineItems: [
{
name: 'My Memoirs',
id: 'coffee_1',
price: {
amount: {
currencyCode: 'USD',
nanos: 990000000,
units: 3,
},
type: 'ACTUAL',
},
quantity: 1,
subLines: [
{
note: 'coffee',
},
],
type: 'REGULAR',
},
otherItems: [
{
name: 'Subtotal',
id: 'subtotal',
price: {
amount: {
currencyCode: 'USD',
nanos: 220000000,
units: 32,
},
type: 'ESTIMATE',
},
type: 'SUBTOTAL',
},
{
name: 'Tax',
id: 'tax',
price: {
amount: {
currencyCode: 'USD',
nanos: 780000000,
units: 2,
},
type: 'ESTIMATE',
},
type: 'TAX',
},
],
totalPrice: {
amount: {
currencyCode: 'USD',
nanos: 0,
units: 35,
},
type: 'ESTIMATE',
},
};
请注意:这主要是伪代码,因此如果出现收费过高或价格不合理等问题,这不是我要解决的问题。
我如何获取用户通过任何方法选择的内容,并将其显示在订单预览或建议订单中?我不需要任何有关制作旋转木马或基本卡片等的帮助。只是如何将这个选中的信息获取到订单预览中。
更具体地说:
- 我可以创建一个所需的
order
对象,并且我知道如何将它作为ProposedOrder
对象的一部分发送给 Google(然后发送给用户)成为TransactionDecision
对象的一部分。 (上面代码中的 "transaction_decision_action" Intent 处理程序。) - 我不明白的是如何根据用户所说的内容或通过选择轮播或我向他们展示的列表项来构建
order
。 (例如,我在上面的 "actions.intent.OPTION" Intent 处理程序中做什么?)
编辑: 这也可能会消除任何混淆。这是我正在尝试做的事情的视频表示(在下面的评论中提到):
- youtube.com/watch?v=LlgMcJBnNN8 从 1:02 到 1:29 我知道该怎么做,我很困惑(在视频示例中)他们是如何获得 'turkey sandwich'并且 'Green smoothie' 添加到 1:35 处的订单预览来自轮播选择
您要做的就是 Google 所指的 building the order。正如它指出的那样 link
Once you have the user information you need, you'll build a "cart assembly" experience that guides the user to build an order. Every Action will likely have a slightly different cart assembly flow as appropriate for your product or service.
You could build a cart assembly experience that enables the user to re-order their most recent purchase via a simple yes or no question. You could also present the user a carousel or list card of the top "featured" or "recommended" items. We recommend using rich responses to present the user's options visually, but also design the conversation such that the user can build their cart using only their voice.
For more information on how to build a high-quality cart assembly experience, see the Transactions Design Guidelines.
所以没有一种方法可以完成您的要求。但是,有一些提示可以帮助您构建 proposed order.
管理订单
您需要做的最重要的事情是在整个过程中跟踪用户订购的所有东西。您可以通过多种方式存储此信息:
- 在 Dialogflow 上下文中
- 在用户会话存储中
- 在会话的数据库或数据存储中
简而言之,您必须使用当前的任何方式来存储会话信息。以下所有信息均假定您已选择某种方式来执行此操作。
由于所有内容都将成为 lineItems
之一,一个简单的解决方案是边构建这个数组,然后您可以直接将数组复制到订单对象中。另一种方法是仅存储项目 ID 列表,然后在我们构建订单时填充其余信息。
对于这个例子,我们将采用后一种方案(因为它更容易显示)并使用 actions-on-google 库将其存储在会话存储对象中。
所以对于初学者来说,当我们开始操作时,或者当我们知道我们将接受订单时,我们需要使用类似
的东西来初始化我们正在订购的项目列表conv.user.data.items = [];
现在我们有了初始项目列表,我们可以探索添加到此列表的不同方法。
添加项目:"my regular"
对于某些类型的订单,用户能够说 "I'll have my usual" 可能是有意义的。在这种情况下,我们需要一个 Intent 来处理这个短语(或处理 "yes" 对我们提示的响应),以及一个 Intent Handler 来查找用户的常规订单并将其添加到项目中。也许是这样的:
app.intent('order.usual', conv => {
// Get their user profile from our database
// The "loadUser" function is up to you, and has little to do with AoG
return loadUser( conv )
.then( user => {
// Add each item in their usual order to the current items
let usualOrder = user.usualOrder;
usualOrder.forEach( item => conv.user.data.items.push( item ) );
// Send a message back to the user
conv.add( "You got it! Do you want anything else?" );
});
});
从列表中添加项目
如果您向用户展示了可能项目的旋转木马或列表,您的生活就会轻松一些(尽管您目前可能不这么认为)。您确实需要设置一个 Dialogflow Intent 来处理 actions_intent_OPTION
事件(在本例中我将其称为 order.option
)。
在此处理程序中,我们假设您用于该选项的密钥也恰好是项目 ID,因此您可以将其添加到列表中
app.intent('order.option', (conv, params, option) => {
// The item is the option sent
let item = option;
// Add the item to the list of items
conv.user.data.items.push( item );
// Send a message back to the user
conv.add( "I've put that in your cart. Anything else?" );
});
按名称添加项目
但请记住,用户可以随时向任何方向进行对话。因此,他们可能会要求您当前未在轮播中显示的项目。处理此问题的最佳方法是在 Dialogflow 中创建一个实体类型(我将其称为 item
,作为示例)
然后是一个 Intent,它捕获一些表达用户要求添加它们的短语(我将其称为 order.name
并且它有一个用户必须包含的 itemName
参数)。
[
在处理程序中,您需要获取他们所说的姓名,查找商品是什么,并将其添加到他们订购的商品列表中。
app.intent('order.name', (conv, params) => {
// Get the name
let itemName = params['itemName'];
// Look it up to find out what they ordered
// You need to implement the itemFromName function
return itemFromName( itemName )
.then( item => {
// Add the item
conv.user.data.items.push( item );
// And reply
conv.add( "You got it! Anything else?" );
});
});
完成构建订单
一旦你收集完他们想要的所有东西,你的 Intent Handler 应该把顺序放在一起,从我们一直放在一起的 conv.user.data.items
数组中组装 lineItems
的完整列表,计算税收、总计和 order
.
然后我们需要 propose the order 通过发送包含我们在 proposedOrder
参数中的订单的 TransactionDecision 对象。聪明,不是吗?可能是这样的:
app.intent('review', conv => {
// Get the items the user has saved
let items = conv.user.data.items;
// Turn these into more complete lineItems
// You will need to provide the "itemToLineItem" function
let lineItems = items.map( itemToLineItem );
// Get some other objects we need
// You'll need to define these functions, too
let orderId = generateOrderId();
let subtotal = computeSubtotal( lineItems );
let tax = computeTax( lineItems );
let total = computerTotal( subtotal, tax );
// Build the order object
let order = buildOrder( lineItems, subtotal, tax, total );
conv.ask(new TransactionDecision({
orderOptions: {
requestDeliveryAddress: false,
},
paymentOptions: {
googleProvidedOptions: {
prepaidCardDisallowed: false,
supportedCardNetworks: ['VISA', 'AMEX'],
// These will be provided by payment processor,
// like Stripe, Braintree, or Vantiv.
tokenizationParameters: {
tokenizationType: 'PAYMENT_GATEWAY',
parameters: {
'gateway': 'stripe',
'stripe:publishableKey': (conv.sandbox ? 'pk_test_key' : 'pk_live_key'),
'stripe:version': '2017-04-06'
},
},
},
},
proposedOrder: order,
}));
});
我将大部分内容分解为一个函数,因为除了订单格式(您在示例中说明)之外,它们没有任何具体内容。您真的可以随心所欲地构建它。
结论
您需要做的很多事情都可以归结为
- 收集用户想点什么的信息,主要是存储这些商品的ID
- 将这个项目列表变成完整的订单对象
- 正在发送此订单以供用户查看