Proces płatności jest wywoływany, gdy użytkownik utworzy koszyk. Zawartość koszyka użytkownika i szczegóły zamówienia są wysyłane do kompleksowej usługi internetowej do obsługi zamówień. Informacje te są sprawdzane przez Twoją usługę internetową. W razie potrzeby możesz kontynuować lub wprowadzić zmiany w koszyku.
Moduł obsługi płatności Twojej usługi internetowej musi odpowiadać na żądania POST. Gdy klient zdecyduje się zapłacić za zakupy, Google wysyła do kompleksowej usługi sieciowej do obsługi zamówień treść żądania JSON w postaci CheckoutRequestMessage
, która zawiera szczegóły identyfikatora Cart
klienta. Następnie usługa internetowa odpowiada CheckoutResponseMessage
. Poniższy diagram przedstawia cały proces.
Po otrzymaniu prośby o płatność Twoja kompleksowa usługa internetowa do obsługi zamówień musi wykonać te czynności:
- Sprawdzanie poprawności koszyka na podstawie aktualnych cen produktów, dostępności i usługi dostawcy.
- Oblicz łączną cenę (obejmującą rabaty, podatki i opłaty za dostawę).
- Jeśli operacja się uda, w odpowiedzi prześlij niezmodyfikowany koszyk.
- Jeśli się to nie powiedzie, w odpowiedzi prześlij komunikat o błędzie i nowe proponowane zamówienie.
Zanim zaczniesz implementować proces płatności, zapoznaj się z dokumentacją omówienia realizacji.
Wiadomość z prośbą o płatność
Gdy klient zdecyduje się dokonać płatności, Google wysyła do Twojej usługi internetowej żądanie z treścią JSON w postaci CheckoutRequestMessage
. Zamówienie klienta jest przesyłane dopiero później w ramach kompleksowego procesu składania zamówień.
Dane zawarte w elemencie CheckoutRequestMessage
to m.in.:
- Intencja: pole
inputs[0].intent
każdej treści żądania płatności zawiera wartość ciągu tekstowegoactions.foodordering.intent.CHECKOUT
. - Koszyk: pole
inputs[0].arguments[0].extension
żądania płatności zawiera obiektCart
reprezentujący koszyk klienta. - Dostarczanie lub eksportowanie: pole rozszerzenia obiektu
Cart
zawiera obiektFoodCartExtension
, który określa właściwości przesyłania lub eksportowania:- W przypadku zamówień z dostawą obiekt
FoodCartExtension
zawiera adres dostawy. - W przypadku zamówień z odbiorem lub na wynos obiekt
FoodCartExtension
nie zawiera informacji o lokalizacji.
- W przypadku zamówień z dostawą obiekt
- Piaskownica: pole
isInSandbox
żądania płatności zawiera wartość logiczną, która wskazuje, czy transakcja korzysta z płatności w piaskownicy.
Przykład żądania płatności
Poniżej znajduje się przykład atrybutu 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
}
Wiadomość z odpowiedzią dotyczącą płatności
Gdy otrzymasz żądanie od usługi kompleksowej obsługi zamówień, usługa internetowa płatności musi ją przetworzyć i odpowiedzieć za pomocą polecenia CheckoutResponseMessage
. CheckoutResponseMessage
musi uwzględniać udane lub nieudane żądanie.
Żądanie przetworzone
Jeśli prośba o płatność zostanie zrealizowana, CheckoutResponseMessage
musi zawierać tagi ProposedOrder
i PaymentOptions
:
ProposedOrder
cart
: obiektcart
identyczny z koszykiem podanym wCheckoutRequestMessage
. Jeśli chcesz zmienić zawartość koszyka, elementCheckoutResponseMessage
powinien zawierać w zamian elementFoodErrorExtension
z poprawioną wartościąProposedOrder
.otherItems
: elementy dodane przez dostawcę, np. opłaty za dostawę, podatki i inne opłaty. Może również zawierać napiwek dodany przez użytkownika.totalPrice
: łączna cena zamówienia.extension
: elementFoodOrderExtension
, który określa informacje o realizacji zamówienia, takie jak czas dostawy.
PaymentOptions
- Konfigurowanie przetwarzania płatności zostało opisane w dalszej części artykułu Konfigurowanie Google Pay.
Dopóki nie przygotujesz się do zaimplementowania przetwarzania płatności, możesz używać zastępczego kodu JSON w
CheckoutResponseMessage
. - Aby dodać zastępcze opcje płatności na koncie
CheckoutResponseMessage
, zapoznaj się z poniższym przykładem, w którym użyto przykładowej bramy płatności do płatnościPaymentOptions
.
- Konfigurowanie przetwarzania płatności zostało opisane w dalszej części artykułu Konfigurowanie Google Pay.
Dopóki nie przygotujesz się do zaimplementowania przetwarzania płatności, możesz używać zastępczego kodu JSON w
Przykład udanej odpowiedzi
{
"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": []
}
}
}
]
}
}
}
]
}
}
}
Żądanie nie powiodło się
Jeśli żądanie płatności nie powiedzie się, CheckoutResponseMessage
musi uwzględnić element FoodErrorExtension
, który zawiera listę elementów FoodOrderError
opisujących wszelkie błędy, które wystąpiły. Jeśli w zamówieniu występują błędy, które można naprawić, np. zmiana ceny produktu w koszyku, FoodErrorExtension
musi zawierać parametr correctedProposedOrder
.
Przykład odpowiedzi nieudanej
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "CLOSED",
"description": "The restaurant is closed."
}
]
}
}
}
]
}
}
}
Implementacja płatności
Podczas wdrażania płatności należy wykonać poniższe czynności.
Zweryfikuj usługę
Zwracaj wartość FoodOrderError w przypadku pierwszego znalezionego stanu błędu usługi. Tych błędów nie można odzyskać, więc należy zwrócić pierwszy napotkany błąd. Opis błędów możliwych do naprawienia znajdziesz w sekcji Obsługa błędów.
- Przeczytaj właściwość FulfillmentOptionInfo w żądaniu, aby określić, czy typ realizacji to
delivery
czypickup
. W razie potrzeby zwracaj te typy błędów:
Typ błędu Przypadek użycia INVALID Typ realizacji jest nieprawidłowy. NOT_FOUND Nie znaleziono typu realizacji. ZAMKNIĘTE - Nie ma okien OperationHours dla tego zamówienia.
- Zamówienie jest zamówieniem typu Jak najszybciej. W tej chwili nie ma dostępnych ServiceHours na karcie ASAP (jak najszybciej).
- Zamknięcie awaryjne lub usługa
isDisabled
jest prawda.
UNAVAILABLE_SLOT Nie można zrealizować zamówienia z wyprzedzeniem. NO_CAPACITY Restauracja jest zatłoczona i nie przyjmuje obecnie zamówień. OUT_OF_SERVICE_AREA Nie można dostarczyć zamówienia na adres użytkownika. Przykład znajdziesz w artykule Sprawdzanie poprawności adresu dostawy. NO_COURIER_AVAILABLE Nie można dostarczyć zamówienia ze względu na ograniczoną liczbę pracowników.
Zweryfikuj koszyk i wycen go
Wyszukaj każdy Koszyk.
lineItems
i zweryfikuj go na podstawie bieżących danych w swoim systemie lub systemie sprzedawcy. Wartość MenuItemOffer.sku
z elementu pliku danych jest uwzględniana jako LineItem.offerId
W razie potrzeby utwórz dla każdego elementu zamówienia FoodOrderError. Utwórz maksymalnie 1 błąd dla każdego elementu. W razie potrzeby zwracaj te typy błędów:Typ błędu Przypadek użycia możliwy do odzyskania INVALID Dane produktu lub dane opcji są nieprawidłowe. Nie NOT_FOUND Nie znaleziono elementu lub jednej z opcji. Nie PRICE_CHANGED Zmieniła się cena produktu lub kombinacji dodatku. Ten błąd można potraktować jako możliwych do naprawienia. Tak AVAILABILITY_CHANGED Kwota żądana dla elementów zamówienia lub żadna z opcji jest niedostępna. Tak REQUIREMENTS_NOT_MET Nie osiągnięto minimalnej lub maksymalnej wartości zamówienia. Można to ustalić, sprawdzając, czy cena koszyka jest niższa niż Opłata. eligibleTransactionVolumeMin
czy większa od Opłaty.eligibleTransactionVolumeMax
. Zobacz przykład dotyczący weryfikacji minimalnej wartości zamówienia.Nie Zwraca weryfikację listy elementów lineItems z wartością LineItemType
REGULAR
. Suma cen wszystkich elementów zamówienia w koszyku to cena koszyka (SUBTOTAL
).
Zapoznaj się z przykładami w artykule Sprawdzanie poprawności elementów koszyka.
Oblicz opłaty za obsługę
- Znajdź prawidłowy element Opłata dla usługi na podstawie
eligibleRegion
,validFrom
,validThrough
ipriority
. - Oblicz kwotę opłaty na podstawie tego, czy podmiot został zdefiniowany za pomocą właściwości
price
,percentageOfCart
czypricePerMeter
. - Zwróć opłatę za dostawę lub na wynos jako element LineItem o wartości LineItemType
DELIVERY
lubFEE
. Dodaj opłatę do listy Koszyk.otherItems
.
Zastosuj promocje
- Znajdź element Umowa na podstawie dopasowania wartości Promocja.
coupon
do Umowa.dealCode
. Sprawdź umowę i w razie potrzeby zwracaj błąd FoodOrderError. Takie błędy można uznać za możliwe do naprawienia. W razie potrzeby zwracaj te typy błędów:
Typ błędu Przypadek użycia PROMO_NOT_RECOGNIZED Nie rozpoznano kodu kuponu. PROMO_EXPIRED Umowa wygasła. PROMO_ORDER_INELIGIBLE Zamówienie nie kwalifikuje się do otrzymania kuponu. PROMO_NOT_APPLICABLE Jakikolwiek inny powód. Oblicz kwotę ceny w umowie na podstawie wartości Umowa.
discount
lub Umowa.discountPercentage
.Zastosuj kwotę ceny w umowie, używając łącznej kwoty w koszyku lub łącznej opłaty (w zależności od umowy).
dealType
Zwróć Koszyk.
promotions
z zastosowaną promocją.Zwróć promocję jako element LineItem z wartością LineItemType
DISCOUNT
. Dodaj rabat do listy Koszyk.otherItems
z ujemną ceną.
Wysyłanie odpowiedzi
- Utwórz ProposedOrder.
cart
, jeśli podczas weryfikacji nie wystąpią błędy, koszyk odpowiedzi jest taki sam jak koszyk żądania. - Zwraca listę ProposedOrder.
otherItems
zawierającą podatki, opłaty, napiwkę i rabatę, jeśli mają zastosowanie. Więcej informacji o konfigurowaniu bezpłatnych środków znajdziesz w sekcji Należność. - Uwzględnij właściwość ProposedOrder.
totalPrice
, dodając cenę koszyka, opłaty, rabat, podatki i napiwek. - Zwróć
FoodOrderExtension.
availableFulfillmentOptions
z odpowiednią wartością FulfillmentOption. Zaktualizuj szacowany czas odbioru lub dostawy do oczekiwanego czasu. - Jeśli w wyniku poprzednich testów weryfikacji wystąpiły błędy jedzenia:
- Dołącz StructuredResponse.
error
i listę błędów w pliku FoodErrorExtension.foodOrderErrors
. - Jeśli wszystkie błędy można odzyskać, zwracaj wartość ProposedOrder w polu
correctedProposedOrder
. - Jeśli wszystkie błędy można naprawić, zwróć PaymentOptions w polu
paymentOptions
. - Opcjonalnie uwzględnij wartość
additionalPaymentOptions
, jeśli dostępne są inne opcje płatności i wszystkie błędy można naprawić.
- Dołącz StructuredResponse.
- Jeśli podczas weryfikacji nie wystąpiły żadne błędy weryfikacji, zwróć wartość
proposedOrder
,paymentOptions
w obiekcie CheckoutResponse. Opcjonalnie uwzględnijadditionalPaymentOptions
, jeśli dostępne są inne opcje płatności.