Crie transações físicas com o Google Pay

Neste guia, mostramos o processo de desenvolvimento de um projeto do Actions que incorpora transações de produtos físicos e usa o Google Pay para pagamento.

Fluxo de transações

Quando o projeto do Actions processa transações físicas usando pagamentos gerenciados pelo comerciante, ele usa o seguinte fluxo:

  1. Coletar informações (opcional): dependendo da natureza da transação, colete as seguintes informações do usuário no início da conversa:
    1. Validar os requisitos da transação: no início da conversa, confirme se o usuário atende aos requisitos para fazer uma transação, como ter as informações de pagamento configuradas e disponíveis corretamente antes de criar o carrinho.
    2. Solicitar um endereço de entrega: se a transação exigir um endereço de entrega, peça um ao usuário.
  2. Criar o pedido: oriente o usuário sobre uma "montagem de carrinho", em que ele escolhe quais itens quer comprar.
  3. Propor o pedido: quando o carrinho estiver concluído, proponha o pedido ao usuário para que ele possa confirmar que está correto. Se o pedido for confirmado, você receberá uma resposta com os detalhes do pedido e um token de pagamento.
  4. Finalizar o pedido e enviar um comprovante: depois de confirmar o pedido, atualize o rastreamento de inventário ou outros serviços de atendimento do pedido e envie um comprovante ao usuário.
  5. Enviar atualizações de pedidos: ao longo da vida útil do atendimento do pedido, forneça ao usuário atualizações de pedidos enviando solicitações PATCH para a API Orders.

Restrições e diretrizes de revisão

Lembre-se de que políticas adicionais se aplicam a ações com transações. Pode levar até seis semanas para analisar as Ações com transações. Portanto, considere esse tempo ao planejar a programação de lançamentos. Para facilitar o processo de revisão, verifique se você está em conformidade com as políticas e diretrizes para transações antes de enviar sua ação para análise.

Só é possível implantar Ações que vendem produtos físicos nos seguintes países:

Austrália
Brasil
Canadá
Indonésia
Japão
México
Rússia
Singapura
Tailândia
Turquia
Reino Unido
Estados Unidos

Criar o projeto

Para ver exemplos extensos de conversas transacionais, veja a amostra de transações do Node.js.

Configuração

Ao criar sua ação, você precisa especificar que quer realizar transações no Console do Actions.

Para configurar o projeto e o fulfillment, faça o seguinte:

  1. Crie um novo projeto ou importe um existente.
  2. Navegue até Implantar > Informações do diretório.
  3. Em Informações adicionais > Transações > marque a caixa que diz "Suas ações usam a API Transações para realizar transações de produtos físicos?".

1. Coletar informações (opcional)

1a. Validar os requisitos da transação (opcional)

Assim que o usuário indicar que quer fazer uma compra, verifique se ele vai poder realizar uma transação. Por exemplo, quando invocada, a Ação pode perguntar: "Você quer comprar sapatos ou conferir o saldo da conta?" Se o usuário disser "comprar sapatos", verifique se ele pode continuar e dê a ele a oportunidade de corrigir as configurações que o impedem de continuar a transação. Para isso, faça a transição para uma cena que realize uma verificação de requisitos de transação.

Criar cena de verificação de requisitos de transação
  1. Na guia "Scenes", adicione uma nova cena com o nome TransactionRequirementsCheck.
  2. Em Preenchimento de slot, clique em + para adicionar um novo slot.
  3. Em Selecionar tipo, selecione actions.type.TransactionRequirementsCheckResult como o tipo de slot.
  4. No campo do nome do slot, digite o nome TransactionRequirementsCheck.
  5. Ative a caixa de seleção Personalizar gravação do valor do slot (ativada por padrão).
  6. Clique em Salvar.

Uma verificação de requisitos de transação tem um dos resultados a seguir:

  • Se os requisitos forem atendidos, o parâmetro de sessão será definido com uma condição de sucesso e você poderá prosseguir com a criação do pedido do usuário.
  • Se não for possível atender a um ou mais dos requisitos, o parâmetro da sessão será definido com uma condição de falha. Nesse caso, afaste a conversa da experiência transacional ou encerre a conversa.
    • Se algum erro que resulte no estado de falha puder ser corrigido pelo usuário, ele receberá uma solicitação para resolver esses problemas no dispositivo. Se a conversa estiver ocorrendo em uma plataforma somente de voz, uma transferência será iniciada para o smartphone do usuário.

Processar o resultado da verificação de requisitos da transação

  1. Na guia Scenes, selecione a cena TransactionRequirementsCheck recém-criada.
  2. Em Condição, clique em + para adicionar uma nova condição.
  3. No campo de texto, insira a seguinte sintaxe de condição para verificar a condição bem-sucedida:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. Passe o cursor sobre a condição que você acabou de adicionar e clique na seta para cima para colocá-la antes de if scene.slots.status == "FINAL".

  5. Ative Enviar solicitações e forneça uma solicitação simples informando ao usuário que ele está pronto para fazer uma transação:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                You are ready to purchase physical goods.
    
  6. Em Transition, selecione outra cena, permitindo que o usuário continue a conversa e prossiga para a transação.

  7. Selecione a condição else if scene.slots.status == "FINAL".

  8. Ative Enviar solicitações e forneça uma solicitação simples informando ao usuário que não é possível realizar uma transação:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. Em Transição, selecione Encerrar conversa para encerrar a conversa se um usuário não conseguir fazer transações.

Solicitar um endereço de entrega

Se a transação exigir o endereço de entrega de um usuário, solicite essa informação ao usuário. Isso pode ser útil para determinar o preço total, o local de entrega/retirada ou para garantir que o usuário esteja na sua região de serviço. Para fazer isso, faça a transição para uma cena que solicite ao usuário o endereço de entrega.

Criar cena do endereço de entrega

  1. Na guia Cenas, adicione uma nova cena com o nome DeliveryAddress.
  2. Em Preenchimento de slot, clique em + para adicionar um novo slot.
  3. Em Selecionar tipo, escolha actions.type.DeliveryAddressValue como o tipo de slot.
  4. No campo do nome do slot, digite o nome TransactionDeliveryAddress.
  5. Ative a caixa de seleção Personalizar gravação do valor do slot (ativada por padrão).
  6. Clique em Salvar.

Ao configurar o slot, você pode fornecer um reason que permita apresentar a solicitação do Google Assistente para conseguir um endereço com uma string.A string de motivo padrão é "saber para onde enviar o pedido". Portanto, o Assistente pode perguntar ao usuário: "Para saber para onde enviar o pedido, preciso saber seu endereço de entrega".

  • Em plataformas com uma tela, o usuário escolhe qual endereço quer usar para a transação. Se ainda não tiverem fornecido um endereço, eles poderão inserir um novo.
  • Em plataformas somente por voz, o Google Assistente vai pedir permissão ao usuário para compartilhar o endereço padrão para a transação. Se a pessoa não tiver informado um endereço, a conversa será transferida para um smartphone.

Para processar o resultado do endereço de entrega, siga estas etapas:

  1. Na guia Scenes, selecione a cena DeliveryAddress recém-criada.
  2. Em Condição, clique em + para adicionar uma nova condição.
  3. No campo de texto, insira a seguinte sintaxe de condição para verificar a condição bem-sucedida:

    scene.slots.status == "FINAL" && session.params.TransactionDeliveryAddress.userDecision == "ACCEPTED"
    
  4. Passe o cursor sobre a condição que você acabou de adicionar e clique na seta para cima para colocá-la antes de if scene.slots.status == "FINAL".

  5. Ative Enviar solicitações e forneça um comando simples informando ao usuário que você recebeu o endereço dele:

    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. Em Transition, selecione outra cena, permitindo que o usuário continue a conversa.

  7. Selecione a condição else if scene.slots.status == "FINAL".

  8. Ative Enviar solicitações e forneça uma solicitação simples informando ao usuário que não é possível realizar uma transação:

    candidates:
      - first_simple:
          variants:
            - speech: I failed to get your delivery address.
    
  9. Em Transição, selecione Encerrar conversa para encerrar a conversa se um usuário não conseguir fazer transações.

Criar o pedido

Quando tiver as informações necessárias, você criará uma experiência de "montagem do carrinho" que orienta o usuário a criar um pedido. Cada ação vai ter um fluxo de montagem do carrinho um pouco diferente, conforme apropriado para o produto ou serviço.

Na experiência mais básica de montagem de carrinhos, o usuário seleciona itens de uma lista para adicionar ao pedido, embora você possa projetar a conversa para simplificar a experiência do usuário. É possível criar uma experiência de montagem de carrinho que permita ao usuário reordenar a compra mais recente com uma simples pergunta de sim ou não. Você também pode apresentar ao usuário um carrossel ou um card de lista dos principais itens "em destaque" ou "recomendados".

Recomendamos o uso de respostas avançadas para apresentar visualmente as opções do usuário, mas também projete a conversa de modo que o usuário possa criar o carrinho usando apenas a voz. Para conferir algumas práticas recomendadas e exemplos de experiências de alta qualidade de montagem de carrinhos, consulte as Diretrizes de design.

Criar um pedido

Ao longo da conversa, você precisará reunir os itens que um usuário quer comprar e, em seguida, construir um objeto Order.

No mínimo, Order precisa conter o seguinte:

  • buyerInfo: informações sobre o usuário que fez a compra.
  • transactionMerchant: informações sobre o comerciante que facilitou o pedido.
  • contents: o conteúdo real do pedido listado como lineItems.
  • priceAttributes: detalhes dos preços do pedido, incluindo o custo total com descontos e tributos.

Consulte a documentação da resposta Order para criar seu carrinho. Talvez seja necessário incluir campos diferentes, dependendo da ordem.

O exemplo de código abaixo mostra um pedido completo, incluindo campos opcionais:

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

Criar opções de ordem e apresentação

Antes de o usuário confirmar o pedido, um cartão de pedido proposto será apresentado. Personalize a forma como esse card é apresentado ao usuário definindo várias opções de ordem e apresentação.

Confira abaixo as opções de pedido e apresentação para fazer um pedido que exige um endereço de entrega, incluindo o e-mail do usuário no card de confirmação:

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

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

Criar parâmetros de pagamento

O objeto paymentParameters incluirá parâmetros de tokenização que mudam de acordo com o processador do Google Pay que você planeja usar (como Stripe, Braintree, ACI etc.).

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

O conteúdo do objeto tokenizationSpecification será diferente para cada gateway de pagamento. A tabela a seguir mostra os parâmetros usados por cada gateway:

EXEMPLO
"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"
}
FINALIZAÇÃO DA 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"
}
IMSOLUÇÕES
"parameters": {
  "gateway": "imsolutions",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
LIRA
"parameters": {
  "gateway": "lyra",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
MPGS
"parameters": {
  "gateway": "mpgs",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
money_MAIL_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"
}
PAYTURE
"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"
}
QUADRO
"parameters": {
  "gateway": "square",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
LISTA
"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"
}
UNÉLIDO
"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"
}
PAGAMENTO MUNDO
"parameters": {
  "gateway": "worldpay",
  "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"
}
YANDEX
"parameters": {
  "gateway": "yandexcheckout",
  "gatewayMerchantId": "YOUR_SHOP_ID"
}

Salvar dados do pedido no parâmetro da sessão

No fulfillment, salve os dados do pedido em um parâmetro de sessão. O objeto "order" será usado em todas as cenas da mesma sessão.

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

Propor o pedido

Depois de criar um pedido, você deve apresentá-lo ao usuário para que ele confirme ou recuse. Para isso, faça a transição para uma cena que realize uma decisão de transação.

Criar cenário de decisão da transação

  1. Na guia Cenas, adicione uma nova cena com o nome TransactionDecision.
  2. Em Preenchimento de slot, clique em + para adicionar um novo slot.
  3. Em Selecionar tipo, selecione actions.type.TransactionDecisionValue como o tipo de slot.
  4. No campo do nome do slot, digite o nome TransactionDecision.
  5. Ative a caixa de seleção Personalizar gravação do valor do slot (ativada por padrão).
  6. Em Configurar slot, selecione Usar parâmetro de sessão no menu suspenso.
  7. Em Configurar slot, insira no campo de texto o nome do parâmetro de sessão usado para armazenar a ordem (ou seja, $session.params.order).
  8. Clique em Salvar.

Para preencher um slot TransactionDecisionValue, o Google Assistente inicia uma experiência integrada em que o Order transmitido é renderizado diretamente em um "card de visualização de carrinho". O usuário pode dizer "fazer pedido", recusar a transação, mudar uma opção de pagamento, como cartão de crédito ou endereço, ou pedir para mudar o conteúdo do pedido.

O usuário também pode solicitar alterações no pedido nesse momento. Nesse caso, verifique se o fulfillment pode processar solicitações de alteração de pedidos após a conclusão da experiência de montagem do carrinho.

Processar o resultado da decisão da transação

Quando um slot TransactionDecisionValue for preenchido, a resposta do usuário à decisão da transação será armazenada em um parâmetro de sessão. Esse valor contém o seguinte:

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

Para processar o resultado de uma decisão da transação:

  1. Na guia Scenes, selecione a cena TransactionDecision recém-criada.
  2. Em Condição, clique em + para adicionar uma nova condição.
  3. No campo de texto, insira a seguinte sintaxe de condição para verificar a condição de êxito:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. Passe o cursor sobre a condição que você acabou de adicionar e clique na seta para cima para colocá-la antes de if scene.slots.status == "FINAL".

  5. Ative Enviar solicitações e forneça uma solicitação simples, informando ao usuário que o pedido foi concluído:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your order
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. Em Transição, selecione Encerrar conversa para encerrar a conversa.

  7. Em Condição, clique em + para adicionar uma nova condição.

  8. No campo de texto, insira a seguinte sintaxe de condição para verificar as condições de falha:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. Passe o cursor sobre a condição que você acabou de adicionar e clique na seta para cima para colocá-la antes de if scene.slots.status == "FINAL".

  10. Ative Enviar solicitações e forneça uma solicitação simples informando ao usuário que o pedido foi rejeitado:

    candidates:
      - first_simple:
          variants:
            - speech: Look like you don't want to order anything. Goodbye.
    
  11. Em Transição, selecione Encerrar conversa para encerrar a conversa.

  12. Selecione a condição else if scene.slots.status == "FINAL".

  13. Ative Enviar solicitações e forneça uma solicitação simples informando ao usuário que não é possível realizar uma transação:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. Em Transição, selecione Encerrar conversa para encerrar a conversa se um usuário não conseguir fazer transações.

Finalizar o pedido e enviar um comprovante

Quando o slot TransactionDecisionValue retorna um resultado de ORDER_ACCEPTED, você precisa executar imediatamente qualquer processamento necessário para "confirmar" o pedido (como manter o pedido no próprio banco de dados e cobrar o usuário).

Você pode encerrar a conversa com essa resposta, mas precisa incluir uma resposta simples para manter a conversa em movimento. Quando você fornece esse orderUpdate inicial, o usuário vê um "card de recibo recolhido" com o restante da resposta. Esse card espelha o recibo que o usuário encontra no Histórico de pedidos.

Durante a confirmação do pedido, o objeto do pedido pode incluir um userVisibleOrderId, que é o código que o usuário vê para o pedido. É possível reutilizar merchantOrderId para esse campo.

Parte do objeto OrderUpdate precisa conter um objeto de ação de acompanhamento, que se manifesta como botões de URL na parte de baixo dos detalhes do pedido, que o usuário pode encontrar no histórico de pedidos do Google Assistente.

  • É necessário fornecer, no mínimo, uma ação de acompanhamento VIEW_DETAILS em cada pedido. Ela precisa conter um link direto para a representação do pedido no seu app para dispositivos móveis ou site.
  • Você também precisa enviar um comprovante formal por e-mail que atenda a todos os requisitos jurídicos para realizar uma transação, além do cartão do comprovante na conversa da sua Ação.

Para enviar uma atualização inicial do pedido:

  1. Na guia Scenes, selecione a cena TransactionDecision.
  2. Em Condição, selecione a condição que verifica o resultado de sucesso, ORDER_ACCEPTED:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. Para essa condição, ative Call your webhook e forneça um nome de gerenciador de intent, como update_order.

  4. No código do webhook, adicione um gerenciador de intent para enviar uma atualização inicial do 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 atualizações do pedido

É preciso manter o usuário informado sobre o status do pedido durante o ciclo de vida dele. Envie as atualizações de pedidos do usuário enviando solicitações PATCH HTTP para a API Orders com o status e os detalhes do pedido.

Configurar solicitações assíncronas para a API Orders

As solicitações de atualização do pedido para a API Orders são autorizadas por um token de acesso. Para fazer o PATCH de uma atualização de pedido para a API Orders, faça o download de uma chave de conta de serviço JSON associada ao seu projeto do Console do Actions e troque a chave da conta de serviço por um token do portador que pode ser transmitido para o cabeçalho Authorization da solicitação HTTP.

Para recuperar a chave da conta de serviço, siga estas etapas:

  1. No Console do Google Cloud, acesse Menu ☰ > APIs e serviços > Credenciais > Criar credenciais > Chave da conta de serviço.
  2. Em Conta de serviço, selecione Nova conta de serviço.
  3. Defina a conta de serviço como service-account.
  4. Defina o Papel como Projeto > Proprietário.
  5. Defina o tipo de chave como JSON.
  6. Selecione Criar.
  7. Uma chave privada da conta de serviço JSON será transferida por download para a máquina local.

No código de atualização do pedido, é possível trocar a chave de serviço por um token do portador usando a biblioteca de cliente de APIs do Google e o escopo "https://www.googleapis.com/auth/actions.order.developer". Você encontra etapas e exemplos de instalação na página do GitHub da biblioteca de cliente da API.

Também é possível mencionar order-update.js na nossa amostra Node.js para ver um exemplo de troca de chaves.

Enviar atualizações do pedido

Depois de trocar a chave da sua conta de serviço por um token do portador OAuth, você pode enviar atualizações do pedido como solicitações PATCH autorizadas para a API Orders.

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

Forneça os seguintes cabeçalhos na sua solicitação:

  • "Authorization: Bearer token" pelo token do portador OAuth pelo qual você trocou a chave da conta de serviço.
  • "Content-Type: application/json".

A solicitação PATCH precisa ter um corpo JSON no seguinte formato:

{ "orderUpdate": OrderUpdate }

O objeto OrderUpdate consiste nos seguintes campos de nível superior:

  • updateMask: os campos do pedido que você está atualizando. Para atualizar o status do pedido, defina o valor como purchase.status, purchase.userVisibleStatusLabel.
  • order: o conteúdo da atualização. Se você estiver atualizando o conteúdo do pedido, defina o valor como o objeto Order atualizado. Se você estiver atualizando o status do pedido (por exemplo, de "CONFIRMED" para "SHIPPED"), o objeto conterá os seguintes campos:

    • merchantOrderId: o mesmo ID que você definiu no objeto Order.
    • lastUpdateTime: o carimbo de data/hora dessa atualização.
    • purchase: um objeto que contém o seguinte:
      • status: o status do pedido como um PurchaseStatus, como "SHIPPED" ou "DELIVERED".
      • userVisibleStatusLabel: um rótulo voltado para o usuário com detalhes sobre o status do pedido, por exemplo, "Seu pedido foi enviado e está a caminho".
  • userNotification que pode ser exibido no dispositivo do usuário quando essa atualização é enviada. A inclusão desse objeto não garante que uma notificação seja exibida no dispositivo do usuário.

A amostra de código a seguir mostra um exemplo de OrderUpdate que atualiza o status do pedido para 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}`);
}
Definir o status da compra

O status de uma atualização de pedido precisa descrever o estado atual dele. No campo order.purchase.status da atualização, use um dos seguintes valores:

  • CREATED: o pedido é aceito pelo usuário e "criado" da perspectiva da sua ação, mas requer processamento manual no seu back-end.
  • CONFIRMED: o pedido está ativo e sendo processado para atendimento.
  • IN_PREPARATION: o pedido está sendo preparado para envio/entrega, como comida sendo cozida ou um item sendo embalado.
  • READY_FOR_PICKUP: o pedido estará disponível para retirada pelo destinatário.
  • DELIVERED: o pedido foi entregue ao destinatário.
  • OUT_OF_STOCK - Um ou mais itens no pedido estão esgotados.
  • CHANGE_REQUESTED: o usuário solicitou uma mudança no pedido, e essa mudança está sendo processada.
  • RETURNED: o pedido foi devolvido pelo usuário após a entrega.
  • REJECTED: se não for possível processar, cobrar ou "ativar" o pedido.
  • CANCELLED: o pedido foi cancelado pelo usuário.

Envie atualizações de pedidos para cada status relevante para a transação. Por exemplo, se a transação exigir processamento manual para registrar o pedido depois de ser feito, envie uma atualização do pedido CREATED até que o processamento adicional seja concluído. Nem todos os pedidos exigem todos os valores de status.

Testar o projeto

Ao testar o projeto, você pode ativar o modo sandbox no Console do Actions para testar a ação sem cobrar uma forma de pagamento. Para ativar o modo sandbox, siga estas etapas:

  1. No Console do Actions, clique em Testar na navegação.
  2. Clique em Configurações.
  3. Ative a opção Sandbox de desenvolvimento.

Para transações físicas, também é possível definir o campo isInSandbox como true na amostra. Esta ação é equivalente a ativar a configuração do modo sandbox no Console do Actions. Para conferir um snippet de código que usa isInSandbox, consulte a seção Enviar atualizações de pedidos.

Solução de problemas

Caso tenha problemas durante o teste, leia nossas etapas de solução de problemas para transações.