Crea transacciones físicas con pagos administrados por el comercio

En esta guía, se explica el proceso de desarrollo de un proyecto de Actions que incorpora transacciones de bienes físicos mediante formas de pago administradas por el sitio.

Flujo de transacción

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

  1. Vincular la cuenta del usuario: Para que el usuario use una forma de pago que guardó con tu servicio, usa la vinculación de cuentas a fin de asociar su Cuenta de Google con su cuenta en tu servicio.
  2. Recopilar información (opcional): Según la naturaleza de tu 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 inicio de la sección de transacciones de la conversación, verifica que el usuario cumpla con los requisitos para realizarlas, como configurar la información de pago y que esté disponible antes de compilar el carrito.
    2. Solicitar una dirección de entrega: Si la transacción requiere una dirección de entrega, recopila una del usuario.
  3. Crea el pedido: Guía al usuario a través de un “conjunto de carritos” en el que elija qué artículos desea comprar.
  4. Propón el pedido: Una vez que se complete el carrito, 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.
  5. Finalizar el pedido y enviar un recibo: Una vez que se confirme el pedido, actualiza el seguimiento de inventario y otros servicios de entrega y, luego, envía un recibo al usuario.
  6. Enviar actualizaciones de pedidos: Durante el ciclo de vida de entrega del pedido, envía solicitudes de PATCH a la API de pedidos para darle al usuario actualizaciones.

Restricciones y lineamientos de 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 debes tener en cuenta ese tiempo cuando planifiques tu programa de lanzamientos. A fin de facilitar el proceso de revisión, asegúrate de cumplir con los lineamientos y políticas de 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
Turquía
Reino Unido
Estados Unidos

Cómo compilar un proyecto

Para ver un ejemplo de una conversación transaccional, consulta la muestra de transacciones de Node.js.

Configura el proyecto

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. Navegue 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?".

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

Diseña la interfaz de usuario de voz para el flujo de autenticación

Verifica si el usuario está verificado y comienza el flujo de vinculación de cuentas

  1. Abra su proyecto de Actions Builder en Actions Console.
  2. Crea una escena nueva para iniciar la vinculación de cuentas en tu acción:
    1. Haz clic en Escenas.
    2. Haz clic en el ícono de agregar (+) para agregar una escena nueva.
  3. En la escena recién creada, haz clic en el ícono para agregar en Condiciones.
  4. Agrega una condición que verifique si el usuario asociado con la conversación es un usuario verificado. Si falla la verificación, tu acción no podrá realizar la vinculación de cuentas durante la conversación y debería dar acceso a funcionalidades que no requieran la vinculación de cuentas.
    1. En el campo Enter new expression, en Condition, ingresa la siguiente lógica: user.verificationStatus != "VERIFIED"
    2. En Transition, selecciona una escena que no requiera la vinculación de cuentas o una escena que sea el punto de entrada a la funcionalidad solo para invitados.

  1. Haz clic en el ícono para agregar en Condiciones.
  2. Agrega una condición para activar un flujo de vinculación de cuentas si el usuario no tiene una identidad asociada.
    1. En el campo Enter new expression, en Condition, ingresa la siguiente lógica: user.verificationStatus == "VERIFIED"
    2. En Transition, selecciona la escena del sistema Account Linking.
    3. Haz clic en Guardar.

Después de guardar, se agregará a tu proyecto una nueva escena del sistema de vinculación de cuentas llamada <SceneName>_AccountLinking.

Cómo personalizar la escena de vinculación de cuentas

  1. En Escenas, selecciona la escena del sistema de vinculación de cuentas.
  2. Haz clic en Enviar mensaje y agrega una oración corta para describir al usuario por qué la acción debe acceder a su identidad (por ejemplo, "Para guardar tus preferencias").
  3. Haz clic en Guardar.

  1. En Condiciones, haga clic en Si el usuario completa la vinculación de la cuenta correctamente.
  2. Configura cómo debe proceder el flujo si el usuario acepta vincular su cuenta. Por ejemplo, llama al webhook para procesar cualquier lógica empresarial personalizada necesaria y volver a la escena de origen.
  3. Haz clic en Guardar.

  1. En Condiciones, haga clic en Si el usuario cancela o descarta la vinculación de cuentas.
  2. Configura cómo debe proceder el flujo si el usuario no acepta vincular su cuenta. Por ejemplo, envía un mensaje de confirmación y redirecciona a escenas que proporcionen una funcionalidad que no requiera la vinculación de cuentas.
  3. Haz clic en Guardar.

  1. En Condiciones, haga clic en Si se produce un error del sistema o de la red.
  2. Configura cómo debe proceder el flujo si no se puede completar el flujo de vinculación de cuentas debido a errores del sistema o de la red. Por ejemplo, envía un mensaje de confirmación y redirecciona a escenas que proporcionen una funcionalidad que no requiera la vinculación de cuentas.
  3. Haz clic en Guardar.

Recopila información (opcional)

Validar los requisitos de las transacciones (opcional)

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

Crear escena de verificación de requisitos de transacción
  1. En la pestaña Escenas, agrega un ambiente nuevo con el nombre TransactionRequirementsCheck.
  2. En Relleno de ranuras, haz clic en + para agregar un espacio nuevo.
  3. En Seleccionar tipo, selecciona actions.type.TransactionRequirementsCheckResult como tipo de espacio.
  4. En el campo del nombre de la ranura, asígnale el nombre TransactionRequirementsCheck.
  5. Habilita la casilla de verificación Personalizar la escritura de valores de ranura (habilitada de forma predeterminada).
  6. Haz clic en Guardar.

Una verificación de los requisitos de la transacción generará 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 compilació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 finalizarla.
    • Si el usuario puede corregir cualquier error que genere el estado de falla, se le pedirá que lo resuelva. Si la conversación se lleva a cabo en una plataforma de solo voz, se iniciará una transferencia al teléfono del usuario.

Resultado de la verificación de los 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 para verificar la condición correcta:

    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 Enviar mensajes y proporciona un mensaje simple que le 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 permitir 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 Enviar mensajes y proporciona un mensaje simple para que el usuario sepa 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 finalizarla si un usuario no puede realizar transacciones.

Solicita una dirección de entrega (opcional)

Si la transacción requiere la dirección de entrega del usuario, debes solicitarla. Esto puede ser útil para determinar el precio total, la ubicación de entrega o retiro o para garantizar que el usuario se encuentre en tu región de servicio. Para hacerlo, debes hacer la transición a una escena que solicite al usuario su dirección de entrega.

Crea la escena de la dirección de entrega

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

Cuando configuras la ranura, puedes proporcionar un reason que te permita anteponer la solicitud de Asistente a fin de obtener una dirección con una string.La string predeterminada es "saber a dónde enviar el pedido". Por lo tanto, es posible que el Asistente le pregunte al usuario: "A fin de saber dónde enviar el pedido, necesito obtener la dirección de entrega".

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

Para controlar 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 para verificar la condición correcta:

    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 Enviar mensajes 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 permitir que el usuario continúe la conversación.

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

  8. Habilita Enviar mensajes y proporciona un mensaje simple para que el usuario sepa 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 finalizarla si un usuario no puede realizar transacciones.

Cree el pedido

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

La experiencia de ensamblado de carrito más básica tiene un usuario que elige artículos de una lista para agregar a su pedido, aunque puedes diseñar la conversación a fin de simplificar la experiencia del usuario. Podrías crear una experiencia de ensamblado de carritos que permita al usuario reordenar 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 con los elementos "destacados" o "recomendados" principales.

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

Crea un pedido

Durante la conversación, deberás recopilar los elementos que un usuario quiera 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 la información sobre el comercio que facilitó el pedido.
  • contents: El contenido real del pedido que aparece como lineItems.
  • priceAttributes: Detalles de precios sobre el pedido, incluido el costo total del pedido con impuestos y descuentos.

Consulta la documentación de respuesta de Order para construir el carrito. Ten en cuenta que posiblemente debas incluir diferentes campos según el orden.

El siguiente código de muestra muestra 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 pedido 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 configurando 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'
    };

Crear parámetros de pago

El objeto paymentParameters incluye un merchantPaymentOption con campos que describen la forma de pago del usuario para su pedido. A continuación, se muestra un ejemplo de parámetros de pago con una tarjeta de crédito Visa:

const paymentParamenters = {
      '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'
          }
        }]
      }
    };

Guardar datos del pedido en el parámetro de la sesión

Desde tu entrega, guarda los datos del pedido en un parámetro session. El objeto de orden se usará entre escenas para 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 pedido

Una vez que haya creado un pedido, debe presentarlo al usuario para que lo confirme o lo rechace. Para ello, debes cambiar a una escena que tome una decisión sobre una transacción.

Crear escena de decisiones de transacción

  1. En la pestaña Escenas, 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 espacio.
  4. En el campo del nombre de la ranura, asígnale el nombre TransactionDecision.
  5. Habilita la casilla de verificación Personalizar la escritura de valores de ranura (habilitada de forma predeterminada).
  6. En Configurar espacio, selecciona Usar parámetro de sesión en el menú desplegable.
  7. En Configurar ranura, ingresa el nombre del parámetro de sesión que se usó para almacenar el pedido en el campo de texto (es decir, $session.params.order).
  8. Haga clic en Guardar.

En un intento por llenar un espacio 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 un pedido", rechazar la transacción, cambiar una opción de pago, como la tarjeta de crédito o la dirección, o solicitar cambiar 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 ensamblado del carrito.

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

Cuando se llena un espacio TransactionDecisionValue, la respuesta del usuario a la decisión de 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 manejar 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 para verificar la condición correcta:

    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 Enviar mensajes y proporciona un mensaje simple que le informe al usuario que se completó su 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 para finalizarla.

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

  8. En el campo de texto, ingresa la siguiente sintaxis 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 Enviar mensajes y proporciona un mensaje simple que informe 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 para finalizarla.

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

  13. Habilita Enviar mensajes 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 cualquier procesamiento necesario para “confirmar” el orden (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 mantenerla activa. Cuando proporciones esta orderUpdate inicial, el usuario verá una "tarjeta de recibo contraída" junto con el resto de tu respuesta. Esta tarjeta duplicará el recibo que el usuario encuentra 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 reutilizar tu 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 app para dispositivos móviles o sitio web.
  • 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:

  1. En la pestaña Scenes, selecciona tu escena TransactionDecision.
  2. En Condición, selecciona la condición que verifica el resultado correcto, 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 tu código de webhook, agrega un controlador de intents para enviar una actualización del pedido inicial:

    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 al usuario informado sobre el estado del pedido durante su vida útil. Para enviar actualizaciones de pedidos de usuarios, envía solicitudes HTTP PATCH a la API de pedidos con el estado y los detalles del pedido.

Cómo configurar solicitudes asíncronas a la API de Orders

Las solicitudes de actualización de pedidos a la API de Orders se autorizan mediante un token de acceso. Para PACAR una actualización de pedido a 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 pueda pasarse 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ú ☰ > 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 la Función como Proyecto > Propietario.
  5. Establece el tipo de clave en JSON.
  6. Seleccione 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 usando la biblioteca cliente de las API de Google y el alcance "https://www.googleapis.com/auth/actions.order.developer". Puedes encontrar pasos y ejemplos de instalación en la página de GitHub de la biblioteca cliente de la API.

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

Enviar actualizaciones del pedido

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

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

Proporciona los siguientes encabezados en la solicitud:

  • "Authorization: Bearer token" por el token del portador de OAuth para 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: El contenido de la actualización Si actualizas el contenido del pedido, establece el valor del objeto Order actualizado. Si actualizas el estado del pedido (por ejemplo, de "CONFIRMED" a "SHIPPED"), el objeto contiene los siguientes campos:

    • merchantOrderId: Es el mismo ID que configuraste en el objeto Order.
    • lastUpdateTime: Es la marca de tiempo de esta actualización.
    • purchase: Un objeto que contiene lo siguiente:
      • status: Es el estado del pedido como PurchaseStatus, como "SHIPPED" o "DELIVERED".
      • userVisibleStatusLabel: Es una etiqueta orientada al usuario que proporciona detalles sobre el estado del pedido, como “Se envió tu pedido y está en camino”.
  • userNotification (opcional): Es un objeto 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 muestra 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}`);
}
Cómo establecer el estado de compra

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

  • CREATED: El usuario acepta el pedido y lo "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: se prepara el pedido para el envío o la entrega, como cuando se cocina o se empaqueta un artículo.
  • READY_FOR_PICKUP: El destinatario puede solicitar el pedido.
  • DELIVERED: Se entregó el pedido 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.
  • RETURNED: el usuario devolvió el pedido después de la entrega.
  • REJECTED: si no pudiste procesar, cargar o "activar" el pedido.
  • CANCELLED: El usuario canceló el pedido.

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

Prueba 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 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 tu muestra. Esta acción es equivalente a habilitar la 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 Cómo enviar actualizaciones de pedidos.

Solución de problemas

Si tienes algún problema durante la prueba, debes leer nuestros pasos para solucionar problemas relacionados con las transacciones.