En esta guía, se explica el proceso de desarrollo de un proyecto de Actions que incorpore transacciones de bienes físicos y use Google Pay para los pagos
Flujo de transacción
Cuando tu proyecto de Acciones maneja transacciones físicas con Google Pay, usa el siguiente flujo:
- Recopilar información (opcional): Según la naturaleza de
por cada transacción, te recomendamos que recopiles la siguiente información del usuario al inicio
de la conversación.
- Valida los requisitos de las transacciones: Usa el asistente de requisitos para las transacciones. al inicio de la conversación para asegurarte de que la información de pago del usuario esté configurada correctamente y esté disponible antes de que el usuario cree su carrito.
- Solicita una dirección de entrega: Si tu transacción requiere una entrega dirección, solicita la entrega del intent auxiliar de dirección de entrega para recopilar una del usuario.
- Crea el orden: explícale al usuario “montaje de carrito” en la que eligen los artículos que quieren comprar.
- Proponer el pedido: Una vez que el carrito esté completo, propone el pedido a al usuario para que pueda confirmar que es correcto. Si se confirma el pedido, recibir una respuesta con los detalles del pedido y un token de pago.
- Finalizar el pedido y enviar el recibo: Una vez confirmado el pedido, actualiza seguimiento del inventario u otros servicios de entrega y, luego, enviar un recibo para el usuario.
- Enviar actualizaciones de pedidos: Durante el ciclo de vida del pedido, proporcionar al usuario actualizaciones sobre el pedido enviando solicitudes PATCH al equipo de Pedidos en la API de Cloud.
Restricciones y lineamientos de revisión
Ten en cuenta que se aplican políticas adicionales a las Acciones con transacciones. Podemos demorar hasta seis semanas en revisar las acciones con transacciones, así que ten en cuenta ese tiempo cuando planifiques tu programa de lanzamientos. Para facilitar el proceso de revisión, asegúrate de cumplir con las políticas y los lineamientos para las transacciones antes de enviar tu Acción para su revisión.
Solo puedes implementar Acciones que vendan bienes físicos en los siguientes países:
Australia Brasil Canadá Indonesia |
Japón México Catar Rusia |
Singapur Suiza Tailandia Türkiye Reino Unido Estados Unidos |
Cómo compilar un proyecto
Para ver ejemplos exhaustivos de conversaciones transaccionales, consulta nuestras muestras de transacciones en Node.js y Java.
Configura el proyecto
Cuando crees tu Acción, debes especificar que quieres realizar transacciones en la Consola de Actions. Además, si estás con la biblioteca cliente de Node.js, configura tu entrega para que use la versión de la API de Orders.
Para configurar tu proyecto y entrega, haz lo siguiente:
- Crea un proyecto nuevo o importa uno existente.
- Navega a Implementar > Información del directorio.
En Información adicional > Transacciones > marca la casilla que dice "Realiza tus acciones usar la API de Transactions para realizar transacciones de bienes físicos?".
Si usas la biblioteca cliente de Node.js para compilar la entrega de tu Acción, abre tu código de entrega y actualiza la publicación de tu app para establecer la la marca
ordersv3
atrue
. En el siguiente fragmento de código, se muestra una app de ejemplo para la versión 3 de Pedidos.
Node.js
const {dialogflow} = require('actions-on-google'); let app = dialogflow({ clientId, // If using account linking debug: true, ordersv3: true, });
Node.js
const {actionssdk} = require('actions-on-google'); let app = actionssdk({ clientId, // If using account linking debug: true, ordersv3: true, });
1. Recopila información (opcional)
1a. Valida los requisitos de las transacciones (opcional).
Experiencia del usuario
Tan pronto como el usuario indique que desea realizar una compra, te recomendamos que actives el
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
para asegurarse rápidamente de
no puedan realizar una transacción. Por ejemplo, cuando se invoca, tu Action puede preguntar:
"¿te gustaría pedir zapatos o consultar el saldo de tu cuenta?" Si el usuario dice
"pedir zapatos", debes solicitar este intent de inmediato. Esto garantizará
que pueden continuar y darles la oportunidad de corregir cualquier configuración
lo que evita que continúen con la transacción.
Cómo solicitar las transacciones el intent de verificación de requisitos dará como resultado uno de los siguientes resultados:
- Si se cumplen los requisitos, el intent se enviará de vuelta a tu entrega con un la condición de éxito y puedes continuar con la creación del orden del usuario.
- Si no se pueden cumplir uno o más de los requisitos, se devolverá el intent.
a tu entrega con una condición de falla. En este caso, debes reorientar la
una conversación fuera de la experiencia transaccional o finalizarla.
- Si el usuario puede corregir algún error que genere el estado de falla, se le solicitará que resuelva esos problemas en su dispositivo. Si el botón conversación se desarrolla en una plataforma de solo voz, se iniciará una transferencia al teléfono del usuario.
Entrega
Para garantizar que un usuario cumpla
los requisitos de las transacciones, solicitar el cumplimiento del
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
con una
TransactionRequirementsCheckSpec.
Consulte los requisitos
Puedes verificar si un usuario cumple con los requisitos de las transacciones mediante la biblioteca cliente:
Node.js
conv.ask(new TransactionRequirements());
Node.js
conv.ask(new TransactionRequirements());
Java
return getResponseBuilder(request) .add(new TransactionRequirements()) .build();
Java
return getResponseBuilder(request) .add(new TransactionRequirements()) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Looks like you're good to go! Next I'll need your delivery address.Try saying \"get delivery address\"." } } ], "suggestions": [ { "title": "get delivery address" } ] } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Looks like you're good to go! Next I'll need your delivery address.Try saying \"get delivery address\"." } } ], "suggestions": [ { "title": "get delivery address" } ] } } } ], "conversationToken": "{\"data\":{\"paymentType\":\"google_payment\"}}" }
Recibir el resultado de una verificación de requisitos
Después de que Asistente completa el intent, le envía una solicitud a tu entrega
con el intent actions.intent.TRANSACTION_REQUIREMENTS_CHECK
con el resultado
de la cuenta.
Para manejar correctamente esta solicitud, declara un intent de Dialogflow que se active mediante
el evento actions_intent_TRANSACTION_REQUIREMENTS_CHECK
. Cuando se activa,
controlarlo en tu entrega con la biblioteca cliente:
Node.js
app.intent('Transaction Check Complete', (conv) => { const arg = conv.arguments.get('TRANSACTION_REQUIREMENTS_CHECK_RESULT'); if (arg && arg.resultType === 'CAN_TRANSACT') { // Normally take the user through cart building flow conv.ask(`Looks like you're good to go! ` + `Next I'll need your delivery address.` + `Try saying "get delivery address".`); conv.ask(new Suggestions('get delivery address')); } else { // Exit conversation conv.close('Transaction failed.'); } });
Node.js
app.intent('actions.intent.TRANSACTION_REQUIREMENTS_CHECK', (conv) => { const arg = conv.arguments.get('TRANSACTION_REQUIREMENTS_CHECK_RESULT'); if (arg && arg.resultType === 'CAN_TRANSACT') { // Normally take the user through cart building flow conv.ask(`Looks like you're good to go! ` + `Next I'll need your delivery address.` + `Try saying "get delivery address".`); conv.ask(new Suggestions('get delivery address')); } else { // Exit conversation conv.close('Transaction failed.'); } });
Java
@ForIntent("Transaction Check Complete") public ActionResponse transactionCheckComplete(ActionRequest request) { LOGGER.info("Checking Transaction Requirements Result."); // Check result of transaction requirements check Argument transactionCheckResult = request .getArgument("TRANSACTION_REQUIREMENTS_CHECK_RESULT"); boolean result = false; if (transactionCheckResult != null) { Map<String, Object> map = transactionCheckResult.getExtension(); if (map != null) { String resultType = (String) map.get("resultType"); result = resultType != null && resultType.equals("CAN_TRANSACT"); } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (result) { // Normally take the user through cart building flow responseBuilder .add("Looks like you're good to go! Next " + "I'll need your delivery address. Try saying " + "\"get delivery address\".") .addSuggestions(new String[]{"get delivery address"}); } else { // Exit conversation responseBuilder.add("Transaction failed."); } return responseBuilder.build(); }
Java
@ForIntent("actions.intent.TRANSACTION_REQUIREMENTS_CHECK") public ActionResponse transactionCheckComplete(ActionRequest request) { LOGGER.info("Checking Transaction Requirements Result."); // Check result of transaction requirements check Argument transactionCheckResult = request .getArgument("TRANSACTION_REQUIREMENTS_CHECK_RESULT"); boolean result = false; if (transactionCheckResult != null) { Map<String, Object> map = transactionCheckResult.getExtension(); if (map != null) { String resultType = (String) map.get("resultType"); result = resultType != null && resultType.equals("CAN_TRANSACT"); } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (result) { // Normally take the user through cart building flow responseBuilder .add("Looks like you're good to go! Next " + "I'll need your delivery address. Try saying " + "\"get delivery address\".") .addSuggestions(new String[]{"get delivery address"}); } else { // Exit conversation responseBuilder.add("Transaction failed."); } return responseBuilder.build(); }
JSON
{ "responseId": "db1a333c-2781-41e3-84b1-cc0cc37643d7-594de0a7", "queryResult": { "queryText": "actions_intent_TRANSACTION_REQUIREMENTS_CHECK", "action": "transaction.check.complete", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Failed to get transaction check results", "fulfillmentMessages": [ { "text": { "text": [ "Failed to get transaction check results" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/google_assistant_input_type_keyboard" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/merchant_payment", "lifespanCount": 1 }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_transaction_requirements_check", "parameters": { "TRANSACTION_REQUIREMENTS_CHECK_RESULT": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" }, "text": "" } } ], "intent": { "name": "projects/df-transactions/agent/intents/fd16d86b-60db-4d19-a683-5b52a22f4795", "displayName": "Transaction Check Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:32Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[\"merchant_payment\"]" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "rawInputs": [ { "inputType": "KEYBOARD" } ], "arguments": [ { "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:56:03Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "rawInputs": [ {} ], "arguments": [ { "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
1b. Solicita una dirección de entrega (opcional)
Si la transacción requiere la dirección de entrega de un usuario, puedes solicitar
entrega del intent actions.intent.DELIVERY_ADDRESS
. Puede ser
útil para determinar el precio total, la ubicación de entrega/retiro o para
lo que garantiza que el usuario
esté dentro de la región de servicio.
Cuando solicitas que se cumpla este intent, pasas una opción reason
que
te permite anteponer la solicitud del Asistente para obtener una dirección con una cadena.
Por ejemplo, si especificas "saber dónde enviar el pedido", Asistente
pueden preguntar al usuario:
“Para saber dónde enviar el pedido, necesito tu dirección de entrega”
Experiencia del usuario
En las superficies con pantalla, el usuario elegirá la dirección que desea usar para la transacción. Si no proporcionó una dirección anteriormente, será ingresar una nueva dirección.
En plataformas que solo usan voz, el Asistente le pedirá permiso al usuario para compartir su dirección predeterminada para la transacción. Si no han otorgado un dirección, la conversación se pasará a un teléfono para que la ingrese.
Solicita la dirección
Node.js
app.intent('Delivery Address', (conv) => { conv.ask(new DeliveryAddress({ addressOptions: { reason: 'To know where to send the order', }, })); });
Node.js
conv.ask(new DeliveryAddress({ addressOptions: { reason: 'To know where to send the order', }, }));
Java
@ForIntent("Delivery Address") public ActionResponse deliveryAddress(ActionRequest request) { DeliveryAddressValueSpecAddressOptions addressOptions = new DeliveryAddressValueSpecAddressOptions() .setReason("To know where to send the order"); return getResponseBuilder(request) .add(new DeliveryAddress() .setAddressOptions(addressOptions)) .build(); }
Java
DeliveryAddressValueSpecAddressOptions addressOptions = new DeliveryAddressValueSpecAddressOptions() .setReason("To know where to send the order"); return getResponseBuilder(request) .add(new DeliveryAddress() .setAddressOptions(addressOptions)) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.DELIVERY_ADDRESS", "data": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec", "addressOptions": { "reason": "To know where to send the order" } } } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.DELIVERY_ADDRESS", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec", "addressOptions": { "reason": "To know where to send the order" } } } ] } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }
Recibir la dirección
Después de que Asistente completa el intent, le envía una solicitud a tu entrega
con el intent actions.intent.DELIVERY_ADDRESS
.
Para manejar correctamente esta solicitud, declara un intent de Dialogflow que se active mediante
el evento actions_intent_DELIVERY_ADDRESS
. Cuando se active, adminístralo en tu
entrega con la biblioteca cliente:
Node.js
app.intent('Delivery Address Complete', (conv) => { const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE'); if (arg && arg.userDecision ==='ACCEPTED') { conv.data.location = arg.location; conv.ask('Great, got your address! Now say "confirm transaction".'); conv.ask(new Suggestions('confirm transaction')); } else { conv.close('Transaction failed.'); } });
Node.js
app.intent('actions.intent.DELIVERY_ADDRESS', (conv) => { const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE'); if (arg && arg.userDecision ==='ACCEPTED') { conv.data.location = arg.location; conv.ask('Great, got your address! Now say "confirm transaction".'); conv.ask(new Suggestions('confirm transaction')); } else { conv.close('Transaction failed.'); } });
Java
@ForIntent("Delivery Address Complete") public ActionResponse deliveryAddressComplete(ActionRequest request) { Argument deliveryAddressValue = request.getArgument("DELIVERY_ADDRESS_VALUE"); Location deliveryAddress = null; if (deliveryAddressValue != null) { Map<String, Object> map = deliveryAddressValue.getExtension(); if (map != null) { String userDecision = (String) map.get("userDecision"); Location location = (Location) map.get("location"); deliveryAddress = userDecision != null && userDecision.equals("ACCEPTED") ? location : null; } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (deliveryAddress != null) { // Cache delivery address in conversation data for later use Map<String, Object> conversationData = request.getConversationData(); conversationData.put("location", GSON_BUILDER.create().toJson(deliveryAddress, Location.class)); responseBuilder .add("Great, got your address! Now say \"confirm transaction\".") .addSuggestions(new String[] { "confirm transaction" }); } else { responseBuilder.add("Transaction failed.").endConversation(); } return responseBuilder.build(); }
Java
@ForIntent("actions.intent.DELIVERY_ADDRESS") public ActionResponse deliveryAddressComplete(ActionRequest request) { Argument deliveryAddressValue = request.getArgument("DELIVERY_ADDRESS_VALUE"); Location deliveryAddress = null; if (deliveryAddressValue != null) { Map<String, Object> map = deliveryAddressValue.getExtension(); if (map != null) { String userDecision = (String) map.get("userDecision"); Location location = (Location) map.get("location"); deliveryAddress = userDecision != null && userDecision.equals("ACCEPTED") ? location : null; } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (deliveryAddress != null) { // Cache delivery address in conversation data for later use Map<String, Object> conversationData = request.getConversationData(); conversationData.put("location", GSON_BUILDER.create().toJson(deliveryAddress, Location.class)); responseBuilder .add("Great, got your address! Now say \"confirm transaction\".") .addSuggestions(new String[] { "confirm transaction" }); } else { responseBuilder.add("Transaction failed.").endConversation(); } return responseBuilder.build(); }
JSON
{ "responseId": "58b0c305-b437-47ac-8593-4fb0122a19e6-594de0a7", "queryResult": { "queryText": "actions_intent_DELIVERY_ADDRESS", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentMessages": [ { "text": { "text": [ "" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_delivery_address", "parameters": { "DELIVERY_ADDRESS_VALUE": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue", "userDecision": "ACCEPTED", "location": { "coordinates": { "latitude": 37.432524, "longitude": -122.098545 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" } }, "text": "1600 AMPHITHEATRE PKWY" } } ], "intent": { "name": "projects/df-transactions/agent/intents/0be5d130-1760-4355-85e9-4dc01da8bf3c", "displayName": "Delivery Address Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:55Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.DELIVERY_ADDRESS", "rawInputs": [ { "query": "1600 AMPHITHEATRE PKWY" } ], "arguments": [ { "name": "DELIVERY_ADDRESS_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue", "userDecision": "ACCEPTED", "location": { "coordinates": { "latitude": 37.432524, "longitude": -122.098545 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" } } } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:57:20Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }, "inputs": [ { "intent": "actions.intent.DELIVERY_ADDRESS", "rawInputs": [ { "inputType": "VOICE", "query": "1600 AMPHITHEATRE PKWY" } ], "arguments": [ { "name": "DELIVERY_ADDRESS_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue", "userDecision": "ACCEPTED", "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" } } }, { "name": "text", "rawText": "1600 AMPHITHEATRE PKWY", "textValue": "1600 AMPHITHEATRE PKWY" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }
2. Crea el pedido
Experiencia del usuario
Una vez que tienes la información del usuario que necesitas, creas un "carrito" ensamblado" experiencia que guía al usuario a crear un pedido. Todas las Acción tienen un flujo de montaje de carro ligeramente diferente según corresponda para su producto o servicio.
En la experiencia más básica de ensamblado de carritos, el usuario elige artículos de una lista para agregarlos a su orden, aunque puedes diseñar la conversación para simplificar el proceso la experiencia del usuario. Podrías crear una experiencia de ensamblado de carro que permita que la que vuelva a ordenar su compra más reciente mediante una simple pregunta de sí o no. También puedes presentar al usuario un carrusel o una tarjeta de lista de los principales "destacados" o "recomendado" elementos.
Recomendamos usar elementos respuestas para presentar las opciones del usuario sino también diseñar la conversación, de modo que el usuario pueda construir carrito solo con su voz. Para ver algunas prácticas recomendadas y ejemplos experiencias de alta calidad en el armado de carritos, consulta la Lineamientos de diseño de transacciones.
Entrega
A lo largo de la conversación, deberás reunir los elementos que el usuario quiere
para comprar y, luego, construye un objeto Order
.
Como mínimo, tu Order
debe contener lo siguiente:
buyerInfo
: Es la información sobre el usuario que realiza la compra.transactionMerchant
: información sobre el comercio que facilitó la en el orden personalizado.contents
: Es el contenido real del pedido que aparece comolineItems
.priceAttributes
: Detalles de precios del pedido, incluido el total el costo del pedido con impuestos y descuentos.
Consulta la documentación sobre la respuesta de Order
.
para construir tu carrito. Es posible que debas incluir campos diferentes
según el orden.
El siguiente código de muestra muestra un pedido completo, incluidos los campos opcionales:
Node.js
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: 'Pizza', description: 'A four cheese pizza.', priceAttributes: [ { type: 'REGULAR', name: 'Item Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 8990000, }, taxIncluded: true, }, { type: 'TOTAL', name: 'Total Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 9990000, }, taxIncluded: true, }, ], notes: [ 'Extra cheese.', ], purchase: { quantity: 1, unitMeasure: { measure: 1, unit: 'POUND', }, itemOptions: [ { id: 'ITEM_OPTION_ID', name: 'Pepperoni', prices: [ { type: 'REGULAR', state: 'ACTUAL', name: 'Item Price', amount: { currencyCode: 'USD', amountInMicros: 1000000, }, taxIncluded: true, }, { type: 'TOTAL', name: 'Total Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 1000000, }, taxIncluded: true, }, ], note: 'Extra pepperoni', quantity: 1, subOptions: [], }, ], }, }, ], }, buyerInfo: { email: 'janedoe@gmail.com', firstName: 'Jane', lastName: 'Doe', displayName: 'Jane Doe', }, priceAttributes: [ { type: 'SUBTOTAL', name: 'Subtotal', state: 'ESTIMATE', amount: { currencyCode: 'USD', amountInMicros: 9990000, }, taxIncluded: true, }, { type: 'DELIVERY', name: 'Delivery', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 2000000, }, taxIncluded: true, }, { type: 'TAX', name: 'Tax', state: 'ESTIMATE', amount: { currencyCode: 'USD', amountInMicros: 3780000, }, taxIncluded: true, }, { type: 'TOTAL', name: 'Total Price', state: 'ESTIMATE', amount: { currencyCode: 'USD', amountInMicros: 15770000, }, taxIncluded: true, }, ], 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', note: 'Sale event', promotions: [ { coupon: 'COUPON_CODE', }, ], purchase: { status: 'CREATED', userVisibleStatusLabel: 'CREATED', type: 'FOOD', returnsInfo: { isReturnable: false, daysToReturn: 1, policyUrl: 'http://www.example.com', }, fulfillmentInfo: { id: 'FULFILLMENT_SERVICE_ID', fulfillmentType: 'DELIVERY', expectedFulfillmentTime: { timeIso8601: '2019-09-25T18:00:00.877Z', }, location: location, price: { type: 'REGULAR', name: 'Delivery Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 2000000, }, taxIncluded: true, }, fulfillmentContact: { email: 'johnjohnson@gmail.com', firstName: 'John', lastName: 'Johnson', displayName: 'John Johnson', }, }, purchaseLocationType: 'ONLINE_PURCHASE', }, };
Node.js
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: 'Pizza', description: 'A four cheese pizza.', priceAttributes: [ { type: 'REGULAR', name: 'Item Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 8990000, }, taxIncluded: true, }, { type: 'TOTAL', name: 'Total Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 9990000, }, taxIncluded: true, }, ], notes: [ 'Extra cheese.', ], purchase: { quantity: 1, unitMeasure: { measure: 1, unit: 'POUND', }, itemOptions: [ { id: 'ITEM_OPTION_ID', name: 'Pepperoni', prices: [ { type: 'REGULAR', state: 'ACTUAL', name: 'Item Price', amount: { currencyCode: 'USD', amountInMicros: 1000000, }, taxIncluded: true, }, { type: 'TOTAL', name: 'Total Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 1000000, }, taxIncluded: true, }, ], note: 'Extra pepperoni', quantity: 1, subOptions: [], }, ], }, }, ], }, buyerInfo: { email: 'janedoe@gmail.com', firstName: 'Jane', lastName: 'Doe', displayName: 'Jane Doe', }, priceAttributes: [ { type: 'SUBTOTAL', name: 'Subtotal', state: 'ESTIMATE', amount: { currencyCode: 'USD', amountInMicros: 9990000, }, taxIncluded: true, }, { type: 'DELIVERY', name: 'Delivery', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 2000000, }, taxIncluded: true, }, { type: 'TAX', name: 'Tax', state: 'ESTIMATE', amount: { currencyCode: 'USD', amountInMicros: 3780000, }, taxIncluded: true, }, { type: 'TOTAL', name: 'Total Price', state: 'ESTIMATE', amount: { currencyCode: 'USD', amountInMicros: 15770000, }, taxIncluded: true, }, ], 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', note: 'Sale event', promotions: [ { coupon: 'COUPON_CODE', }, ], purchase: { status: 'CREATED', userVisibleStatusLabel: 'CREATED', type: 'FOOD', returnsInfo: { isReturnable: false, daysToReturn: 1, policyUrl: 'http://www.example.com', }, fulfillmentInfo: { id: 'FULFILLMENT_SERVICE_ID', fulfillmentType: 'DELIVERY', expectedFulfillmentTime: { timeIso8601: '2019-09-25T18:00:00.877Z', }, location: location, price: { type: 'REGULAR', name: 'Delivery Price', state: 'ACTUAL', amount: { currencyCode: 'USD', amountInMicros: 2000000, }, taxIncluded: true, }, fulfillmentContact: { email: 'johnjohnson@gmail.com', firstName: 'John', lastName: 'Johnson', displayName: 'John Johnson', }, }, purchaseLocationType: 'ONLINE_PURCHASE', }, };
Java
// Transaction Merchant MerchantV3 transactionMerchant = new MerchantV3() .setId("http://www.example.com") .setName("Example Merchant"); // Line Item PriceAttribute itemPrice = new PriceAttribute() .setType("REGULAR") .setName("Item Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(8990000L) ) .setTaxIncluded(true); PriceAttribute totalItemPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); // Purchase Item Extension PurchaseItemExtension purchaseItemExtension = new PurchaseItemExtension() .setQuantity(1) .setUnitMeasure(new MerchantUnitMeasure() .setMeasure(1.0) .setUnit("POUND")) .setItemOptions(Arrays.asList(new PurchaseItemExtensionItemOption() .setId("ITEM_OPTION_ID") .setName("Pepperoni") .setPrices(Arrays.asList( new PriceAttribute() .setType("REGULAR") .setState("ACTUAL") .setName("Item Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true), new PriceAttribute() .setType("TOTAL") .setState("ACTUAL") .setName("Total Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true) )) .setNote("Extra pepperoni") .setQuantity(1))); LineItemV3 lineItem = new LineItemV3() .setId("LINE_ITEM_ID") .setName("Pizza") .setDescription("A four cheese pizza.") .setPriceAttributes(Arrays.asList(itemPrice, totalItemPrice)) .setNotes(Collections.singletonList("Extra cheese.")) .setPurchase(purchaseItemExtension); // Order Contents OrderContents contents = new OrderContents() .setLineItems(Collections.singletonList(lineItem)); // User Info UserInfo buyerInfo = new UserInfo() .setEmail("janedoe@gmail.com") .setFirstName("Jane") .setLastName("Doe") .setDisplayName("Jane Doe"); // Price Attributes PriceAttribute subTotal = new PriceAttribute() .setType("SUBTOTAL") .setName("Subtotal") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); PriceAttribute deliveryFee = new PriceAttribute() .setType("DELIVERY") .setName("Delivery") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L) ) .setTaxIncluded(true); PriceAttribute tax = new PriceAttribute() .setType("TAX") .setName("Tax") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(3780000L) ) .setTaxIncluded(true); PriceAttribute totalPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(15770000L) ) .setTaxIncluded(true); // Follow up actions Action viewDetails = new Action() .setType("VIEW_DETAILS") .setTitle("View details") .setOpenUrlAction(new OpenUrlAction() .setUrl("https://example.com")); Action call = new Action() .setType("CALL") .setTitle("Call us") .setOpenUrlAction(new OpenUrlAction() .setUrl("tel:+16501112222")); Action email = new Action() .setType("EMAIL") .setTitle("Email us") .setOpenUrlAction(new OpenUrlAction() .setUrl("mailto:person@example.com")); // Terms of service and order note String termsOfServiceUrl = "http://example.com"; String orderNote = "Sale event"; // Promotions PromotionV3 promotion = new PromotionV3() .setCoupon("COUPON_CODE"); // Purchase Order Extension Location location = GSON_BUILDER.create().fromJson( (String) conversationData.get("location"), Location.class); PurchaseOrderExtension purchaseOrderExtension = new PurchaseOrderExtension() .setStatus("CREATED") .setUserVisibleStatusLabel("CREATED") .setType("FOOD") .setReturnsInfo(new PurchaseReturnsInfo() .setIsReturnable(false) .setDaysToReturn(1) .setPolicyUrl("https://example.com")) .setFulfillmentInfo(new PurchaseFulfillmentInfo() .setId("FULFILLMENT_SERVICE_ID") .setFulfillmentType("DELIVERY") .setExpectedFulfillmentTime(new TimeV3() .setTimeIso8601("2019-09-25T18:00:00.877Z")) .setLocation(location) .setPrice(new PriceAttribute() .setType("REGULAR") .setName("Delivery price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L)) .setTaxIncluded(true)) .setFulfillmentContact(new UserInfo() .setEmail("johnjohnson@gmail.com") .setFirstName("John") .setLastName("Johnson") .setDisplayName("John Johnson"))) .setPurchaseLocationType("ONLINE_PURCHASE"); OrderV3 order = new OrderV3() .setCreateTime("2019-09-24T18:00:00.877Z") .setLastUpdateTime("2019-09-24T18:00:00.877Z") .setMerchantOrderId(orderId) .setUserVisibleOrderId(orderId) .setTransactionMerchant(transactionMerchant) .setContents(contents) .setBuyerInfo(buyerInfo) .setPriceAttributes(Arrays.asList( subTotal, deliveryFee, tax, totalPrice )) .setFollowUpActions(Arrays.asList( viewDetails, call, email )) .setTermsOfServiceUrl(termsOfServiceUrl) .setNote(orderNote) .setPromotions(Collections.singletonList(promotion)) .setPurchase(purchaseOrderExtension);
Java
// Transaction Merchant MerchantV3 transactionMerchant = new MerchantV3() .setId("http://www.example.com") .setName("Example Merchant"); // Line Item PriceAttribute itemPrice = new PriceAttribute() .setType("REGULAR") .setName("Item Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(8990000L) ) .setTaxIncluded(true); PriceAttribute totalItemPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); // Purchase Item Extension PurchaseItemExtension purchaseItemExtension = new PurchaseItemExtension() .setUnitMeasure(new MerchantUnitMeasure() .setMeasure(1.0) .setUnit("POUND")) .setItemOptions(Arrays.asList(new PurchaseItemExtensionItemOption() .setId("ITEM_OPTION_ID") .setName("Pepperoni") .setPrices(Arrays.asList( new PriceAttribute() .setType("REGULAR") .setState("ACTUAL") .setName("Item Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true), new PriceAttribute() .setType("TOTAL") .setState("ACTUAL") .setName("Total Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true) )) .setNote("Extra pepperoni"))); LineItemV3 lineItem = new LineItemV3() .setId("LINE_ITEM_ID") .setName("Pizza") .setDescription("A four cheese pizza.") .setPriceAttributes(Arrays.asList(itemPrice, totalItemPrice)) .setNotes(Collections.singletonList("Extra cheese.")) .setPurchase(purchaseItemExtension); // Order Contents OrderContents contents = new OrderContents() .setLineItems(Collections.singletonList(lineItem)); // User Info UserInfo buyerInfo = new UserInfo() .setEmail("janedoe@gmail.com") .setFirstName("Jane") .setLastName("Doe") .setDisplayName("Jane Doe"); // Price Attributes PriceAttribute subTotal = new PriceAttribute() .setType("SUBTOTAL") .setName("Subtotal") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); PriceAttribute deliveryFee = new PriceAttribute() .setType("DELIVERY") .setName("Delivery") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L) ) .setTaxIncluded(true); PriceAttribute tax = new PriceAttribute() .setType("TAX") .setName("Tax") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(3780000L) ) .setTaxIncluded(true); PriceAttribute totalPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(15770000L) ) .setTaxIncluded(true); // Follow up actions Action viewDetails = new Action() .setType("VIEW_DETAILS") .setTitle("View details") .setOpenUrlAction(new OpenUrlAction() .setUrl("https://example.com")); Action call = new Action() .setType("CALL") .setTitle("Call us") .setOpenUrlAction(new OpenUrlAction() .setUrl("tel:+16501112222")); Action email = new Action() .setType("EMAIL") .setTitle("Email us") .setOpenUrlAction(new OpenUrlAction() .setUrl("mailto:person@example.com")); // Terms of service and order note String termsOfServiceUrl = "http://example.com"; String orderNote = "Sale event"; // Promotions PromotionV3 promotion = new PromotionV3() .setCoupon("COUPON_CODE"); // Purchase Order Extension Location location = GSON_BUILDER.create().fromJson( (String) conversationData.get("location"), Location.class); PurchaseOrderExtension purchaseOrderExtension = new PurchaseOrderExtension() .setStatus("CREATED") .setUserVisibleStatusLabel("CREATED") .setType("FOOD") .setReturnsInfo(new PurchaseReturnsInfo() .setIsReturnable(false) .setDaysToReturn(1) .setPolicyUrl("https://example.com")) .setFulfillmentInfo(new PurchaseFulfillmentInfo() .setId("FULFILLMENT_SERVICE_ID") .setFulfillmentType("DELIVERY") .setExpectedFulfillmentTime(new TimeV3() .setTimeIso8601("2019-09-25T18:00:00.877Z")) .setLocation(location) .setPrice(new PriceAttribute() .setType("REGULAR") .setName("Delivery price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L)) .setTaxIncluded(true)) .setFulfillmentContact(new UserInfo() .setEmail("johnjohnson@gmail.com") .setFirstName("John") .setLastName("Johnson") .setDisplayName("John Johnson"))) .setPurchaseLocationType("ONLINE_PURCHASE"); OrderV3 order = new OrderV3() .setCreateTime("2019-09-24T18:00:00.877Z") .setLastUpdateTime("2019-09-24T18:00:00.877Z") .setMerchantOrderId(orderId) .setUserVisibleOrderId(orderId) .setTransactionMerchant(transactionMerchant) .setContents(contents) .setBuyerInfo(buyerInfo) .setPriceAttributes(Arrays.asList( subTotal, deliveryFee, tax, totalPrice )) .setFollowUpActions(Arrays.asList( viewDetails, call, email )) .setTermsOfServiceUrl(termsOfServiceUrl) .setNote(orderNote) .setPromotions(Collections.singletonList(promotion)) .setPurchase(purchaseOrderExtension);
3. Proponer el pedido
Una vez que hayas creado un pedido, debes presentarlo al usuario para confirmarlo o
rechazar. Solicita el actions.intent.TRANSACTION_DECISION
y proporcionan el orden que compilaste.
Experiencia del usuario
Cuando solicitas el intent actions.intent.TRANSACTION_DECISION
, Asistente
inicia una experiencia integrada en la que el Order
que pasaste
se renderiza directamente en una "tarjeta de vista previa del carrito". El usuario puede decir “Realizar pedido”,
rechazar la transacción o cambiar una opción de pago, como la tarjeta de crédito
dirección de correo electrónico
o solicitar que se cambie el contenido del pedido.
En este punto, el usuario también puede solicitar cambios en el pedido. En este caso, debes asegurarte de que tu entrega pueda controlar las solicitudes de cambio de pedidos después la experiencia de armado del carrito.
Entrega
Cuando solicitas el
actions.intent.TRANSACTION_DECISION
, crearás un
TransactionDecision
que contiene el Order
así como orderOptions
y paymentParameters
.
Tu objeto paymentParameters
incluirá parámetros de asignación de token que cambian.
según el procesador de Google Pay que planees usar (como Stripe,
Braintree, ACI, etc.).
En el siguiente código, se muestra un TransactionsDecision
de ejemplo para un pedido:
Node.js
conv.ask(new TransactionDecision({ orderOptions: { userInfoOptions: { userInfoProperties: [ 'EMAIL', ], }, }, paymentParameters: { googlePaymentOption: { // facilitationSpec is expected to be a serialized JSON string facilitationSpec: JSON.stringify({ apiVersion: 2, apiVersionMinor: 0, merchantInfo: { merchantName: 'Example Merchant', }, allowedPaymentMethods: [ { type: 'CARD', parameters: { allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], allowedCardNetworks: [ 'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'], }, tokenizationSpecification: { type: 'PAYMENT_GATEWAY', parameters: { gateway: 'example', gatewayMerchantId: 'exampleGatewayMerchantId', }, }, }, ], transactionInfo: { totalPriceStatus: 'FINAL', totalPrice: '15.77', currencyCode: 'USD', }, }), }, }, presentationOptions: { actionDisplayName: 'PLACE_ORDER', }, order: order, }));
Node.js
conv.ask(new TransactionDecision({ orderOptions: { userInfoOptions: { userInfoProperties: [ 'EMAIL', ], }, }, paymentParameters: { googlePaymentOption: { // facilitationSpec is expected to be a serialized JSON string facilitationSpec: JSON.stringify({ apiVersion: 2, apiVersionMinor: 0, merchantInfo: { merchantName: 'Example Merchant', }, allowedPaymentMethods: [ { type: 'CARD', parameters: { allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], allowedCardNetworks: [ 'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'], }, tokenizationSpecification: { type: 'PAYMENT_GATEWAY', parameters: { gateway: 'example', gatewayMerchantId: 'exampleGatewayMerchantId', }, }, }, ], transactionInfo: { totalPriceStatus: 'FINAL', totalPrice: '15.77', currencyCode: 'USD', }, }), }, }, presentationOptions: { actionDisplayName: 'PLACE_ORDER', }, order: order, }));
Java
// Create order options OrderOptionsV3 orderOptions = new OrderOptionsV3() .setUserInfoOptions(new UserInfoOptions() .setUserInfoProperties(Collections.singletonList("EMAIL"))); // Create presentation options PresentationOptionsV3 presentationOptions = new PresentationOptionsV3() .setActionDisplayName("PLACE_ORDER"); // Create payment parameters JSONObject merchantInfo = new JSONObject(); merchantInfo.put("merchantName", "Example Merchant"); JSONObject facilitationSpec = new JSONObject(); facilitationSpec.put("apiVersion", 2); facilitationSpec.put("apiVersionMinor", 0); facilitationSpec.put("merchantInfo", merchantInfo); JSONObject allowedPaymentMethod = new JSONObject(); allowedPaymentMethod.put("type", "CARD"); JSONArray allowedAuthMethods = new JSONArray(); allowedAuthMethods.addAll(Arrays.asList("PAN_ONLY", "CRYPTOGRAM_3DS")); JSONArray allowedCardNetworks = new JSONArray(); allowedCardNetworks.addAll(Arrays.asList("AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA")); JSONObject allowedPaymentMethodParameters = new JSONObject(); allowedPaymentMethodParameters.put("allowedAuthMethods", allowedAuthMethods); allowedPaymentMethodParameters.put("allowedCardNetworks", allowedCardNetworks); allowedPaymentMethod.put("parameters", allowedPaymentMethodParameters); JSONObject tokenizationSpecificationParameters = new JSONObject(); tokenizationSpecificationParameters.put("gateway", "example"); tokenizationSpecificationParameters.put("gatewayMerchantId", "exampleGatewayMerchantId"); JSONObject tokenizationSpecification = new JSONObject(); tokenizationSpecification.put("type", "PAYMENT_GATEWAY"); tokenizationSpecification.put("parameters", tokenizationSpecificationParameters); allowedPaymentMethod.put("tokenizationSpecification", tokenizationSpecification); JSONArray allowedPaymentMethods = new JSONArray(); allowedPaymentMethods.add(allowedPaymentMethod); facilitationSpec.put("allowedPaymentMethods", allowedPaymentMethods); JSONObject transactionInfo = new JSONObject(); transactionInfo.put("totalPriceStatus", "FINAL"); transactionInfo.put("totalPrice", "15.77"); transactionInfo.put("currencyCode", "USD"); facilitationSpec.put("transactionInfo", transactionInfo); GooglePaymentOption googlePaymentOption = new GooglePaymentOption() .setFacilitationSpec(facilitationSpec.toJSONString()); paymentParameters.setGooglePaymentOption(googlePaymentOption); return getResponseBuilder(request) .add(new TransactionDecision() .setOrder(order) .setOrderOptions(orderOptions) .setPresentationOptions(presentationOptions) .setPaymentParameters(paymentParameters) ) .build();
Java
// Create order options OrderOptionsV3 orderOptions = new OrderOptionsV3() .setUserInfoOptions(new UserInfoOptions() .setUserInfoProperties(Collections.singletonList("EMAIL"))); // Create presentation options PresentationOptionsV3 presentationOptions = new PresentationOptionsV3() .setActionDisplayName("PLACE_ORDER"); // Create payment parameters JSONObject merchantInfo = new JSONObject(); merchantInfo.put("merchantName", "Example Merchant"); JSONObject facilitationSpec = new JSONObject(); facilitationSpec.put("apiVersion", 2); facilitationSpec.put("apiVersionMinor", 0); facilitationSpec.put("merchantInfo", merchantInfo); JSONObject allowedPaymentMethod = new JSONObject(); allowedPaymentMethod.put("type", "CARD"); JSONArray allowedAuthMethods = new JSONArray(); allowedAuthMethods.addAll(Arrays.asList("PAN_ONLY", "CRYPTOGRAM_3DS")); JSONArray allowedCardNetworks = new JSONArray(); allowedCardNetworks.addAll(Arrays.asList("AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA")); JSONObject allowedPaymentMethodParameters = new JSONObject(); allowedPaymentMethodParameters.put("allowedAuthMethods", allowedAuthMethods); allowedPaymentMethodParameters.put("allowedCardNetworks", allowedCardNetworks); allowedPaymentMethod.put("parameters", allowedPaymentMethodParameters); JSONObject tokenizationSpecificationParameters = new JSONObject(); tokenizationSpecificationParameters.put("gateway", "example"); tokenizationSpecificationParameters.put("gatewayMerchantId", "exampleGatewayMerchantId"); JSONObject tokenizationSpecification = new JSONObject(); tokenizationSpecification.put("type", "PAYMENT_GATEWAY"); tokenizationSpecification.put("parameters", tokenizationSpecificationParameters); allowedPaymentMethod.put("tokenizationSpecification", tokenizationSpecification); JSONArray allowedPaymentMethods = new JSONArray(); allowedPaymentMethods.add(allowedPaymentMethod); facilitationSpec.put("allowedPaymentMethods", allowedPaymentMethods); JSONObject transactionInfo = new JSONObject(); transactionInfo.put("totalPriceStatus", "FINAL"); transactionInfo.put("totalPrice", "15.77"); transactionInfo.put("currencyCode", "USD"); facilitationSpec.put("transactionInfo", transactionInfo); GooglePaymentOption googlePaymentOption = new GooglePaymentOption() .setFacilitationSpec(facilitationSpec.toJSONString()); paymentParameters.setGooglePaymentOption(googlePaymentOption); return getResponseBuilder(request) .add(new TransactionDecision() .setOrder(order) .setOrderOptions(orderOptions) .setPresentationOptions(presentationOptions) .setPaymentParameters(paymentParameters) ) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction Decision Placeholder." } } ] }, "systemIntent": { "intent": "actions.intent.TRANSACTION_DECISION", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "userInfoOptions": { "userInfoProperties": [ "EMAIL" ] } }, "paymentParameters": { "merchantPaymentOption": { "defaultMerchantPaymentMethodId": "12345678", "managePaymentMethodUrl": "https://example.com/managePayment", "merchantPaymentMethod": [ { "paymentMethodDisplayInfo": { "paymentMethodDisplayName": "VISA **** 1234", "paymentType": "PAYMENT_CARD" }, "paymentMethodGroup": "Payment method group", "paymentMethodId": "12345678", "paymentMethodStatus": { "status": "STATUS_OK", "statusMessage": "Status message" } } ] } }, "presentationOptions": { "actionDisplayName": "PLACE_ORDER" }, "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Pizza", "description": "A four cheese pizza.", "priceAttributes": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 8990000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true } ], "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "unitMeasure": { "measure": 1, "unit": "POUND" }, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "state": "ACTUAL", "name": "Item Price", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true } ], "note": "Extra pepperoni", "quantity": 1, "subOptions": [] } ] } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "priceAttributes": [ { "type": "SUBTOTAL", "name": "Subtotal", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true }, { "type": "DELIVERY", "name": "Delivery", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, { "type": "TAX", "name": "Tax", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 3780000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 15770000 }, "taxIncluded": true } ], "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", "note": "Sale event", "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CREATED", "userVisibleStatusLabel": "CREATED", "type": "FOOD", "returnsInfo": { "isReturnable": false, "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "city": "MOUNTAIN VIEW", "coordinates": { "latitude": 37.432524, "longitude": -122.098545 }, "phoneNumber": "+1 123-456-7890", "postalAddress": { "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "postalCode": "94043-1351", "recipients": [ "John Doe" ], "regionCode": "US" }, "zipCode": "94043-1351" }, "price": { "type": "REGULAR", "name": "Delivery Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, "fulfillmentContact": { "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson", "displayName": "John Johnson" } }, "purchaseLocationType": "ONLINE_PURCHASE" } } } } } }, "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/_actions_on_google", "lifespanCount": 99, "parameters": { "data": "{\"location\":{\"coordinates\":{\"latitude\":37.432524,\"longitude\":-122.098545},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}" } } ] }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TRANSACTION_DECISION", "inputValueData": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "userInfoOptions": { "userInfoProperties": [ "EMAIL" ] } }, "paymentParameters": { "merchantPaymentOption": { "defaultMerchantPaymentMethodId": "12345678", "managePaymentMethodUrl": "https://example.com/managePayment", "merchantPaymentMethod": [ { "paymentMethodDisplayInfo": { "paymentMethodDisplayName": "VISA **** 1234", "paymentType": "PAYMENT_CARD" }, "paymentMethodGroup": "Payment method group", "paymentMethodId": "12345678", "paymentMethodStatus": { "status": "STATUS_OK", "statusMessage": "Status message" } } ] } }, "presentationOptions": { "actionDisplayName": "PLACE_ORDER" }, "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Pizza", "description": "A four cheese pizza.", "priceAttributes": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 8990000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true } ], "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "unitMeasure": { "measure": 1, "unit": "POUND" }, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "state": "ACTUAL", "name": "Item Price", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true } ], "note": "Extra pepperoni", "quantity": 1, "subOptions": [] } ] } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "priceAttributes": [ { "type": "SUBTOTAL", "name": "Subtotal", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true }, { "type": "DELIVERY", "name": "Delivery", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, { "type": "TAX", "name": "Tax", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 3780000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 15770000 }, "taxIncluded": true } ], "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", "note": "Sale event", "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CREATED", "userVisibleStatusLabel": "CREATED", "type": "FOOD", "returnsInfo": { "isReturnable": false, "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "price": { "type": "REGULAR", "name": "Delivery Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, "fulfillmentContact": { "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson", "displayName": "John Johnson" } }, "purchaseLocationType": "ONLINE_PURCHASE" } } } } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction Decision Placeholder." } } ] } } } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\",\"location\":{\"coordinates\":{\"latitude\":37.421578499999995,\"longitude\":-122.0837816},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}}" }
El contenido del objeto tokenizationSpecification
será diferente para cada uno
la puerta de enlace de pago. En la siguiente tabla, se muestran los parámetros que usa cada puerta de enlace:
"parameters": { "gateway": "example", "gatewayMerchantId": "exampleGatewayMerchantId" }
"parameters": { "gateway": "aciworldwide", "gatewayMerchantId": "YOUR_ENTITY_ID" }
"parameters": { "gateway": "adyen", "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME" }
"parameters": { "gateway": "alfabank", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "bluemedia", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "bluesnap", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "braintree", "braintree:apiVersion": "v1", "braintree:sdkVersion": braintree.client.VERSION, "braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID", "braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY" }
"parameters": { "gateway": "chase", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ACCOUNT_NUMBER" }
"parameters": { "gateway": "checkoutltd", "gatewayMerchantId": "YOUR_PUBLIC_KEY" }
"parameters": { "gateway": "cloudpayments", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "cybersource", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "datatrans", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "ebanx", "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY" }
"parameters": { "gateway": "firstdata", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "globalpayments", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "gopay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "hitrustpay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "imsolutions", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "lyra", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "mpgs", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "moneymailru", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "newebpay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "nexi", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "creditcall", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "paysafe", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "payture", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "payu", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "przelewy24", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "rbkmoney", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "sberbank", "gatewayMerchantId": "YOUR_ORGANIZATION_NAME" }
"parameters": { "gateway": "square", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "stripe", "stripe:version": "2018-10-31", "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY" }
"parameters": { "gateway": "tappay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "tinkoff", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "uniteller", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "vantiv", "vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID", "vantiv:merchantOrderId": "YOUR_ORDER_ID", "vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID", "vantiv:merchantReportGroup": "*web" }
"parameters": { "gateway": "worldpay", "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID" }
"parameters": { "gateway": "yandexcheckout", "gatewayMerchantId": "YOUR_SHOP_ID" }
Maneja la decisión del usuario
Después de que Asistente completa el intent, le envía una solicitud a tu entrega
con el intent actions_intent_TRANSACTION_DECISION
con la respuesta del usuario a
la decisión de la transacción. Recibirás un
Argument
que contiene un TransactionDecisionValue. Este valor contendrá lo siguiente:
transactionDecision
: La decisión del usuario con respecto a la propuesta en el orden personalizado. Los valores posibles sonORDER_ACCEPTED
,ORDER_REJECTED
,DELIVERY_ADDRESS_UPDATED
,CART_CHANGE_REQUESTED
yUSER_CANNOT_TRANSACT
deliveryAddress
: Es una dirección de entrega actualizada, en caso de que el usuario cambió su dirección de entrega. En este caso, el valor detransactionDecision
seránDELIVERY_ADDRESS_UPDATED
.
Para manejar correctamente esta solicitud, declara un intent de Dialogflow que se active mediante
el evento actions_intent_TRANSACTION_DECISION
. Cuando se active, manéjalo en
tu entrega:
Node.js
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE'); if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') { console.log('Order accepted.'); const order = arg.order; }
Node.js
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE'); if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') { console.log('Order accepted.'); const order = arg.order; }
Java
// Check transaction decision value Argument transactionDecisionValue = request .getArgument("TRANSACTION_DECISION_VALUE"); Map<String, Object> extension = null; if (transactionDecisionValue != null) { extension = transactionDecisionValue.getExtension(); } String transactionDecision = null; if (extension != null) { transactionDecision = (String) extension.get("transactionDecision"); } ResponseBuilder responseBuilder = getResponseBuilder(request); if ((transactionDecision != null && transactionDecision.equals("ORDER_ACCEPTED"))) { OrderV3 order = ((OrderV3) extension.get("order")); }
Java
// Check transaction decision value Argument transactionDecisionValue = request .getArgument("TRANSACTION_DECISION_VALUE"); Map<String, Object> extension = null; if (transactionDecisionValue != null) { extension = transactionDecisionValue.getExtension(); } String transactionDecision = null; if (extension != null) { transactionDecision = (String) extension.get("transactionDecision"); } ResponseBuilder responseBuilder = getResponseBuilder(request); if ((transactionDecision != null && transactionDecision.equals("ORDER_ACCEPTED"))) { OrderV3 order = ((OrderV3) extension.get("order")); }
JSON
{ "responseId": "aba44717-4236-4602-af55-e5ae1fc2d97a-594de0a7", "queryResult": { "queryText": "actions_intent_TRANSACTION_DECISION", "action": "transaction.decision.complete", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Failed to get transaction decision", "fulfillmentMessages": [ { "text": { "text": [ "Failed to get transaction decision" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/google_assistant_input_type_voice" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/_actions_on_google", "lifespanCount": 97, "parameters": { "data": "{\"location\":{\"coordinates\":{\"latitude\":37.432524,\"longitude\":-122.098545},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"}}" } }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_transaction_decision", "parameters": { "TRANSACTION_DECISION_VALUE": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue", "transactionDecision": "ORDER_ACCEPTED", "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Pizza", "description": "A four cheese pizza.", "priceAttributes": [ { "type": "REGULAR", "name": "Line Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 8990000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true } ], "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "unitMeasure": { "measure": 1, "unit": "POUND" }, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "state": "ACTUAL", "name": "Item Price", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true } ], "note": "Extra pepperoni", "quantity": 1, "subOptions": [] } ] } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "priceAttributes": [ { "type": "SUBTOTAL", "name": "Subtotal", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true }, { "type": "DELIVERY", "name": "Delivery", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, { "type": "TAX", "name": "Tax", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 3780000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 15770000 }, "taxIncluded": true } ], "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": "www.example.com", "note": "Sale event", "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CREATED", "userVisibleStatusLabel": "CREATED", "type": "FOOD", "returnsInfo": { "isReturnable": false, "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": {}, "price": { "type": "REGULAR", "name": "Delivery Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, "fulfillmentContact": { "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson", "displayName": "John Johnson" } }, "purchaseLocationType": "ONLINE_PURCHASE" } } }, "text": "" } } ], "intent": { "name": "projects/df-transactions/agent/intents/fd16d86b-60db-4d19-a683-5b52a22f4795", "displayName": "Transaction Decision Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:32Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[\"merchant_payment\"]" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_DECISION", "rawInputs": [ { "inputType": "KEYBOARD" } ], "arguments": [ { "name": "TRANSACTION_DECISION_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue", "transactionDecision": "ORDER_ACCEPTED", "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T19:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Pizza", "description": "A four cheese pizza.", "priceAttributes": [ { "type": "REGULAR", "name": "Line Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 8990000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true } ], "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "unitMeasure": { "measure": 1, "unit": "POUND" }, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "state": "ACTUAL", "name": "Item Price", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 1000000 }, "taxIncluded": true } ], "note": "Extra pepperoni", "quantity": 1, "subOptions": [] } ] } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "priceAttributes": [ { "type": "SUBTOTAL", "name": "Subtotal", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 9990000 }, "taxIncluded": true }, { "type": "DELIVERY", "name": "Delivery", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, { "type": "TAX", "name": "Tax", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 3780000 }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": 15770000 }, "taxIncluded": true } ], "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": "www.example.com", "note": "Sale event", "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CREATED", "userVisibleStatusLabel": "CREATED", "type": "FOOD", "returnsInfo": { "isReturnable": false, "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": {}, "price": { "type": "REGULAR", "name": "Delivery Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": 2000000 }, "taxIncluded": true }, "fulfillmentContact": { "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson", "displayName": "John Johnson" } }, "purchaseLocationType": "ONLINE_PURCHASE" } } } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:57:31Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\",\"location\":{\"coordinates\":{\"latitude\":37.421578499999995,\"longitude\":-122.0837816},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}}" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_DECISION", "rawInputs": [ {} ], "arguments": [ { "name": "TRANSACTION_DECISION_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue", "transactionDecision": "ORDER_ACCEPTED", "order": { "googleOrderId": "05528125187071048269", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "buyerInfo": { "email": "janedoe@example.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Pizza", "priceAttributes": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "8990000" }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "9990000" }, "taxIncluded": true } ], "description": "A four cheese pizza.", "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "1000000" }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "1000000" }, "taxIncluded": true } ], "note": "Extra pepperoni", "quantity": 1 } ], "unitMeasure": { "measure": 1, "unit": "POUND" } }, "vertical": { "@type": "type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseItemExtension", "quantity": 1, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "1000000" }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "1000000" }, "taxIncluded": true } ], "note": "Extra pepperoni", "quantity": 1 } ], "unitMeasure": { "measure": 1, "unit": "POUND" } } } ] }, "priceAttributes": [ { "type": "SUBTOTAL", "name": "Subtotal", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": "9990000" }, "taxIncluded": true }, { "type": "DELIVERY", "name": "Delivery", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "2000000" }, "taxIncluded": true }, { "type": "TAX", "name": "Tax", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": "3780000" }, "taxIncluded": true }, { "type": "TOTAL", "name": "Total Price", "state": "ESTIMATE", "amount": { "currencyCode": "USD", "amountInMicros": "15770000" }, "taxIncluded": true } ], "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", "note": "Sale event", "paymentData": { "paymentResult": { "merchantPaymentMethodId": "12345678" }, "paymentInfo": { "paymentMethodDisplayInfo": { "paymentType": "PAYMENT_CARD", "paymentMethodDisplayName": "VISA **** 1234" }, "paymentMethodProvenance": "PAYMENT_METHOD_PROVENANCE_MERCHANT" } }, "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CREATED", "type": "FOOD", "returnsInfo": { "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "price": { "type": "REGULAR", "name": "Delivery Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "2000000" }, "taxIncluded": true }, "fulfillmentContact": { "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson", "displayName": "John Johnson" } }, "purchaseLocationType": "ONLINE_PURCHASE", "userVisibleStatusLabel": "CREATED" }, "vertical": { "@type": "type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseOrderExtension", "status": "CREATED", "type": "FOOD", "returnsInfo": { "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "price": { "type": "REGULAR", "name": "Delivery Price", "state": "ACTUAL", "amount": { "currencyCode": "USD", "amountInMicros": "2000000" }, "taxIncluded": true }, "fulfillmentContact": { "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson", "displayName": "John Johnson" } }, "purchaseLocationType": "ONLINE_PURCHASE", "userVisibleStatusLabel": "CREATED" } } } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] } ] }
4. Finalizar el pedido y enviar un recibo
Cuando el intent actions.intent.TRANSACTION_DECISION
se muestra con un
transactionDecision
de ORDER_ACCEPTED
, debes realizar de inmediato
el procesamiento es necesario para “confirmar” el orden (como mantenerlo en
tu propia base de datos y cobrar al usuario).
Puedes finalizar la conversación con esta respuesta, pero debes incluir una respuesta simple.
para mantener la conversación. Cuando proporcionas este orderUpdate
inicial,
el usuario verá una "tarjeta de recibo contraída" junto con el resto de tu respuesta.
Esta tarjeta replicará el recibo que el usuario encuentre en su Historial de pedidos.
Durante la confirmación del pedido, tu objeto de pedido puede incluir una userVisibleOrderId
que
es el ID que el usuario ve para el pedido. Puedes volver a usar tu merchantOrderId
para este campo.
Parte de OrderUpdate objeto deberá contener un acción de seguimiento que se manifiestan como botones de URL en la parte inferior de los detalles del pedido que que el usuario puede encontrar en el historial de pedidos del Asistente.
Entrega
Node.js
// Set lastUpdateTime and update status of order const order = arg.order; order.lastUpdateTime = '2019-09-24T19:00:00.877Z'; order.purchase.status = 'CONFIRMED'; order.purchase.userVisibleStatusLabel = 'Order confirmed'; // Send synchronous order update conv.ask(`Transaction completed! Your order` + ` ${conv.data.latestOrderId} is all set!`); conv.ask(new Suggestions('send order update')); conv.ask(new OrderUpdate({ type: 'SNAPSHOT', reason: 'Reason string', order: order, }));
Node.js
// Set lastUpdateTime and update status of order const order = arg.order; order.lastUpdateTime = '2019-09-24T19:00:00.877Z'; order.purchase.status = 'CONFIRMED'; order.purchase.userVisibleStatusLabel = 'Order confirmed'; // Send synchronous order update conv.ask(`Transaction completed! Your order ` + `${conv.data.latestOrderId} is all set!`); conv.ask(new Suggestions('send order update')); conv.ask(new OrderUpdate({ type: 'SNAPSHOT', reason: 'Reason string', order: order, }));
Java
OrderV3 order = ((OrderV3) extension.get("order")); order.setLastUpdateTime("2019-09-24T19:00:00.877Z"); // Update order status PurchaseOrderExtension purchaseOrderExtension = order.getPurchase(); purchaseOrderExtension.setStatus("CONFIRMED"); purchaseOrderExtension.setUserVisibleStatusLabel("Order confirmed"); order.setPurchase(purchaseOrderExtension); // Order update OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setType("SNAPSHOT") .setReason("Reason string") .setOrder(order); Map<String, Object> conversationData = request.getConversationData(); String orderId = (String) conversationData.get("latestOrderId"); responseBuilder .add("Transaction completed! Your order " + orderId + " is all set!") .addSuggestions(new String[] {"send order update"}) .add(new StructuredResponse().setOrderUpdateV3(orderUpdate));
Java
OrderV3 order = ((OrderV3) extension.get("order")); order.setLastUpdateTime("2019-09-24T19:00:00.877Z"); // Update order status PurchaseOrderExtension purchaseOrderExtension = order.getPurchase(); purchaseOrderExtension.setStatus("CONFIRMED"); purchaseOrderExtension.setUserVisibleStatusLabel("Order confirmed"); order.setPurchase(purchaseOrderExtension); // Order update OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setType("SNAPSHOT") .setReason("Reason string") .setOrder(order); Map<String, Object> conversationData = request.getConversationData(); String orderId = (String) conversationData.get("latestOrderId"); responseBuilder .add("Transaction completed! Your order " + orderId + " is all set!") .addSuggestions(new String[] {"send order update"}) .add(new StructuredResponse().setOrderUpdateV3(orderUpdate));
JSON
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! Your order undefined is all set!" } }, { "structuredResponse": { "orderUpdateV3": { "order": { "buyerInfo": { "displayName": "Jane Doe", "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe" }, "contents": { "lineItems": [ { "description": "A four cheese pizza.", "id": "LINE_ITEM_ID", "name": "Pizza", "notes": [ "Extra cheese." ], "priceAttributes": [ { "amount": { "amountInMicros": 8990000, "currencyCode": "USD" }, "name": "Line Item Price", "state": "ACTUAL", "taxIncluded": true, "type": "REGULAR" }, { "amount": { "amountInMicros": 9990000, "currencyCode": "USD"