Konfigurowanie procesu płatności

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.

CheckoutResponseMessage zwraca niezmodyfikowany koszyk klienta lub błąd.

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ów actions.foodordering.intent.CHECKOUT.
  • Koszyk: pole inputs[0].arguments[0].extension w żądaniu płatności zawiera obiekt Cart, który reprezentuje koszyk klienta.
  • Dostawa lub odbiór: pole rozszerzenia obiektu Cart zawiera obiekt FoodCartExtension, 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.
  • 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: obiekt cart identyczny z koszkiem podanym w CheckoutRequestMessage. Jeśli zawartość koszyka wymaga zmiany, element CheckoutResponseMessage powinien zawierać element FoodErrorExtension z poprawionym elementem ProposedOrder.
    • 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 dla PaymentOptions.

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.

  1. W wniosku odczytaj właściwość FulfillmentOptionInfo, aby ustalić, czy typ realizacji zamówienia to delivery czy pickup.
  2. 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.
    Pamiętaj, że okna specjalne mają pierwszeństwo przed zwykłymi oknami. Zobacz przykłady w sekcji Weryfikacja okna zamówieniatymczasowe usuwanie elementów usługi.
    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

  1. Sprawdź każdy koszyklineItems 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
  2. Zwraca zweryfikowaną listę pozycji zamówienia z parametrem LineItemType.REGULAR Suma wszystkich cen elementów zamówienia w koszyku to cena koszyka lub SUBTOTAL.

Przykłady znajdziesz w sekcji walidacja produktów w koszyku.

Obliczanie opłat za obsługę

  1. Znajdź odpowiednią jednostkę Opłata dla usługi na podstawie wartości pól eligibleRegion, validFrom, validThrough i priority.
  2. Oblicz kwotę opłaty na podstawie tego, czy element został zdefiniowany za pomocą właściwości price, percentageOfCart lub pricePerMeter.
  3. Zwracaj opłatę za dostawę lub wynos jako LineItemLineItemType DELIVERY lub FEE. Dodaj opłatę do listy Koszyk.otherItems

Stosowanie promocji

  1. Znajdź element Deal na podstawie dopasowania wartości Promotion.coupon do wartości Deal.dealCode.
  2. 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.
  3. Oblicz kwotę ceny umowy na podstawie umowydiscount lub umowydiscountPercentage.

  4. Zastosować cenę oferty, używając łącznej kwoty koszyka lub łącznej kwoty opłaty w zależności od oferty.dealType

  5. Zwraca element Cart (koszyk)promotions z zastosowanej promocji.

  6. Zwracaj promocję jako LineItemLineItemType DISCOUNT. Dodaj rabat do listy Koszyk.otherItems z ujemną ceną.

Zwracanie odpowiedzi

  1. Utwórz ProposedOrder.cart Jeśli podczas weryfikacji nie wystąpią żadne błędy, koszyk odpowiedzi będzie taki sam jak koszyk żądania.
  2. 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.
  3. Uwzględnij ProposedOrder.totalPrice, dodając do koszyka cenę, opłaty, rabaty, podatki i napiwki.
  4. Zwracaj FoodOrderExtension.availableFulfillmentOptions z odpowiednią opcją FulfillmentOption. Zaktualizuj szacowany czas odbioru lub dostawy do oczekiwanego czasu.
  5. 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ć.
  6. Jeśli nie ma błędów weryfikacji, zwracaj proposedOrder, paymentOptions w obiekcie CheckoutResponse. Opcjonalnie dodaj additionalPaymentOptions, jeśli dostępne są inne opcje płatności.