Crea transacciones físicas con Google Pay

En esta guía, se explica el proceso de desarrollo de un proyecto de Acciones que incorpore transacciones de bienes físicos y use Google Pay para los pagos.

Flujo de transacciones

Cuando tu proyecto de Acciones controla transacciones físicas con pagos administrados por comercios, usa el siguiente flujo:

  1. Recopilar información (opcional): Según la naturaleza de la transacción, es posible que desees recopilar la siguiente información del usuario al comienzo de la conversación:
    1. Valida los requisitos de las transacciones: Al comienzo de la conversación, verifica que el usuario cumpla con los requisitos para realizar una transacción, como tener la información de pago configurada correctamente y disponible antes de crear el carrito.
    2. Solicita una dirección de entrega: Si la transacción requiere una dirección de entrega, recopila una del usuario.
  2. Crea el pedido: Guía al usuario a través de un "ensamblaje del carrito" en el que elige los artículos que desea comprar.
  3. Proponer el pedido: Una vez que el carrito esté completo, propón el pedido al usuario para que pueda confirmar que es correcto. Si se confirma el pedido, recibirás una respuesta con los detalles del pedido y un token de pago.
  4. Finalizar el pedido y enviar un recibo: Una vez confirmado el pedido, actualiza el seguimiento de inventario o algún otro servicio de entrega y, luego, envía una confirmación al usuario.
  5. Enviar actualizaciones de pedidos: Durante el transcurso de la vida útil de la entrega del pedido, envía solicitudes PATCH a la API de pedidos para proporcionar al usuario actualizaciones del pedido.

Restricciones y lineamientos para la revisión

Ten en cuenta que se aplican políticas adicionales a las Acciones con transacciones. La revisión de las Acciones con transacciones puede tardar hasta seis semanas, por lo que te recomendamos que tengas 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 la acción a revisión.

Solo puedes implementar Acciones que vendan bienes físicos en los siguientes países:

Australia
Brasil
Canadá
Indonesia
Japón
México
Rusia
Singapur
Tailandia
Turquía
Reino Unido
Estados Unidos

Cómo compilar un proyecto

Si deseas ver una amplia variedad de ejemplos de conversaciones transaccionales, consulta la muestra de transacciones de Node.js.

Configuración

Cuando creas tu acción, debes especificar que deseas realizar transacciones en la Consola de Actions.

Para configurar tu proyecto y la entrega, haz lo siguiente:

  1. Crea un proyecto nuevo o importa uno existente.
  2. Ve a Implementar > Información del directorio.
  3. En Información adicional > Transacciones > marca la casilla que dice “¿Tus acciones usan la API de transacciones para realizar transacciones de bienes físicos?”.

1. Recopila información (opcional)

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

En cuanto el usuario indique que desea realizar una compra, debes verificar que pueda realizarla. Por ejemplo, cuando se invoca, tu Acción podría preguntar: "¿Te gustaría pedir zapatos o revisar el saldo de tu cuenta?" Si el usuario dice "pedir calzado", debes asegurarte de que pueda continuar y darle la oportunidad de corregir cualquier configuración que impida continuar con la transacción. Para hacerlo, debes hacer la transición a una escena que realice una verificación de requisitos de la transacción.

Crea una escena de verificación de requisitos para las transacciones
  1. En la pestaña Scenes, agrega una nueva escena con el nombre TransactionRequirementsCheck.
  2. En Relleno de ranuras, haz clic en + para agregar un espacio nuevo.
  3. En Select type, selecciona actions.type.TransactionRequirementsCheckResult como el tipo de ranura.
  4. En el campo del nombre del espacio, asígnale el nombre TransactionRequirementsCheck.
  5. Habilita la casilla de verificación Customize slot value writeback (habilitada de forma predeterminada).
  6. Haz clic en Guardar.

Una verificación de requisitos de la transacción dará como resultado uno de los siguientes resultados:

  • Si se cumplen los requisitos, el parámetro de sesión se establece con una condición de éxito y puedes continuar con la creación del pedido del usuario.
  • Si no se pueden cumplir uno o más de los requisitos, el parámetro de sesión se establece con una condición de falla. En este caso, debes alejar la conversación de la experiencia transaccional o finalizar la conversación.
    • Si el usuario puede corregir los errores que generan el estado de falla, se le solicitará que resuelvan esos problemas en el dispositivo. Si la conversación se realiza en una superficie solo de voz, se iniciará una transferencia en el teléfono del usuario.

Controla el resultado de la verificación de requisitos de la transacción

  1. En la pestaña Scenes, selecciona la escena TransactionRequirementsCheck que acabas de crear.
  2. En Condición, haz clic en + para agregar una condición nueva.
  3. En el campo de texto, ingresa la siguiente sintaxis de condición para verificar la condición de éxito:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. Coloca el cursor sobre la condición que acabas de agregar y haz clic en la flecha hacia arriba para colocarla antes de if scene.slots.status == "FINAL".

  5. Habilita Send prompts y proporciona un mensaje simple que informe al usuario que está listo para realizar una transacción:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                You are ready to purchase physical goods.
    
  6. En Transition, selecciona otra escena para que el usuario continúe la conversación y realice una transacción.

  7. Selecciona la condición else if scene.slots.status == "FINAL".

  8. Habilita Send prompts y proporciona un mensaje simple para informar al usuario que no puede realizar una transacción:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. En Transición, selecciona Finalizar conversación para finalizar la conversación si un usuario no puede realizar transacciones.

Solicita una dirección de entrega

Si tu transacción requiere la dirección de entrega de un usuario, debes solicitárselo. Esto puede ser útil para determinar el precio total o la ubicación de entrega o retiro, o para asegurarte de que el usuario se encuentre dentro de tu región de servicio. Para hacerlo, debes realizar una transición a una escena que le solicite al usuario su dirección de entrega.

Crea la escena de la dirección de entrega

  1. En la pestaña Scenes, agrega una escena nueva con el nombre DeliveryAddress.
  2. En Relleno de ranuras, haz clic en + para agregar un espacio nuevo.
  3. En Select type, selecciona actions.type.DeliveryAddressValue como el tipo de ranura.
  4. En el campo del nombre del espacio, asígnale el nombre TransactionDeliveryAddress.
  5. Habilita la casilla de verificación Customize slot value writeback (habilitada de forma predeterminada).
  6. Haz clic en Save (Guardar).

Cuando configuras la ranura, puedes proporcionar un reason que te permita anteponer la solicitud de Asistente para obtener una dirección con una string.La string del motivo predeterminado es "saber a dónde enviar el pedido". Por lo tanto, Asistente podría preguntarle al usuario: "Para saber a dónde enviar el pedido, necesitaré tu dirección de entrega".

  • En las plataformas que tienen pantalla, el usuario elegirá la dirección que desea usar para la transacción. Si no proporcionó una dirección antes, podrá ingresar una nueva.
  • En plataformas solo de voz, Asistente le pedirá permiso al usuario para compartir su dirección predeterminada de la transacción. Si no proporcionó una dirección antes, la conversación se entregará a un teléfono para que pueda ingresar.

Para administrar el resultado de la dirección de entrega, sigue estos pasos:

  1. En la pestaña Scenes, selecciona la escena DeliveryAddress que acabas de crear.
  2. En Condición, haz clic en + para agregar una condición nueva.
  3. En el campo de texto, ingresa la siguiente sintaxis de condición para verificar la condición de éxito:

    scene.slots.status == "FINAL" && session.params.TransactionDeliveryAddress.userDecision == "ACCEPTED"
    
  4. Coloca el cursor sobre la condición que acabas de agregar y haz clic en la flecha hacia arriba para colocarla antes de if scene.slots.status == "FINAL".

  5. Habilita Send prompts y proporciona un mensaje simple para que el usuario sepa que recibiste su dirección:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Great! Your order will be delivered to
                $session.params.TransactionDeliveryAddress.location.postalAddress.locality
                $session.params.TransactionDeliveryAddress.location.postalAddress.administrativeArea
                $session.params.TransactionDeliveryAddress.location.postalAddress.regionCode
                $session.params.TransactionDeliveryAddress.location.postalAddress.postalCode
    
  6. En Transition, selecciona otra escena para que el usuario continúe con la conversación.

  7. Selecciona la condición else if scene.slots.status == "FINAL".

  8. Habilita Send prompts y proporciona un mensaje simple para informar al usuario que no puede realizar una transacción:

    candidates:
      - first_simple:
          variants:
            - speech: I failed to get your delivery address.
    
  9. En Transición, selecciona Finalizar conversación para finalizar la conversación si un usuario no puede realizar transacciones.

Arma el pedido

Una vez que tengas la información del usuario que necesitas, compilarás una experiencia de "ensamblaje del carrito" que guíe al usuario para crear un pedido. Cada acción tendrá un flujo de ensamblaje del carrito ligeramente diferente según corresponda para su producto o servicio.

En la experiencia de ensamblaje del carrito más básica, el usuario puede elegir elementos de una lista para agregar a su pedido, aunque puedes diseñar la conversación para simplificar la experiencia del usuario. Podrías crear una experiencia de armado del carrito que le permita al usuario volver a pedir su compra más reciente a través de una simple pregunta de sí o no. También puedes presentar al usuario un carrusel o una tarjeta de lista con los elementos principales "destacados" o "recomendados".

Recomendamos usar respuestas enriquecidas para presentar las opciones del usuario de forma visual, pero también diseñar la conversación de modo que el usuario pueda crear su carrito solo con su voz. Para obtener algunas prácticas recomendadas y ejemplos de experiencias de ensamblaje de carritos de alta calidad, consulta los Lineamientos de diseño.

Crea un pedido

A lo largo de la conversación, deberás recopilar los elementos que un usuario desea comprar y, luego, construir 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: Es información sobre el comercio que facilitó el pedido.
  • contents: Es el contenido real del pedido que aparece como lineItems.
  • priceAttributes: Son los detalles de precios del pedido, incluido su costo total con impuestos y descuentos.

Consulta la documentación de respuesta de Order para crear tu carrito. Ten en cuenta que es posible que debas incluir diferentes campos según el orden.

El código de muestra que aparece a continuación presenta un orden completo, incluidos los campos opcionales:

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',
  },
};

Crear opciones de orden y presentación

Antes de que el usuario confirme su pedido, se le presentará una tarjeta de pedido propuesta. Puedes personalizar la forma en que se presenta esta tarjeta al usuario si configuras varias opciones de orden y presentación.

A continuación, se muestran las opciones de pedido y presentación para realizar un pedido que requiere una dirección de entrega, incluido el correo electrónico del usuario en la tarjeta de confirmación del pedido:

const orderOptions = {
      'requestDeliveryAddress': true,
      'userInfoOptions': {
        'userInfoProperties': ['EMAIL']
      }
    };

const presentationOptions = {
      'actionDisplayName': 'PLACE_ORDER'
    };

Cómo crear parámetros de pago

El objeto paymentParameters incluirá parámetros de asignación de token que cambian según el procesador de Google Pay que planees usar (como Stripe, Braintree, ACI, etcétera).

const paymentParamenters = {
      'googlePaymentOption': {
        // facilitationSpec is expected to be a serialized JSON string
        'facilitationSpec': JSON.stringify({
          'apiVersion': 2,
          'apiVersionMinor': 0,
          'merchantInfo': {
            'merchantName': 'Example Merchant',
          },
          'allowedPaymentMethods': [
            {
              'type': 'CARD',
              'parameters': {
                'allowedAuthMethods': ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
                'allowedCardNetworks': [
                  'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'],
              },
              'tokenizationSpecification': {
                'type': 'PAYMENT_GATEWAY',
                'parameters': {
                  'gateway': 'example',
                  'gatewayMerchantId': 'exampleGatewayMerchantId',
                },
              },
            },
          ],
          'transactionInfo': {
            'totalPriceStatus': 'FINAL',
            'totalPrice': '15.77',
            'currencyCode': 'USD',
          },
        }),
      },
    };

El contenido del objeto tokenizationSpecification será diferente para cada puerta de enlace de pago. En la siguiente tabla, se muestran los parámetros que usa cada puerta de enlace:

EJEMPLO
"parameters": {
  "gateway": "example",
  "gatewayMerchantId": "exampleGatewayMerchantId"
}
ACI
"parameters": {
  "gateway": "aciworldwide",
  "gatewayMerchantId": "YOUR_ENTITY_ID"
}
ADYEN
"parameters": {
  "gateway": "adyen",
  "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"
}
ALFA-BANCO
"parameters": {
  "gateway": "alfabank",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUE_MEDIA
"parameters": {
  "gateway": "bluemedia",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUESNAP
"parameters": {
  "gateway": "bluesnap",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BRAINTREE
"parameters": {
  "gateway": "braintree",
  "braintree:apiVersion": "v1",
  "braintree:sdkVersion": braintree.client.VERSION,
  "braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID",
  "braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY"
}
CHASE_PAYMENTECH
"parameters": {
  "gateway": "chase",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ACCOUNT_NUMBER"
}
CONFIRMAR LA COMPRA
"parameters": {
  "gateway": "checkoutltd",
  "gatewayMerchantId": "YOUR_PUBLIC_KEY"
}
CLOUDPAYMENTS
"parameters": {
  "gateway": "cloudpayments",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
CYBERSOURCE
"parameters": {
  "gateway": "cybersource",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
DATATRANS
"parameters": {
  "gateway": "datatrans",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
EBANX
"parameters": {
  "gateway": "ebanx",
  "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY"
}
FIRST_DATA
"parameters": {
  "gateway": "firstdata",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
GLOBAL_PAYMENTS
"parameters": {
  "gateway": "globalpayments",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
GOPAY
"parameters": {
  "gateway": "gopay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
HITRUST
"parameters": {
  "gateway": "hitrustpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
IMSOLUCIONES
"parameters": {
  "gateway": "imsolutions",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
LYRA
"parameters": {
  "gateway": "lyra",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
MPGS
"parameters": {
  "gateway": "mpgs",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
dine_bursátil_RU
"parameters": {
  "gateway": "moneymailru",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NEWEBPAY
"parameters": {
  "gateway": "newebpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NEXI
"parameters": {
  "gateway": "nexi",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NMI
"parameters": {
  "gateway": "creditcall",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYSAFE
"parameters": {
  "gateway": "paysafe",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAGO
"parameters": {
  "gateway": "payture",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYU
"parameters": {
  "gateway": "payu",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PRZELEWY24
"parameters": {
  "gateway": "przelewy24",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
RBKMoney
"parameters": {
  "gateway": "rbkmoney",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
SBERBANK
"parameters": {
  "gateway": "sberbank",
  "gatewayMerchantId": "YOUR_ORGANIZATION_NAME"
}
SQUARE
"parameters": {
  "gateway": "square",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
FRAGMENTO
"parameters": {
  "gateway": "stripe",
  "stripe:version": "2018-10-31",
  "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY"
}
TAPPAY
"parameters": {
  "gateway": "tappay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
TINKOFF
"parameters": {
  "gateway": "tinkoff",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
UNITELLER
"parameters": {
  "gateway": "uniteller",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
VANTIV
"parameters": {
  "gateway": "vantiv",
  "vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID",
  "vantiv:merchantOrderId": "YOUR_ORDER_ID",
  "vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID",
  "vantiv:merchantReportGroup": "*web"
}
WORLDPAY
"parameters": {
  "gateway": "worldpay",
  "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"
}
YANDEX
"parameters": {
  "gateway": "yandexcheckout",
  "gatewayMerchantId": "YOUR_SHOP_ID"
}

Parámetro de guardar datos del pedido en la sesión

Desde tu entrega, guarda los datos del pedido en un parámetro de sesión. El objeto de orden se utilizará en todas las escenas de la misma sesión.

conv.session.params.order = {
    '@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
    order: order,
    orderOptions: orderOptions,
    presentationOptions: presentationOptions,
    paymentParameters: paymentParameters
};

Proponer el orden

Una vez que hayas creado un pedido, debes presentárselo al usuario para confirmarlo o rechazarlo. Para hacerlo, debes realizar la transición a una escena en la que se realice una decisión sobre la transacción.

Crea una escena de decisión de transacciones

  1. En la pestaña Scenes, agrega una escena nueva con el nombre TransactionDecision.
  2. En Relleno de ranuras, haz clic en + para agregar un espacio nuevo.
  3. En Seleccionar tipo, selecciona actions.type.TransactionDecisionValue como el tipo de ranura.
  4. En el campo del nombre del espacio, asígnale el nombre TransactionDecision.
  5. Habilita la casilla de verificación Customize slot value writeback (habilitada de forma predeterminada).
  6. En Configurar espacio, selecciona Usar parámetro de sesión en el menú desplegable.
  7. En Configurar espacio, ingresa el nombre del parámetro de sesión que se usa para almacenar el pedido en el campo de texto (es decir, $session.params.order).
  8. Haz clic en Save (Guardar).

Para intentar llenar un espacio de TransactionDecisionValue, 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, cambiar una opción de pago (como la tarjeta de crédito o la dirección) o solicitar que se cambie el contenido del pedido.

En este momento, 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 pedido después de finalizar la experiencia de ensamblaje del carrito.

Controla el resultado de la decisión de transacción

Cuando se llene un espacio TransactionDecisionValue, la respuesta del usuario a la decisión sobre la transacción se almacenará en un parámetro de sesión. Este valor contiene lo siguiente:

  • ORDER_ACCEPTED,
  • ORDER_REJECTED,
  • DELIVERY_ADDRESS_UPDATED,
  • CART_CHANGE_REQUESTED
  • USER_CANNOT_TRANSACT.

Para administrar un resultado de decisión de transacción, haz lo siguiente:

  1. En la pestaña Scenes, selecciona la escena TransactionDecision que acabas de crear.
  2. En Condición, haz clic en + para agregar una condición nueva.
  3. En el campo de texto, ingrese la siguiente sintaxis de condición para verificar la condición de éxito:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. Coloca el cursor sobre la condición que acabas de agregar y haz clic en la flecha hacia arriba para colocarla antes de if scene.slots.status == "FINAL".

  5. Habilita Send prompts y proporciona un mensaje simple para informar al usuario que se completó el pedido:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your order
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. En Transición, selecciona Finalizar conversación.

  7. En Condición, haz clic en + para agregar una condición nueva.

  8. En el campo de texto, ingresa la siguiente sintaxis de condición para verificar las condiciones de falla:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. Coloca el cursor sobre la condición que acabas de agregar y haz clic en la flecha hacia arriba para colocarla antes de if scene.slots.status == "FINAL".

  10. Habilita Send prompts y proporciona un mensaje simple para informar al usuario que se rechazó el pedido:

    candidates:
      - first_simple:
          variants:
            - speech: Look like you don't want to order anything. Goodbye.
    
  11. En Transición, selecciona Finalizar conversación.

  12. Selecciona la condición else if scene.slots.status == "FINAL".

  13. Habilita Send prompts y proporciona un mensaje simple para que el usuario sepa que no puede realizar una transacción:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. En Transición, selecciona Finalizar conversación para finalizar la conversación si un usuario no puede realizar transacciones.

Finaliza el pedido y envía un recibo

Cuando la ranura TransactionDecisionValue muestra un resultado de ORDER_ACCEPTED, debes realizar de inmediato el procesamiento necesario para “confirmar” el pedido (como conservarlo en tu propia base de datos y cobrar al usuario).

Puedes finalizar la conversación con esta respuesta, pero debes incluir una respuesta simple para mantener la conversación. Cuando proporciones esta orderUpdate inicial, el usuario verá una "tarjeta de recibo contraída" junto con el resto de la respuesta. Esta tarjeta duplicará el recibo que el usuario encuentre en su Historial de pedidos.

Durante la confirmación del pedido, tu objeto de pedido puede incluir un userVisibleOrderId, que es el ID que el usuario ve para el pedido. Puedes volver a usar merchantOrderId para este campo.

Parte del objeto OrderUpdate deberá contener un objeto de acción de seguimiento, que se manifiesta como botones de URL en la parte inferior de los detalles del pedido que el usuario puede encontrar en su Historial de pedidos de Asistente.

  • Debes proporcionar, como mínimo, una acción de seguimiento VIEW_DETAILS con cada pedido. Debe contener un vínculo directo a la representación del pedido en tu sitio web o app para dispositivos móviles.
  • También debes enviar un recibo formal por correo electrónico que cumpla con todos los requisitos legales para realizar una transacción, además de la tarjeta de recibo en la conversación de tu Acción.

Para enviar una actualización inicial del pedido, sigue estos pasos:

  1. En la pestaña Scenes, selecciona tu escena TransactionDecision.
  2. En Condición, selecciona la condición que verifica el resultado exitoso, ORDER_ACCEPTED:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. Para esta condición, habilita Llama a tu webhook y proporciona un nombre de controlador de intent, como update_order.

  4. En el código de webhook, agrega un controlador de intents para enviar una actualización inicial del pedido:

    app.handle('update_order', conv => {
      const currentTime = new Date().toISOString();
      let order = conv.session.params.TransactionDecision.order;
      conv.add(new OrderUpdate({
        'updateMask': {
          'paths': [
            'purchase.status',
            'purchase.user_visible_status_label'
          ]
        },
        'order': {
          'merchantOrderId': order.merchantOrderId,
          'lastUpdateTime': currentTime,
          'purchase': {
            'status': 'CONFIRMED',
            'userVisibleStatusLabel': 'Order confirmed'
          },
        },
        'reason': 'Reason string
      }));
    });
    

Enviar actualizaciones del pedido

Deberás mantener informado al usuario sobre el estado del pedido durante su ciclo de vida. Envía al usuario actualizaciones de pedidos mediante el envío de solicitudes HTTP PATCH a la API de Orders con el estado y los detalles del pedido.

Configura solicitudes asíncronas en la API de Orders

Las solicitudes de actualización de pedidos a la API de Orders están autorizadas por un token de acceso. Para empaquetar una actualización de pedido en la API de Orders, descarga una clave de cuenta de servicio JSON asociada con tu proyecto de Actions Console y, luego, intercambia la clave de la cuenta de servicio por un token del portador que se pueda pasar al encabezado Authorization de la solicitud HTTP.

Para recuperar la clave de tu cuenta de servicio, sigue estos pasos:

  1. En la consola de Google Cloud, ve a Menú \r > APIs y servicios > Credenciales > Crear credenciales > Clave de cuenta de servicio.
  2. En Cuenta de servicio, selecciona Nueva cuenta de servicio.
  3. Establece la cuenta de servicio en service-account.
  4. Configura el Rol como Proyecto > Propietario.
  5. Establece el tipo de clave en JSON.
  6. Selecciona Crear.
  7. Se descargará una clave de cuenta de servicio JSON privada en tu máquina local.

En tu código de actualizaciones de pedido, puedes intercambiar tu clave de servicio por un token del portador mediante la biblioteca cliente de las APIs de Google y el alcance "https://www.googleapis.com/auth/actions.order.developer". Puedes encontrar pasos de instalación y ejemplos en la página de GitHub de la biblioteca cliente de la API.

También puedes hacer referencia a order-update.js en nuestra muestra de Node.js para ver un intercambio de claves de ejemplo.

Enviar actualizaciones del pedido

Una vez que hayas intercambiado la clave de tu cuenta de servicio por un token del portador de OAuth, puedes enviar actualizaciones de pedidos como solicitudes PATCH autorizadas a la API de pedidos.

URL de la API de Orders: PATCH https://actions.googleapis.com/v3/orders/${orderId}

Proporciona los siguientes encabezados en tu solicitud:

  • "Authorization: Bearer token" por el token del portador de OAuth por el que intercambiaste la clave de tu cuenta de servicio.
  • "Content-Type: application/json".

La solicitud PATCH debe tener un cuerpo JSON con el siguiente formato:

{ "orderUpdate": OrderUpdate }

El objeto OrderUpdate consta de los siguientes campos de nivel superior:

  • updateMask: Son los campos del pedido que estás actualizando. Para actualizar el estado del pedido, establece el valor en purchase.status, purchase.userVisibleStatusLabel.
  • order: Es el contenido de la actualización. Si actualizas el contenido del pedido, establece el valor en el objeto Order actualizado. Si actualizas el estado del pedido (por ejemplo, de "CONFIRMED" a "SHIPPED"), el objeto contendrá los siguientes campos:

    • merchantOrderId: Es el mismo ID que configuraste en tu objeto Order.
    • lastUpdateTime: Es la marca de tiempo de esta actualización.
    • purchase: Es un objeto que contiene lo siguiente:
      • status: Es el estado del pedido como PurchaseStatus, como "SHIPPED" o "DELIVERED".
      • userVisibleStatusLabel: Es una etiqueta visible para el usuario que proporciona detalles sobre el estado del pedido, como “Tu pedido se envió y está en camino”.
  • userNotification que se puede mostrar en el dispositivo del usuario cuando se envía esta actualización. Ten en cuenta que incluir este objeto no garantiza que aparezca una notificación en el dispositivo del usuario.

En el siguiente código de muestra, se presenta un OrderUpdate de ejemplo que actualiza el estado del pedido a DELIVERED:

// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request-promise' module for sending an HTTP POST request.
const request = require('request-promise');
// Import the OrderUpdate class from the client library.
const {OrderUpdate} = require('@assistant/conversation');

// Import the service account key used to authorize the request.
// Replacing the string path with a path to your service account key.
// i.e. const serviceAccountKey = require('./service-account.json')

// Create a new JWT client for the Actions API using credentials
// from the service account key.
let jwtClient = new google.auth.JWT(
    serviceAccountKey.client_email,
    null,
    serviceAccountKey.private_key,
    ['https://www.googleapis.com/auth/actions.order.developer'],
    null,
);

// Authorize the client
let tokens = await jwtClient.authorize();

// Declare order update
const orderUpdate = new OrderUpdate({
    updateMask: {
      paths: [
        'purchase.status',
        'purchase.user_visible_status_label'
      ]
    },
    order: {
      merchantOrderId: orderId, // Specify the ID of the order to update
      lastUpdateTime: new Date().toISOString(),
      purchase: {
        status: 'DELIVERED',
        userVisibleStatusLabel: 'Order delivered',
      },
    },
    reason: 'Order status updated to delivered.',
});

// Set up the PATCH request header and body,
// including the authorized token and order update.
let options = {
  method: 'PATCH',
  uri: `https://actions.googleapis.com/v3/orders/${orderId}`,
  auth: {
    bearer: tokens.access_token,
  },
  body: {
    header: {
      isInSandbox: true,
    },
    orderUpdate,
  },
  json: true,
};

// Send the PATCH request to the Orders API.
try {
  await request(options);
} catch (e) {
  console.log(`Error: ${e}`);
}
Establece el estado de la compra

El elemento status de una actualización de pedido debe describir el estado actual del pedido. En el campo order.purchase.status de tu actualización, usa uno de los siguientes valores:

  • CREATED: El usuario acepta el pedido y "se crea" desde la perspectiva de tu Acción, pero requiere procesamiento manual en tu backend.
  • CONFIRMED: El pedido está activo y se está procesando para su entrega.
  • IN_PREPARATION: El pedido se está preparando para el envío o la entrega, como cuando se cocina la comida o se empaqueta un artículo.
  • READY_FOR_PICKUP: El pedido está disponible para que lo retire el destinatario.
  • DELIVERED: El pedido se entregó al destinatario
  • OUT_OF_STOCK: Uno o más artículos del pedido están agotados.
  • CHANGE_REQUESTED: El usuario solicitó un cambio en el pedido y se está procesando el cambio.
  • RETURNED: El usuario devolvió el pedido después de la entrega.
  • REJECTED: si no pudiste procesar, cobrar ni “activar” el pedido de alguna otra manera.
  • CANCELLED: el usuario canceló el pedido.

Debes enviar actualizaciones del pedido para cada estado que sea relevante para tu transacción. Por ejemplo, si tu transacción requiere procesamiento manual para registrar el pedido después de que se realiza, envía una actualización del pedido de CREATED hasta que se complete el procesamiento adicional. No todos los pedidos requieren todos los valores de estado.

Cómo probar tu proyecto

Cuando pruebas tu proyecto, puedes habilitar el modo de zona de pruebas en la Consola de Actions para probar tu acción sin cobrar a una forma de pago. Para habilitar el modo de zona de pruebas, sigue estos pasos:

  1. En la Consola de Actions, haz clic en Test, en el menú de navegación.
  2. Haz clic en Configuración.
  3. Habilita la opción Zona de pruebas de desarrollo.

Para las transacciones físicas, también puedes configurar el campo isInSandbox como true en la muestra. Esta acción equivale a habilitar el parámetro de configuración del modo de zona de pruebas en la Consola de Actions. Para ver un fragmento de código que usa isInSandbox, consulta la sección Envía actualizaciones de pedidos.

Solución de problemas

Si tienes algún problema durante la prueba, lee nuestros pasos para solucionar problemas de transacciones.