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 Twojego internetowego usługi zamawiania. Twoja usługa internetowa zweryfikuje te informacje, a potem możesz kontynuować lub wprowadzić zmiany w koszyku.
Obsługa płatności w usłudze internetowej musi odpowiadać na żądania POST. Gdy klient zdecyduje się na dokonanie płatności, Google wyśle do usługi internetowej Zamawianie na końcu i na początku treść żądania JSON w formie CheckoutRequestMessage
, która zawiera szczegóły Cart
klienta. Twoja usługa internetowa odpowiada wtedy wiadomością CheckoutResponseMessage
. Proces ten obrazuje diagram poniżej.
Po otrzymaniu żądania płatności Twoja usługa internetowa typu end-to-end do zamawiania musi:
- Sprawdzanie ważności koszyka na podstawie aktualnych cen i dostępności produktów oraz usług dostawcy.
- Oblicz łączną cenę (w tym rabaty, podatki i opłaty za dostawę).
- W przypadku powodzenia zwróci niezmodyfikowany koszyk.
- Jeśli się nie uda, odpowiedz z komunikatem o błędzie i nową proponowaną kolejność.
Zanim zaczniesz implementować proces płatności, zalecamy zapoznanie się z dokumentacją dotyczącą realizacji zamówień.
Wiadomość z prośbą o dodanie do koszyka
Aby zweryfikować koszyk klienta, gdy ten zdecyduje się na dokonanie płatności, Google wysyła do Twojej usługi internetowej żądanie z treścią w formacie JSON (CheckoutRequestMessage
). Zamówienie klienta jest przesyłane dopiero później w ramach procesu kompleksowego zamawiania.
Dane zawarte w pliku CheckoutRequestMessage
:
- Intencja: pole
inputs[0].intent
każdego elementu treści żądania płatności zawiera wartość ciągu znakówactions.foodordering.intent.CHECKOUT
. - Koszyk: pole
inputs[0].arguments[0].extension
w żądaniu płatności zawiera obiektCart
, który reprezentuje koszyk klienta. - Dostawa lub odbiór: pole rozszerzenia obiektu
Cart
zawiera obiektFoodCartExtension
, który określa właściwości dostawy lub odbioru:- W przypadku zamówień z dostawą obiekt
FoodCartExtension
zawiera adres dostawy. - W przypadku zamówień z odbiorem osobistym obiekt
FoodCartExtension
nie zawiera żadnych informacji o lokalizacji.
- W przypadku zamówień z dostawą obiekt
- Piaskownica: pole
isInSandbox
w żądaniu płatności zawiera wartość logiczną wskazującą, czy transakcja korzysta z płatności w piaskownicy.
Przykład żądania płatności
Oto przykład właściwości 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ą na proces płatności
Po otrzymaniu żądania od usługi kompleksowego zamawiania usługa internetowa procesu płatności musi je przetworzyć i odpowiedzieć za pomocą CheckoutResponseMessage
. Wartość parametru
CheckoutResponseMessage
musi odpowiadać wartości żądania (sukces lub błąd).
Prośba została zrealizowana
Jeśli żądanie wymeldowania się powiedzie, CheckoutResponseMessage
musi zawierać:
ProposedOrder
i
PaymentOptions
:
ProposedOrder
cart
: obiektcart
identyczny z koszkiem podanym wCheckoutRequestMessage
. Jeśli zawartość koszyka wymaga zmiany, elementCheckoutResponseMessage
powinien zawierać elementFoodErrorExtension
z poprawionym elementemProposedOrder
.otherItems
: elementy dodane przez dostawcę, takie jak opłaty za dostawę, podatki i inne opłaty. Może zawierać również napiwek dodany przez użytkownika.totalPrice
: łączna cena zamówienia.extension
:FoodOrderExtension
, który definiuje informacje o realizacji zamówienia, takie jak czas dostawy.
PaymentOptions
- Konfigurowanie przetwarzania płatności omówiono w artykule Konfigurowanie Google Pay.
Dopóki nie wdrożysz przetwarzania płatności, możesz używać w
CheckoutResponseMessage
zastępczego pliku JSON. - Aby dodać do
CheckoutResponseMessage
opcje płatności zastępcze, zapoznaj się z przykładem poniżej, który wykorzystuje przykładową bramkę płatności dlaPaymentOptions
.
- Konfigurowanie przetwarzania płatności omówiono w artykule Konfigurowanie Google Pay.
Dopóki nie wdrożysz przetwarzania płatności, możesz używać w
Przykład odpowiedzi pozytywnej
{
"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": []
}
}
}
]
}
}
}
]
}
}
}
Nieudane żądanie
Jeśli żądanie płatności nie powiedzie się, element CheckoutResponseMessage
musi zawierać element FoodErrorExtension
, który zawiera listę elementów FoodOrderError
, opisujących wszystkie występujące błędy. Jeśli w zamówieniu występują błędy, które można naprawić, takie jak zmiana ceny produktu w koszyku, FoodErrorExtension
musi zawierać correctedProposedOrder
.
Przykład odpowiedzi z błędem
{
"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 procesu płatności
Podczas implementowania płatności należy wykonać podane niżej czynności.
Weryfikowanie usługi
Zwraca wartość FoodOrderError dla pierwszego znalezionego błędu usługi. Nie można ich naprawić, dlatego należy zwrócić pierwszy błąd. Opis nieodwracalnych błędów znajdziesz w sekcji Przetwarzanie błędów.
- W wniosku odczytaj właściwość FulfillmentOptionInfo, aby ustalić, czy typ realizacji zamówienia to
delivery
czypickup
. W razie potrzeby zwraca te typy błędów:
Typ błędu Przypadek użycia INVALID Typ realizacji jest nieprawidłowy. NOT_FOUND Nie znaleziono typu realizacji zamówień. ZAMKNIĘTE - W zamówieniu nie ma żadnych okien OperationHours.
- Zamówienie jest na „jak najszybciej”, a w obecnej chwili nie ma dostępnych ServiceHours na „jak najszybciej”.
- nastąpiło zamknięcie z powodu sytuacji awaryjnej lub usługa
isDisabled
jest dostępne.
UNAVAILABLE_SLOT Zamówienie z wyprzedzeniem nie może zostać zrealizowane. NO_CAPACITY Restauracja jest zajęta i nie przyjmuje w tej chwili zamówień. OUT_OF_SERVICE_AREA zamówienia nie można dostarczyć na adres użytkownika. Przykład znajdziesz w sekcji Weryfikacja adresu dostawy. NO_COURIER_AVAILABLE Zamówienie nie może zostać dostarczone z powodu ograniczonej liczby pracowników odpowiedzialnych za dostawę.
Sprawdzanie i ustalanie ceny koszyka
Sprawdź każdy koszyk
lineItems
i sprawdź go pod kątem aktualnych danych w Twoim systemie lub systemie sprzedawcy. Wartość MenuItemOffer.sku
z elementu pliku danych jest uwzględniana jako LineItem.offerId
W razie potrzeby utwórz błąd FoodOrderError dla każdego elementu zamówienia. Utwórz maksymalnie 1 błąd na każdy element. W razie potrzeby zwraca te typy błędów:Typ błędu Przypadek użycia Odzyskiwanie INVALID Dane produktu lub dowolne dane opcji są nieprawidłowe. Nie NOT_FOUND Nie znaleziono produktu lub żadnej opcji. Nie PRICE_CHANGED Zmieniła się cena produktu lub kombinacji dodatków. Ten błąd można uznać za odwracalny. Tak AVAILABILITY_CHANGED Kwota żądana dla elementów zamówienia lub niektóre opcje są niedostępne. Tak REQUIREMENTS_NOT_MET Nie została osiągnięta minimalna lub maksymalna wielkość zamówienia. Można to sprawdzić, sprawdzając, czy cena w koszyku jest niższa od opłaty. eligibleTransactionVolumeMin
lub wyższa od opłaty.eligibleTransactionVolumeMax
Zobacz przykład w sekcji Weryfikacja minimalnej wartości zamówienia.Nie Zwraca zweryfikowaną listę pozycji zamówienia z parametrem LineItemType.
REGULAR
Suma wszystkich cen elementów zamówienia w koszyku to cena koszyka lubSUBTOTAL
.
Przykłady znajdziesz w sekcji walidacja produktów w koszyku.
Obliczanie opłat za obsługę
- Znajdź odpowiednią jednostkę Opłata dla usługi na podstawie wartości pól
eligibleRegion
,validFrom
,validThrough
ipriority
. - Oblicz kwotę opłaty na podstawie tego, czy element został zdefiniowany za pomocą właściwości
price
,percentageOfCart
lubpricePerMeter
. - Zwracaj opłatę za dostawę lub wynos jako LineItem z LineItemType
DELIVERY
lubFEE
. Dodaj opłatę do listy Koszyk.otherItems
Stosowanie promocji
- Znajdź element Deal na podstawie dopasowania wartości Promotion.
coupon
do wartości Deal.dealCode
. Sprawdź ofertę i w razie potrzeby zwróć błąd FoodOrderError. Te błędy można uznać za odwracalne. W razie potrzeby zwraca te typy błędów:
Typ błędu Przypadek użycia PROMO_NOT_RECOGNIZED Nie udało się rozpoznać kodu kuponu. PROMO_EXPIRED Ważność umowy wygasła. PROMO_ORDER_INELIGIBLE Zamówienie nie kwalifikuje się do rabatu. PROMO_NOT_APPLICABLE Inny powód. Oblicz kwotę ceny umowy na podstawie umowy
discount
lub umowydiscountPercentage
.Zastosować cenę oferty, używając łącznej kwoty koszyka lub łącznej kwoty opłaty w zależności od oferty.
dealType
Zwraca element Cart (koszyk)
promotions
z zastosowanej promocji.Zwracaj promocję jako LineItem z LineItemType
DISCOUNT
. Dodaj rabat do listy Koszyk.otherItems
z ujemną ceną.
Zwracanie odpowiedzi
- Utwórz ProposedOrder.
cart
Jeśli podczas weryfikacji nie wystąpią żadne błędy, koszyk odpowiedzi będzie taki sam jak koszyk żądania. - Zwracać listę ProposedOrder.
otherItems
, w tym podatek, opłaty, napiwek i rabat (jeśli ma zastosowanie). Więcej informacji o konfigurowaniu pozycji napiwek znajdziesz w sekcji Napiwek. - Uwzględnij ProposedOrder.
totalPrice
, dodając do koszyka cenę, opłaty, rabaty, podatki i napiwki. - Zwracaj FoodOrderExtension.
availableFulfillmentOptions
z odpowiednią opcją FulfillmentOption. Zaktualizuj szacowany czas odbioru lub dostawy do oczekiwanego czasu. - Jeśli w ramach poprzednich weryfikacji wystąpiły błędy FoodOrderErrors:
- Uwzględnij StructuredResponse.
error
oraz listę błędów w FoodErrorExtension.foodOrderErrors
- W polu
correctedProposedOrder
zwracaj wartość ProposedOrder, jeśli wszystkie błędy można naprawić. - W polu
paymentOptions
zwracaj PaymentOptions, jeśli wszystkie błędy można naprawić. - Opcjonalnie dołącz
additionalPaymentOptions
, jeśli dostępne są inne opcje płatności i wszystkie błędy można naprawić.
- Uwzględnij StructuredResponse.
- Jeśli nie ma błędów weryfikacji, zwracaj
proposedOrder
,paymentOptions
w obiekcie CheckoutResponse. Opcjonalnie dodajadditionalPaymentOptions
, jeśli dostępne są inne opcje płatności.