Crea transacciones físicas con pagos administrados por el comercio (Dialogflow)

Esta guía te explicará el proceso de desarrollo de un proyecto de Actions que incorpore transacciones de bienes físicos mediante formas de pago administradas por tu sitio.

Flujo de transacción

Cuando tu proyecto de Acciones maneja transacciones físicas mediante pagos administrados por el comercio, usa el siguiente flujo:

  1. 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:
    1. 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.
    2. 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.
  2. Crea el orden: explícale al usuario “montaje de carrito” en la que eligen los artículos que quieren comprar.
  3. Realizar vinculación de cuentas: Para que el usuario pueda realizar un pago método que haya guardado con tu servicio, usa la vinculación de cuentas asociar su Cuenta de Google con su cuenta en tu servicio.
  4. 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.
  5. Finalizar el pedido y enviar el recibo: Una vez confirmado el pedido, actualiza en el seguimiento del inventario y en otros servicios de entrega para el usuario.
  6. 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:

  1. Crea un proyecto nuevo o importa uno existente.
  2. Navega a Implementar > Información del directorio.
  3. 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?".

  4. 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 a true. 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,
});

Configuración de acceso

Cuando uses tu propia forma de pago para cobrarle al usuario, te recomendamos vincular su Cuenta de Google con una cuenta que tenga con tu propio servicio para recuperar, presentar y cobrar las formas de pago almacenadas allí

Ofrecemos la vinculación de cuentas de OAuth 2.0. para satisfacer esta un requisito de seguridad. Te recomendamos que habilites el flujo de aserción de OAuth 2.0, ya que permite una experiencia del usuario muy optimizada.

Proporcionamos el intent actions.intent.SIGN_IN, que te permite solicitar lo siguiente: a un usuario vincular cuentas en medio de una conversación. Debes habilitar la vinculación de cuentas en la Consola de Actions para usar actions.intent.SIGN_IN.

Debes usar este intent si no puedes encontrar un accessToken en el Un objeto User en la solicitud de webhook. Esto significa que el usuario aún no ha vinculado su cuenta.

Después de solicitar el intent actions.intent.SIGN_IN, recibirás un Argument que contiene un SignInStatus con un valor de "OK", "CANCELLED" o "ERROR". Si el estado es "OK", deberías poder encontrar un accessToken en el objeto User.

Entrega

Solicitar acceso

Node.js

app.intent('Sign In', (conv) => {
  conv.ask(new SignIn('To get your account details'));
});

Node.js

conv.ask(new SignIn('To get your account details'));

Java

@ForIntent("Sign In")
public ActionResponse signIn(ActionRequest request) {
  return getResponseBuilder(request).add(
      new SignIn()
          .setContext("To get your account details"))
      .build();
}

Java

return getResponseBuilder(request).add(
    new SignIn()
        .setContext("To get your account details"))
    .build();

JSON

{
    "payload": {
      "google": {
        "expectUserResponse": true,
        "systemIntent": {
          "intent": "actions.intent.SIGN_IN",
          "data": {
            "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec",
            "optContext": "To get your account details"
          }
        }
      }
    }
  }

JSON

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.SIGN_IN",
          "inputValueData": {
            "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec",
            "optContext": "To get your account details"
          }
        }
      ]
    }
  ],
  "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}"
}
Recibir el resultado de acceso

Node.js

app.intent('Sign In Complete', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    conv.ask('You need to sign in before making a transaction.');
  } else {
    const accessToken = conv.user.access.token;
    // possibly do something with access token
    conv.ask('You must meet all the requirements necessary ' +
      'to make a transaction. Try saying ' +
      '"check transaction requirements".');
      conv.ask(new Suggestions(`check requirements`));
  }
});

Node.js

app.intent('actions.intent.SIGN_IN', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    conv.ask('You need to sign in before making a transaction.');
  } else {
    const accessToken = conv.user.access.token;
    // possibly do something with access token
    conv.ask('You must meet all the requirements necessary ' +
      'to make a transaction. Try saying ' +
      '"check transaction requirements".');
      conv.ask(new Suggestions(`check requirements`));
  }
});

Java

@ForIntent("Sign In Complete")
public ActionResponse signInComplete(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isSignInGranted()) {
    responseBuilder
        .add("You must meet all the requirements necessary to make a " +
            "transaction. Try saying \"check transaction requirements\".")
        .addSuggestions(new String[] {
            "check requirements"
        });
  } else {
    responseBuilder.add("You need to sign in before making a transaction.");
  }
  return responseBuilder.build();
}

Java

@ForIntent("actions.intent.SIGN_IN")
public ActionResponse signInComplete(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isSignInGranted()) {
    responseBuilder
        .add("You must meet all the requirements necessary to make a " +
            "transaction. Try saying \"check transaction requirements\".")
        .addSuggestions(new String[] {
            "check requirements"
        });
  } else {
    responseBuilder.add("You need to sign in before making a transaction.");
  }
  return responseBuilder.build();
}

JSON

{
    "responseId": "d2123d8d-3f00-466e-b5a9-1a4ed53a7cb7-594de0a7",
    "queryResult": {
      "queryText": "actions_intent_SIGN_IN",
      "parameters": {},
      "allRequiredParamsPresent": true,
      "fulfillmentMessages": [
        {
          "text": {
            "text": [
              ""
            ]
          }
        }
      ],
      "outputContexts": [
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/merchant_payment",
          "lifespanCount": 2
        },
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser"
        },
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_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_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/google_assistant_input_type_keyboard"
        },
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_sign_in",
          "parameters": {
            "SIGN_IN": {
              "@type": "type.googleapis.com/google.actions.v2.SignInValue",
              "status": "OK"
            },
            "text": ""
          }
        }
      ],
      "intent": {
        "name": "projects/df-transactions/agent/intents/105b925b-b186-4f5d-8bde-a9a782a0fa9f",
        "displayName": "Sign In Complete"
      },
      "intentDetectionConfidence": 1,
      "languageCode": "en"
    },
    "originalDetectIntentRequest": {
      "source": "google",
      "version": "2",
      "payload": {
        "user": {
          "locale": "en-US",
          "lastSeen": "2019-09-23T19:49:18Z",
          "userVerificationStatus": "VERIFIED"
        },
        "conversation": {
          "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy",
          "type": "ACTIVE",
          "conversationToken": "[]"
        },
        "inputs": [
          {
            "intent": "actions.intent.SIGN_IN",
            "rawInputs": [
              {
                "inputType": "KEYBOARD"
              }
            ],
            "arguments": [
              {
                "name": "SIGN_IN",
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.SignInValue",
                  "status": "OK"
                }
              },
              {
                "name": "text"
              }
            ]
          }
        ],
        "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:55:52Z",
    "userVerificationStatus": "VERIFIED"
  },
  "conversation": {
    "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw",
    "type": "ACTIVE",
    "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}"
  },
  "inputs": [
    {
      "intent": "actions.intent.SIGN_IN",
      "rawInputs": [
        {}
      ],
      "arguments": [
        {
          "name": "SIGN_IN",
          "extension": {
            "@type": "type.googleapis.com/google.actions.v2.SignInValue",
            "status": "OK"
          }
        },
        {
          "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"
        }
      ]
    }
  ]
}

1. Recopila información (opcional)

1a. Valida los requisitos de las transacciones (opcional).

Experiencia del usuario

Activa el intent actions.intent.TRANSACTION_REQUIREMENTS_CHECK para que haga lo siguiente: verificar rápidamente si los usuarios podrán realizar o no una transacción. Esta garantizará que los usuarios puedan continuar y les dará la oportunidad de corregir cualquier configuración. lo que evita que completen 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, lo que garantizará puede continuar y darle la oportunidad de corregir cualquier parámetro de 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 que solo usa 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 con el 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,
        "systemIntent": {
          "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK",
          "data": {
            "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec"
          }
        }
      }
    }
  }

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\":\"merchant_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 activa con 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 como lineItems.
  • 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. Realizar la vinculación de cuentas

Cuando uses tu propia forma de pago para cobrarle al usuario, te recomendamos vincular su Cuenta de Google con una cuenta que tenga con tu propio servicio para recuperar, presentar y cobrar las formas de pago almacenadas allí

Ofrecemos la vinculación de cuentas de OAuth 2.0. para satisfacer esta un requisito de seguridad. Te recomendamos que habilites el flujo de aserción de OAuth 2.0, ya que permite una experiencia del usuario muy optimizada.

Proporcionamos el intent actions.intent.SIGN_IN, que te permite solicitar lo siguiente: a un usuario vincular cuentas en medio de una conversación. Debes habilitar la vinculación de cuentas en la Consola de Actions para usar actions.intent.SIGN_IN.

Debes usar este intent si no puedes encontrar un accessToken en el Un objeto User en la solicitud de webhook. Esto significa que el usuario aún no ha vinculado su cuenta.

Después de solicitar el intent actions.intent.SIGN_IN, recibirás un Argument que contiene un SignInStatus con un valor de "OK", "CANCELLED" o "ERROR". Si el estado es "OK", deberías poder encontrar un accessToken en el objeto User.

Entrega

Solicitar acceso

Node.js

app.intent('Sign In', (conv) => {
  conv.ask(new SignIn('To get your account details'));
});

Node.js

conv.ask(new SignIn('To get your account details'));

Java

@ForIntent("Sign In")
public ActionResponse signIn(ActionRequest request) {
  return getResponseBuilder(request).add(
      new SignIn()
          .setContext("To get your account details"))
      .build();
}

Java

return getResponseBuilder(request).add(
    new SignIn()
        .setContext("To get your account details"))
    .build();

JSON

{
    "payload": {
      "google": {
        "expectUserResponse": true,
        "systemIntent": {
          "intent": "actions.intent.SIGN_IN",
          "data": {
            "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec",
            "optContext": "To get your account details"
          }
        }
      }
    }
  }

JSON

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.SIGN_IN",
          "inputValueData": {
            "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec",
            "optContext": "To get your account details"
          }
        }
      ]
    }
  ],
  "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}"
}
Recibir el resultado de acceso

Node.js

app.intent('Sign In Complete', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    conv.ask('You need to sign in before making a transaction.');
  } else {
    const accessToken = conv.user.access.token;
    // possibly do something with access token
    conv.ask('You must meet all the requirements necessary ' +
      'to make a transaction. Try saying ' +
      '"check transaction requirements".');
      conv.ask(new Suggestions(`check requirements`));
  }
});

Node.js

app.intent('actions.intent.SIGN_IN', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    conv.ask('You need to sign in before making a transaction.');
  } else {
    const accessToken = conv.user.access.token;
    // possibly do something with access token
    conv.ask('You must meet all the requirements necessary ' +
      'to make a transaction. Try saying ' +
      '"check transaction requirements".');
      conv.ask(new Suggestions(`check requirements`));
  }
});

Java

@ForIntent("Sign In Complete")
public ActionResponse signInComplete(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isSignInGranted()) {
    responseBuilder
        .add("You must meet all the requirements necessary to make a " +
            "transaction. Try saying \"check transaction requirements\".")
        .addSuggestions(new String[] {
            "check requirements"
        });
  } else {
    responseBuilder.add("You need to sign in before making a transaction.");
  }
  return responseBuilder.build();
}

Java

@ForIntent("actions.intent.SIGN_IN")
public ActionResponse signInComplete(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isSignInGranted()) {
    responseBuilder
        .add("You must meet all the requirements necessary to make a " +
            "transaction. Try saying \"check transaction requirements\".")
        .addSuggestions(new String[] {
            "check requirements"
        });
  } else {
    responseBuilder.add("You need to sign in before making a transaction.");
  }
  return responseBuilder.build();
}

JSON

{
    "responseId": "d2123d8d-3f00-466e-b5a9-1a4ed53a7cb7-594de0a7",
    "queryResult": {
      "queryText": "actions_intent_SIGN_IN",
      "parameters": {},
      "allRequiredParamsPresent": true,
      "fulfillmentMessages": [
        {
          "text": {
            "text": [
              ""
            ]
          }
        }
      ],
      "outputContexts": [
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/merchant_payment",
          "lifespanCount": 2
        },
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser"
        },
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_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_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/google_assistant_input_type_keyboard"
        },
        {
          "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_sign_in",
          "parameters": {
            "SIGN_IN": {
              "@type": "type.googleapis.com/google.actions.v2.SignInValue",
              "status": "OK"
            },
            "text": ""
          }
        }
      ],
      "intent": {
        "name": "projects/df-transactions/agent/intents/105b925b-b186-4f5d-8bde-a9a782a0fa9f",
        "displayName": "Sign In Complete"
      },
      "intentDetectionConfidence": 1,
      "languageCode": "en"
    },
    "originalDetectIntentRequest": {
      "source": "google",
      "version": "2",
      "payload": {
        "user": {
          "locale": "en-US",
          "lastSeen": "2019-09-23T19:49:18Z",
          "userVerificationStatus": "VERIFIED"
        },
        "conversation": {
          "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy",
          "type": "ACTIVE",
          "conversationToken": "[]"
        },
        "inputs": [
          {
            "intent": "actions.intent.SIGN_IN",
            "rawInputs": [
              {
                "inputType": "KEYBOARD"
              }
            ],
            "arguments": [
              {
                "name": "SIGN_IN",
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.SignInValue",
                  "status": "OK"
                }
              },
              {
                "name": "text"
              }
            ]
          }
        ],
        "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:55:52Z",
    "userVerificationStatus": "VERIFIED"
  },
  "conversation": {
    "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw",
    "type": "ACTIVE",
    "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}"
  },
  "inputs": [
    {
      "intent": "actions.intent.SIGN_IN",
      "rawInputs": [
        {}
      ],
      "arguments": [
        {
          "name": "SIGN_IN",
          "extension": {
            "@type": "type.googleapis.com/google.actions.v2.SignInValue",
            "status": "OK"
          }
        },
        {
          "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"
        }
      ]
    }
  ]
}

4. Proponer el pedido

Una vez que hayas creado un pedido, debes presentarlo al usuario para confirmarlo o rechazar. Solicita el actions.intent.TRANSACTION_DECISION intención y proporcionan el orden que creaste con el pago almacenado del usuario información.

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 paymentParameters incluye un merchantPaymentOption con campos que describen la descripción forma de pago.

El siguiente código muestra un ejemplo de TransactionsDecision para un pedido, pagado con una tarjeta de crédito Visa:

Node.js

conv.ask(new TransactionDecision({
  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: order,
}));

Node.js

conv.ask(new TransactionDecision({
  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: 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
MerchantPaymentMethod merchantPaymentMethod = new MerchantPaymentMethod()
    .setPaymentMethodDisplayInfo(new PaymentMethodDisplayInfo()
        .setPaymentMethodDisplayName("VISA **** 1234")
        .setPaymentType("PAYMENT_CARD"))
    .setPaymentMethodGroup("Payment method group")
    .setPaymentMethodId("12345678")
    .setPaymentMethodStatus(new PaymentMethodStatus()
        .setStatus("STATUS_OK")
        .setStatusMessage("Status message"));

MerchantPaymentOption merchantPaymentOption = new MerchantPaymentOption()
    .setDefaultMerchantPaymentMethodId("12345678")
    .setManagePaymentMethodUrl("https://example.com/managePayment")
    .setMerchantPaymentMethod(Collections.singletonList(merchantPaymentMethod));

paymentParameters.setMerchantPaymentOption(merchantPaymentOption);

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
MerchantPaymentMethod merchantPaymentMethod = new MerchantPaymentMethod()
    .setPaymentMethodDisplayInfo(new PaymentMethodDisplayInfo()
        .setPaymentMethodDisplayName("VISA **** 1234")
        .setPaymentType("PAYMENT_CARD"))
    .setPaymentMethodGroup("Payment method group")
    .setPaymentMethodId("12345678")
    .setPaymentMethodStatus(new PaymentMethodStatus()
        .setStatus("STATUS_OK")
        .setStatusMessage("Status message"));

MerchantPaymentOption merchantPaymentOption = new MerchantPaymentOption()
    .setDefaultMerchantPaymentMethodId("12345678")
    .setManagePaymentMethodUrl("https://example.com/managePayment")
    .setMerchantPaymentMethod(Collections.singletonList(merchantPaymentMethod));

paymentParameters.setMerchantPaymentOption(merchantPaymentOption);

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\"}}"
}

Controla 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 son ORDER_ACCEPTED, ORDER_REJECTED, DELIVERY_ADDRESS_UPDATED, CART_CHANGE_REQUESTED y USER_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 de transactionDecision serán DELIVERY_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"
              },