Configurer Checkout

Le processus de paiement est appelé lorsqu'un utilisateur crée un panier. Le contenu du panier de l'utilisateur et les détails de la commande sont envoyés à votre service Web de bout en bout pour la commande. Ces informations sont validées par votre service Web. Vous pouvez ensuite poursuivre ou apporter des modifications au panier si nécessaire.

Le gestionnaire de paiement de votre service Web doit répondre aux requêtes POST. Lorsqu'un client choisit de payer, Google envoie au service Web Ordering End-to-End un corps de requête JSON sous la forme d'un CheckoutRequestMessage, qui contient les détails de l'Cart du client. Votre service Web répond ensuite par un CheckoutResponseMessage. Le schéma suivant illustre le processus.

CheckoutResponseMessage renvoie le panier non modifié du client ou une erreur.

À la réception d'une requête de paiement, votre service Web de bout en bout pour la commande doit effectuer les opérations suivantes:

  • Vérifiez la validité du panier en fonction des prix, de la disponibilité et du service du fournisseur des articles actuels.
  • Calculez le prix total (y compris les remises, les taxes et les frais de livraison).
  • Si l'opération réussit, répondez avec un panier non modifié.
  • Si l'opération échoue, répondez avec un message d'erreur et une nouvelle commande proposée.

Avant de commencer à implémenter le paiement, nous vous recommandons de consulter la documentation Présentation de l'exécution.

Message de demande de paiement

Pour valider le panier du client, lorsque celui-ci choisit de payer, Google envoie une requête à votre service Web avec un corps JSON sous la forme d'un CheckoutRequestMessage. La commande du client n'est pas envoyée avant plus tard dans le parcours de commande de bout en bout.

Les données contenues dans un CheckoutRequestMessage incluent les éléments suivants:

  • Intent: le champ inputs[0].intent de chaque corps de requête de paiement contient la valeur de la chaîne actions.foodordering.intent.CHECKOUT.
  • Panier: le champ inputs[0].arguments[0].extension d'une requête de paiement contient un objet Cart qui représente le panier du client.
  • Livraison ou retrait: le champ d'extension de l'objet Cart contient un objet FoodCartExtension qui spécifie les propriétés pour la livraison ou le retrait :
    • Pour les commandes de livraison, l'objet FoodCartExtension inclut l'adresse de livraison.
    • Pour les commandes à emporter ou à retirer en magasin, l'objet FoodCartExtension ne contient aucune information de localisation.
  • Bac à sable: le champ isInSandbox d'une requête de paiement contient une valeur booléenne indiquant si la transaction utilise des paiements dans le bac à sable.

Exemple de requête de règlement

Vous trouverez un exemple de CheckoutRequestMessage ci-dessous:

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

Message de réponse au règlement

Après avoir reçu une requête du service de bout en bout de commande, votre service Web de paiement doit la traiter et y répondre avec un CheckoutResponseMessage. CheckoutResponseMessage doit couvrir une requête réussie ou non.

Demande réussie

Si une requête de check-out aboutit, CheckoutResponseMessage doit inclure ProposedOrder et PaymentOptions:

  • ProposedOrder

    • cart: objet cart identique au panier fourni dans CheckoutRequestMessage. Si le contenu du panier doit être modifié, le CheckoutResponseMessage doit inclure un FoodErrorExtension avec un ProposedOrder corrigé.
    • otherItems: éléments ajoutés par le fournisseur, tels que les frais de port, les taxes et autres frais. Peut également contenir un pourboire ajouté par l'utilisateur.
    • totalPrice: prix total de la commande.
    • extension: FoodOrderExtension qui définit les informations de traitement de la commande, telles que le délai de livraison.
  • PaymentOptions

    • La configuration du traitement des paiements est abordée plus loin dans la section Configurer Google Pay. Vous pouvez utiliser des espaces réservés JSON dans votre CheckoutResponseMessage jusqu'à ce que vous soyez prêt à implémenter le traitement des paiements.
    • Pour ajouter des options de paiement d'espace réservé dans votre CheckoutResponseMessage, consultez l'exemple ci-dessous, qui utilise un exemple de passerelle de paiement pour PaymentOptions.

Exemple de réponse réussie

{
    "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": []
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            ]
        }
    }
}

Échec de la requête

Si une demande de paiement échoue, CheckoutResponseMessage doit inclure FoodErrorExtension, qui contient une liste d'éléments FoodOrderError décrivant les erreurs qui se sont produites. S'il existe des erreurs récupérables dans la commande, comme un changement de prix d'un article dans le panier, FoodErrorExtension doit inclure correctedProposedOrder.

Exemple de réponse non réussie

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

Implémentation du paiement

Vous devez suivre les étapes suivantes lors de l'implémentation du paiement.

Valider le service

Renvoyez une FoodOrderError pour la première condition d'erreur de service détectée. Ces erreurs ne sont pas récupérables. La première erreur rencontrée doit donc être renvoyée. Pour en savoir plus sur les erreurs récupérables, consultez la section Gérer les erreurs.

  1. Lisez la propriété FulfillmentOptionInfo dans la requête pour déterminer si le type de traitement est destiné à delivery ou à pickup.
  2. Si nécessaire, renvoyez les types d'erreur suivants:

    Type d'erreur Cas d'utilisation
    INVALID Le type de traitement n'est pas valide.
    NOT_FOUND Le type de traitement est introuvable.
    FERMÉE
    • Aucune période OperationHours n'est définie pour la commande.
    • La commande est urgente et aucune ServiceHours n'est disponible pour le moment.
    • Une route est fermée en raison d'un incident ou le service isDisabled est défini sur "true".
    Notez que les fenêtres spéciales ont la priorité sur les fenêtres standards. Pour voir des exemples, consultez Validation de la période de commande et Supprimer temporairement des entités de service.
    UNAVAILABLE_SLOT La commande à l'avance ne peut pas être traitée.
    NO_CAPACITY Le restaurant est occupé et n'accepte pas les commandes pour le moment.
    OUT_OF_SERVICE_AREA La commande ne peut pas être livrée à l'adresse de l'utilisateur. Pour obtenir un exemple, consultez la section Validation de l'adresse de livraison.
    NO_COURIER_AVAILABLE La commande ne peut pas être livrée en raison du manque de personnel de livraison.

Valider et définir le prix du panier

  1. Recherchez chaque panier.lineItems et validez-le avec les données actuelles de votre système ou de celui du marchand. La valeur MenuItemOffer.sku de l'entité du flux est incluse en tant que LineItem.offerId. Si nécessaire, créez un FoodOrderError pour chaque élément de campagne. Créez une erreur maximale pour chaque élément. Renvoyez les types d'erreurs suivants si nécessaire:

    Type d'erreur Cas d'utilisation Récupérable
    INVALID Les données de l'article ou de l'une des options ne sont pas valides. Non
    NOT_FOUND L'élément ou l'une des options est introuvable. Non
    PRICE_CHANGED Le prix d'un article ou d'une combinaison de modules complémentaires a changé. Cette erreur peut être considérée comme récupérable. Oui
    AVAILABILITY_CHANGED Le montant demandé pour les éléments de campagne ou l'une des options n'est pas disponible. Oui
    REQUIREMENTS_NOT_MET Le montant minimal ou maximal de la commande n'est pas atteint. Pour le savoir, vérifiez si le prix du panier est inférieur à Frais.eligibleTransactionVolumeMin ou supérieur à Frais.eligibleTransactionVolumeMax. Consultez l'exemple dans la section Validation du montant minimal de commande. Non
  2. Renvoyez la liste validée des éléments de ligne avec LineItemType REGULAR. La somme de tous les prix des éléments de campagne du panier correspond au prix du panier ou à SUBTOTAL.

Consultez des exemples dans la section Validation des articles du panier.

Calculer les frais de service

  1. Recherchez l'entité Frais appropriée pour le service en fonction des valeurs eligibleRegion, validFrom, validThrough et priority.
  2. Calculez le montant des frais en fonction de la définition de l'entité avec une propriété price, percentageOfCart ou pricePerMeter.
  3. Renvoyez les frais de livraison ou de retrait en tant que LineItem avec LineItemType DELIVERY ou FEE, respectivement. Ajoutez les frais à la liste Panier.otherItems.

Appliquer des promotions

  1. Recherchez l'entité Offre en faisant correspondre la valeur Promotion.coupon à Offre.dealCode.
  2. Validez l'offre et renvoyez un code FoodOrderError si nécessaire. Ces erreurs peuvent être considérées comme récupérables. Si nécessaire, renvoyez les types d'erreur suivants:

    Type d'erreur Cas d'utilisation
    PROMO_NOT_RECOGNIZED Le code promotionnel n'a pas été reconnu.
    PROMO_EXPIRED La validité de l'offre a expiré.
    PROMO_ORDER_INELIGIBLE La commande n'est pas éligible au bon de réduction.
    PROMO_NOT_APPLICABLE Autre motif.
  3. Calculez le montant du prix de l'offre en fonction de Deal.discount ou Deal.discountPercentage.

  4. Appliquez le montant du prix de l'offre à l'aide du montant total du panier ou du montant total des frais, en fonction de l'offre.dealType.

  5. Renvoyez Panier.promotions avec la promotion appliquée.

  6. Renvoyer la promotion en tant qu'LineItem avec LineItemType DISCOUNT. Ajoutez la remise à la liste Panier.otherItems avec un prix négatif.

Renvoyer la réponse

  1. Créez ProposedOrder.cart. Le panier de réponse est identique au panier de la requête si aucune erreur n'est détectée lors de la validation.
  2. Renvoyez la liste ProposedOrder.otherItems, y compris les taxes, les frais, les pourboires et les remises, le cas échéant. Pour en savoir plus sur la configuration de l'élément pourboire, consultez la section Pourboire.
  3. Incluez ProposedOrder.totalPrice en ajoutant le prix du panier, les frais, la remise, les taxes et les pourboires.
  4. Renvoyez FoodOrderExtension.availableFulfillmentOptions avec l'FulfillmentOption correspondante. Modifiez l'heure de prise en charge ou de livraison estimée pour indiquer l'heure prévue.
  5. Si des erreurs FoodOrderErrors sont générées à partir des vérifications de validation précédentes :
    • Incluez StructuredResponse.error et la liste des erreurs dans FoodErrorExtension.foodOrderErrors.
    • Renvoyez ProposedOrder dans le champ correctedProposedOrder si toutes les erreurs peuvent être récupérées.
    • Renvoyez PaymentOptions dans le champ paymentOptions si toutes les erreurs peuvent être récupérées.
    • Vous pouvez également inclure additionalPaymentOptions si d'autres options de paiement sont disponibles et que toutes les erreurs peuvent être récupérées.
  6. S'il n'y a pas d'erreur de validation, renvoyez proposedOrder, paymentOptions dans l'objet CheckoutResponse. Vous pouvez également inclure additionalPaymentOptions si d'autres options de paiement sont disponibles.