Configurar o Checkout

O processo de finalização da compra é invocado quando um usuário cria um carrinho. O conteúdo do carrinho do usuário e os detalhes do pedido são enviados para seu serviço da Web de ponta a ponta. Essas informações são validadas pelo seu serviço da Web, e você pode continuar ou fazer ajustes no carrinho conforme necessário.

O gerenciador de finalização de compra do seu serviço da Web precisa responder a solicitações POST. Quando um cliente escolhe finalizar a compra, o Google envia ao serviço da Web de pedidos de ponta a ponta um corpo de solicitação JSON no formato de CheckoutRequestMessage, que contém os detalhes do Cart de um cliente. Seu serviço da Web responde com um CheckoutResponseMessage. No diagrama a seguir, ilustramos o processo.

A CheckoutResponseMessage retorna o carrinho não modificado do cliente ou um
erro.

Ao receber uma solicitação de finalização de compra, seu serviço da Web de pedidos de ponta a ponta precisa fazer o seguinte:

  • Verifique a validade do carrinho com base nos preços, na disponibilidade e no serviço do provedor de itens atuais.
  • Calcule o preço total (incluindo descontos, tributos e taxas de entrega).
  • Se for bem-sucedido, responda com um carrinho não modificado.
  • Se não for bem-sucedido, responda com uma mensagem de erro e uma nova ordem proposta.

Antes de começar a implementar o processo de finalização da compra, recomendamos que você leia a documentação Visão geral da conclusão.

Mensagem de solicitação de finalização de compra

Para validar o carrinho do cliente, quando ele escolhe finalizar a compra, o Google envia uma solicitação ao seu serviço da Web com um corpo JSON no formato de CheckoutRequestMessage. O pedido do cliente só é enviado mais tarde no fluxo de finalização de pedidos.

Os dados contidos em um CheckoutRequestMessage incluem o seguinte:

  • Intent: o campo inputs[0].intent de cada corpo de solicitação de finalização de compra contém o valor da string actions.foodordering.intent.CHECKOUT.
  • Cart: o campo inputs[0].arguments[0].extension de uma solicitação de finalização de compra contém um objeto Cart que representa o carrinho do cliente.
  • Entrega ou retirada: o campo de extensão do objeto Cart contém um objeto FoodCartExtension que especifica propriedades para entrega ou retirada:
    • Para pedidos de entrega, o objeto FoodCartExtension inclui o endereço de entrega.
    • Para pedidos de retirada ou entrega, o objeto FoodCartExtension não contém informações de local.
  • Sandbox: o campo isInSandbox de uma solicitação de finalização de compra contém um valor booleano que indica se a transação usa pagamentos do sandbox.

Exemplo de solicitação de finalização de compra

Confira abaixo um exemplo de CheckoutRequestMessage:

{
    "user": {},
    "conversation": {
        "conversationId": "CTZbZfUlHCybEdcz_5PB3Ttf"
    },
    "inputs": [
        {
            "intent": "actions.foodordering.intent.CHECKOUT",
            "arguments": [
                {
                    "extension": {
                        "@type": "type.googleapis.com/google.actions.v2.orders.Cart",
                        "merchant": {
                            "id": "restaurant/Restaurant/QWERTY",
                            "name": "Tep Tep Chicken Club"
                        },
                        "lineItems": [
                            {
                                "name": "Spicy Fried Chicken",
                                "type": "REGULAR",
                                "id": "299977679",
                                "quantity": 2,
                                "price": {
                                    "type": "ESTIMATE",
                                    "amount": {
                                        "currencyCode": "AUD",
                                        "units": "39",
                                        "nanos": 600000000
                                    }
                                },
                                "offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
                                "extension": {
                                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
                                }
                            }
                        ],
                        "extension": {
                            "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                            "fulfillmentPreference": {
                                "fulfillmentInfo": {
                                    "delivery": {
                                        "deliveryTimeIso8601": "P0M"
                                    }
                                }
                            },
                            "location": {
                                "coordinates": {
                                    "latitude": -33.8376441,
                                    "longitude": 151.0868736
                                },
                                "formattedAddress": "Killoola St, 1, Concord West NSW 2138",
                                "zipCode": "2138",
                                "city": "Concord West",
                                "postalAddress": {
                                    "regionCode": "AU",
                                    "postalCode": "2138",
                                    "administrativeArea": "NSW",
                                    "locality": "Concord West",
                                    "addressLines": [
                                        "Killoola St",
                                        "1"
                                    ]
                                }
                            }
                        }
                    }
                }
            ]
        }
    ],
    "directActionOnly": true,
    "isInSandbox": true
}

Mensagem de resposta de finalização de compra

Depois de receber uma solicitação do serviço de finalização de compra, seu serviço da Web de finalização de compra precisa processá-la e responder com um CheckoutResponseMessage. O CheckoutResponseMessage precisa abranger uma solicitação bem-sucedida ou não concluída.

Pedido concluído

Se uma solicitação de finalização de compra for bem-sucedida, o CheckoutResponseMessage precisará incluir ProposedOrder e PaymentOptions:

  • ProposedOrder

    • cart: um objeto cart idêntico ao carrinho fornecido no CheckoutRequestMessage. Se algum conteúdo do carrinho precisar ser alterado, o CheckoutResponseMessage precisará incluir um FoodErrorExtension com um ProposedOrder corrigido.
    • otherItems: itens adicionados pelo provedor, como taxas de entrega, tributos e outras taxas. Também pode conter gorjeta adicionada pelo usuário.
    • totalPrice: o preço total do pedido.
    • extension: um FoodOrderExtension que define informações de preenchimento do pedido, como o tempo de entrega.
  • PaymentOptions

    • A configuração do processamento de pagamentos será abordada mais adiante em Configurar o Google Pay. Você pode usar o marcador de posição JSON no CheckoutResponseMessage até que esteja pronto para implementar o processamento de pagamentos.
    • Para adicionar opções de pagamento de marcador de posição no CheckoutResponseMessage, consulte o exemplo abaixo, que usa um gateway de pagamento de exemplo para PaymentOptions.

Exemplo de resposta bem-sucedida

{
    "finalResponse": {
        "richResponse": {
            "items": [
                {
                    "structuredResponse": {
                        "checkoutResponse": {
                            "proposedOrder": {
                                "cart": {
                                    "merchant": {
                                        "id": "restaurant/Restaurant/QWERTY",
                                        "name": "Tep Tep Chicken Club"
                                    },
                                    "lineItems": [
                                        {
                                            "name": "Spicy Fried Chicken",
                                            "type": "REGULAR",
                                            "id": "299977679",
                                            "quantity": 2,
                                            "price": {
                                                "type": "ESTIMATE",
                                                "amount": {
                                                    "currencyCode": "AUD",
                                                    "units": "39",
                                                    "nanos": 600000000
                                                }
                                            },
                                            "offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
                                            "extension": {
                                                "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
                                            }
                                        }
                                    ],
                                    "extension": {
                                        "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                                        "fulfillmentPreference": {
                                            "fulfillmentInfo": {
                                                "delivery": {
                                                    "deliveryTimeIso8601": "P0M"
                                                }
                                            }
                                        },
                                        "location": {
                                            "coordinates": {
                                                "latitude": -33.8376441,
                                                "longitude": 151.0868736
                                            },
                                            "formattedAddress": "Killoola St, 1, Concord West NSW 2138",
                                            "zipCode": "2138",
                                            "city": "Concord West",
                                            "postalAddress": {
                                                "regionCode": "AU",
                                                "postalCode": "2138",
                                                "administrativeArea": "NSW",
                                                "locality": "Concord West",
                                                "addressLines": [
                                                    "Killoola St",
                                                    "1"
                                                ]
                                            }
                                        }
                                    }
                                },
                                "totalPrice": {
                                    "type": "ESTIMATE",
                                    "amount": {
                                        "currencyCode": "AUD",
                                        "units": "43",
                                        "nanos": 100000000
                                    }
                                },
                                "extension": {
                                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
                                    "availableFulfillmentOptions": [
                                        {
                                            "fulfillmentInfo": {
                                                "delivery": {
                                                    "deliveryTimeIso8601": "P0M"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "otherItems": [
                                    {
                                        "name": "Delivery fee",
                                        "price": {
                                            "type": "ESTIMATE",
                                            "amount": {
                                                "currencyCode": "AUD",
                                                "units": "3",
                                                "nanos": 500000000
                                            }
                                        },
                                        "type": "DELIVERY"
                                    }
                                ]
                            },
                            "paymentOptions": {
                                "googleProvidedOptions": {
                                    "facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gatewayMerchantId\":\"YOUR_MERCHANT_ID\",\"gateway\":\"cybersource\"}}}],\"transactionInfo\":{\"currencyCode\":\"AUD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"43.1\"}} "
                                }
                            },
                            "additionalPaymentOptions": [
                                {
                                    "actionProvidedOptions": {
                                        "paymentType": "ON_FULFILLMENT",
                                        "displayName": "Pay when you get your food.",
                                        "onFulfillmentPaymentData": {
                                            "supportedPaymentOptions": []
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            ]
        }
    }
}

Pedido não realizado

Se uma solicitação de finalização de compra falhar, o CheckoutResponseMessage precisará incluir FoodErrorExtension, que contém uma lista de itens FoodOrderError que descrevem os erros ocorridos. Se houver erros recuperáveis no pedido, como uma mudança de preço de um item no carrinho, o FoodErrorExtension precisará incluir o correctedProposedOrder.

Exemplo de resposta com falha

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "error": {
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
              "foodOrderErrors": [
                {
                  "error": "CLOSED",
                  "description": "The restaurant is closed."
                }
              ]
            }
          }
        }
      ]
    }
  }
}

Implementação da finalização da compra

Siga as etapas abaixo ao implementar o pagamento.

Validar o serviço

Retorne um FoodOrderError para a primeira condição de erro de serviço encontrada. Esses erros não são recuperáveis, então o primeiro erro encontrado precisa ser retornado. Consulte Como lidar com erros para conferir uma descrição dos erros recuperáveis.

  1. Leia a propriedade FulfillmentOptionInfo na solicitação para determinar se o tipo de fulfillment é para delivery ou pickup.
  2. Retorne os seguintes tipos de erro, se necessário:

    Tipo de erro Caso de uso
    INVALID O tipo de fulfillment é inválido.
    NOT_FOUND O tipo de atendimento não foi encontrado.
    CLOSED
    • Não há janelas de OperationHours para o pedido.
    • O pedido é "Assim que possível" e não há ServiceHours disponíveis para o momento.
    • Há uma interdição de emergência ou o serviço isDisabled é verdadeiro.
    As janelas especiais têm precedência sobre as janelas comuns. Consulte exemplos em validação da janela de pedidos e remova entidades de serviço temporariamente.
    UNAVAILABLE_SLOT O pedido com antecedência não pode ser atendido.
    NO_CAPACITY O restaurante está ocupado e não está aceitando pedidos no momento.
    OUT_OF_SERVICE_AREA O pedido não pode ser entregue no endereço do usuário. Consulte Validação do endereço de entrega para conferir um exemplo.
    NO_COURIER_AVAILABLE O pedido não pode ser entregue devido à limitação de pessoal de entrega.

Validar e definir o preço do carrinho

  1. Procure cada carrinho.lineItems e valide com os dados atuais no seu sistema ou no do comerciante. O valor MenuItemOffer.sku da entidade do feed é incluído como LineItem.offerId. Crie um FoodOrderError para cada item de linha, se necessário. Crie no máximo um erro para cada item. Retorne os seguintes tipos de erro, se necessário:

    Tipo de erro Caso de uso Recuperável
    INVALID Os dados do item ou de qualquer uma das opções são inválidos. Não
    NOT_FOUND O item ou qualquer uma das opções não foi encontrado. Não
    PRICE_CHANGED O preço de um item ou de uma combinação de complementos mudou. Esse erro pode ser tratado como recuperável. Sim
    AVAILABILITY_CHANGED O valor solicitado para os itens de linha ou qualquer uma das opções não está disponível. Sim
    REQUIREMENTS_NOT_MET O pedido mínimo ou máximo não foi atendido. Isso pode ser determinado verificando se o preço do carrinho está abaixo da taxa.eligibleTransactionVolumeMin ou acima da taxa.eligibleTransactionVolumeMax. Consulte o exemplo em Validação do valor mínimo do pedido. Não
  2. Retorne a lista validada de itens de linha com LineItemType REGULAR. A soma de todos os preços dos itens de linha do carrinho é o preço do carrinho ou SUBTOTAL.

Confira exemplos em Validação de itens do carrinho.

Calcular as taxas de serviço

  1. Encontre a entidade Fee correta para o serviço com base em eligibleRegion, validFrom, validThrough e priority.
  2. Calcule o valor da taxa com base em se a entidade foi definida com uma propriedade price, percentageOfCart ou pricePerMeter.
  3. Retorne a taxa de serviço de entrega ou retirada como um LineItem com LineItemType DELIVERY ou FEE, respectivamente. Adicione a taxa à lista Cart.otherItems.

Aplicar promoções

  1. Encontre a entidade Deal com base na correspondência do valor Promotion.coupon com o Deal.dealCode.
  2. Valide a transação e retorne um FoodOrderError, se necessário. Esses erros podem ser tratados como recuperáveis. Retorne os seguintes tipos de erro, se necessário:

    Tipo de erro Caso de uso
    PROMO_NOT_RECOGNIZED O código do cupom não foi reconhecido.
    PROMO_EXPIRED A validade da oferta expirou.
    PROMO_ORDER_INELIGIBLE O pedido não está qualificado para o cupom.
    PROMO_NOT_APPLICABLE Qualquer outro motivo.
  3. Calcule o valor do preço da transação com base em Transação.discount ou Transação.discountPercentage.

  4. Aplique o valor do preço da oferta usando o total do carrinho ou da taxa, dependendo da oferta.dealType.

  5. Retorna o carrinho.promotions com a promoção aplicada.

  6. Retorne a promoção como um LineItem com LineItemType DISCOUNT. Adicione o desconto à lista Cart.otherItems com um preço negativo.

Retornar a resposta

  1. Crie a ProposedOrder.cart. O carrinho de resposta será o mesmo que o de solicitação se nenhum erro for encontrado durante a validação.
  2. Retorna a lista ProposedOrder.otherItems, incluindo impostos, taxas, gorjetas e descontos, se aplicável. Consulte Gratuidade para mais detalhes sobre como configurar o item de gorjeta.
  3. Inclua a ProposedOrder.totalPrice adicionando o preço, as taxas, o desconto, os tributos e a gorjeta do carrinho.
  4. Retorne a FoodOrderExtension.availableFulfillmentOptions com a respectiva FulfillmentOption. Atualize o horário de retirada ou entrega estimado.
  5. Se houver erros de pedido de comida gerados pelas verificações de validação anteriores:
    • Inclua StructuredResponse.error e a lista de erros em FoodErrorExtension.foodOrderErrors.
    • Retorne ProposedOrder no campo correctedProposedOrder se todos os erros forem recuperáveis.
    • Retorne PaymentOptions no campo paymentOptions se todos os erros forem recuperáveis.
    • Opcionalmente, inclua additionalPaymentOptions se houver outras opções de pagamento disponíveis e todos os erros forem recuperáveis.
  6. Se não houver erros de validação, retorne o proposedOrder, paymentOptions no objeto CheckoutResponse. Se quiser, inclua additionalPaymentOptions se houver outras opções de pagamento disponíveis.