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.
À 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îneactions.foodordering.intent.CHECKOUT
. - Panier: le champ
inputs[0].arguments[0].extension
d'une requête de paiement contient un objetCart
qui représente le panier du client. - Livraison ou retrait: le champ d'extension de l'objet
Cart
contient un objetFoodCartExtension
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.
- Pour les commandes de livraison, l'objet
- 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
: objetcart
identique au panier fourni dansCheckoutRequestMessage
. Si le contenu du panier doit être modifié, leCheckoutResponseMessage
doit inclure unFoodErrorExtension
avec unProposedOrder
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 pourPaymentOptions
.
- 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
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.
- Lisez la propriété FulfillmentOptionInfo dans la requête pour déterminer si le type de traitement est destiné à
delivery
ou àpickup
. 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".
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
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 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
- Recherchez l'entité Frais appropriée pour le service en fonction des valeurs
eligibleRegion
,validFrom
,validThrough
etpriority
. - Calculez le montant des frais en fonction de la définition de l'entité avec une propriété
price
,percentageOfCart
oupricePerMeter
. - Renvoyez les frais de livraison ou de retrait en tant que LineItem avec LineItemType
DELIVERY
ouFEE
, respectivement. Ajoutez les frais à la liste Panier.otherItems
.
Appliquer des promotions
- Recherchez l'entité Offre en faisant correspondre la valeur Promotion.
coupon
à Offre.dealCode
. 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. Calculez le montant du prix de l'offre en fonction de Deal.
discount
ou Deal.discountPercentage
.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
.Renvoyez Panier.
promotions
avec la promotion appliquée.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
- 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. - 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. - Incluez ProposedOrder.
totalPrice
en ajoutant le prix du panier, les frais, la remise, les taxes et les pourboires. - 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. - 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.
- Incluez StructuredResponse.
- S'il n'y a pas d'erreur de validation, renvoyez
proposedOrder
,paymentOptions
dans l'objet CheckoutResponse. Vous pouvez également inclureadditionalPaymentOptions
si d'autres options de paiement sont disponibles.