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 commande de bout en bout. Ces informations sont validées par votre service Web. Vous pouvez ensuite continuer ou modifier le panier si nécessaire.
Le gestionnaire de paiement de votre service Web doit répondre aux requêtes POST. Lorsqu'un client choisit de procéder au paiement, Google envoie au service Web de commande de bout en bout 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 demande de paiement, votre service Web de commande de bout en bout doit:
- Vérifiez la validité du panier en fonction des prix actuels des articles, de la disponibilité et du service du fournisseur.
- Calculez le prix total (y compris les remises, les taxes et les frais de livraison).
- Si l'opération réussit, renvoyez un panier non modifié.
- En cas d'échec, envoyez un message d'erreur et proposez une nouvelle commande.
Avant de commencer à implémenter le règlement, nous vous recommandons de consulter la documentation Présentation du traitement.
Message de demande de paiement
Afin de valider le panier du client, lorsqu'un client choisit de payer, Google envoie une requête à votre service Web avec un corps JSON sous la forme d'un CheckoutRequestMessage
. La commande client n'est pas passée avant la fin du processus de commande de bout en bout.
Les données contenues dans une 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 récupération: le champ d'extension de l'objet
Cart
contient un objetFoodCartExtension
qui spécifie les propriétés de la livraison ou de la récupération :- Pour les commandes en livraison, l'objet
FoodCartExtension
inclut l'adresse de livraison. - Pour les commandes à emporter ou à emporter, l'objet
FoodCartExtension
ne contient aucune information de localisation.
- Pour les commandes en livraison, l'objet
- Bac à sable: le champ
isInSandbox
d'une requête de paiement contient une valeur booléenne indiquant si la transaction utilise les paiements en bac à sable.
Exemple de demande de paiement
Voici un exemple 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
}
Message de réponse au règlement
Après avoir reçu une requête du service de commande de bout en bout, votre service Web de paiement doit la traiter et répondre avec une CheckoutResponseMessage
. L'élément CheckoutResponseMessage
doit couvrir une requête réussie ou échouée.
Requête réussie
Si une requête de paiement 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 à la place unFoodErrorExtension
avec unProposedOrder
corrigé.otherItems
: éléments ajoutés par le fournisseur, comme les frais de livraison, les taxes et autres frais. Il peut également inclure des pourboires ajoutés 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 ultérieurement dans Configurer Google Pay.
Vous pouvez utiliser l'espace réservé JSON dans votre
CheckoutResponseMessage
jusqu'à ce que vous soyez prêt à implémenter le traitement des paiements. - Pour ajouter des options de paiement d'espaces réservés 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 ultérieurement dans Configurer Google Pay.
Vous pouvez utiliser l'espace réservé 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 demande
Si une demande de règlement échoue, CheckoutResponseMessage
doit inclure FoodErrorExtension
, qui contient une liste d'éléments FoodOrderError
décrivant les erreurs qui se sont produites. En cas d'erreur récupérable concernant la commande, telle qu'un changement de prix d'un article dans le panier, FoodErrorExtension
doit inclure l'correctedProposedOrder
.
Exemple de réponse indiquant un échec
{
"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 règlement
Suivez les étapes ci-dessous lors de la mise en œuvre du règlement.
Valider le service
Renvoie FoodOrderError pour la première condition d'erreur de service détectée. Comme ces erreurs ne peuvent pas être récupérées, la première erreur rencontrée doit être renvoyée. Consultez la section Gérer les erreurs pour obtenir une description des erreurs récupérables.
- Lisez la propriété FulfillmentOptionInfo de la requête pour déterminer si le type de traitement est pour
delivery
oupickup
. Renvoyez les types d'erreur suivants si nécessaire:
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 fenêtre OperationHours n'est associée à la commande.
- Il s'agit d'une commande "Dès que possible", et aucune heure de service ServiceHours n'est disponible pour l'heure actuelle.
- Il y a une fermeture en urgence ou le service
isDisabled
est vrai.
UNAVAILABLE_SLOT La commande à l'avance ne peut pas être traitée. NO_CAPACITY Le restaurant est occupé et ne prend pas les commandes en ce moment. OUT_OF_SERVICE_AREA La commande ne peut pas être livrée à l'adresse de l'utilisateur. Consultez l'article Validation de l'adresse de livraison pour obtenir un exemple. NO_COURIER_AVAILABLE Impossible de livrer la commande en raison du personnel de livraison limité.
Valider le panier et définir son prix
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é de flux est incluse en tant que LineItem.offerId
. Si nécessaire, créez une erreur FoodOrderError pour chaque article. Créez un maximum d'une erreur pour chaque élément. Renvoyez les types d'erreur suivants si nécessaire:Type d'erreur Cas d'utilisation Restauration possible INVALID Les données sur les articles ou les données d'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 ne sont pas disponibles. Oui REQUIREMENTS_NOT_MET Le montant minimal ou maximal de la commande n'est pas atteint. Pour le déterminer, vérifiez si le prix du panier est inférieur aux frais. eligibleTransactionVolumeMin
ou supérieur aux frais.eligibleTransactionVolumeMax
Consultez l'exemple de validation du montant minimal de commande.Non Renvoyez la liste validée des éléments de ligne avec le paramètre LineItemType
REGULAR
. La somme de tous les prix de la ligne du panier est le prix du panier ouSUBTOTAL
.
Consultez des exemples dans la section sur la validation des articles du panier.
Calculer les frais de service
- Recherchez l'entité Frais correcte pour le service en fonction des valeurs
eligibleRegion
,validFrom
,validThrough
etpriority
. - Calculez le montant des frais selon que l'entité a été définie avec une propriété
price
,percentageOfCart
oupricePerMeter
. - Renvoyez les frais de service de livraison ou de vente à emporter en tant que LineItem avec LineItemType
DELIVERY
ouFEE
respectivement. Ajoutez les frais à la liste Panier.otherItems
.
Appliquer les promotions
- Recherchez l'entité Offre en fonction de la valeur de l'élément Promotion.
coupon
correspondant à l'offre.dealCode
Validez l'offre et renvoyez une erreur FoodOrderError, si nécessaire. Ces erreurs peuvent être considérées comme récupérables. Renvoyez les types d'erreur suivants si nécessaire:
Type d'erreur Cas d'utilisation PROMO_NOT_RECOGNIZED Le code promotionnel n'a pas été reconnu. PROMO_EXPIRED L'accord a expiré. PROMO_ORDER_INELIGIBLE La commande ne permet pas de bénéficier du bon de réduction. PROMO_NOT_APPLICABLE Toute autre raison. Calculez le montant de l'accord en fonction de l'accord.
discount
ou de l'accord.discountPercentage
Appliquez le montant de l'accord en utilisant le montant total du panier ou les frais totaux, en fonction de l'accord.
dealType
.Retournez le Panier.
promotions
avec la promotion appliquée.Renvoyez la promotion en tant que LineItem avec LineItemType
DISCOUNT
. Ajoutez la remise à Panier.otherItems
avec un prix négatif.
Renvoyer la réponse
- Créez le ProposedOrder.
cart
, le panier de réponse est identique au panier de 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 la remise, le cas échéant. Pour savoir comment configurer les récompenses, consultez la section Sans frais. - Incluez la valeur ProposedOrder.
totalPrice
en ajoutant le prix du panier, les frais, la remise, les taxes et les pourboires. - Renvoyez l'extension FoodOrderExtension.
availableFulfillmentOptions
avec l'option FulfillmentOption correspondante. Mettez à jour le délai de retrait ou de livraison estimé sur l'heure prévue. - Si des erreurs FoodOrderError ont été générées lors des vérifications de validation précédentes :
- Ajoutez StructuredResponse.
error
ainsi que la liste des erreurs dans FoodErrorExtension.foodOrderErrors
. - Renvoyez ProposedOrder dans le champ
correctedProposedOrder
si toutes les erreurs peuvent être récupérées. - Renvoyez les 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 si toutes les erreurs peuvent être récupérées.
- Ajoutez StructuredResponse.
- En l'absence d'erreurs de validation, renvoyez
proposedOrder
,paymentOptions
dans l'objet CheckoutResponse. Vous pouvez également inclureadditionalPaymentOptions
si d'autres options de paiement sont disponibles.