Ta sekcja zawiera informacje o sposobie wysyłania do Google ograniczonych czasowo aktualizacji elementów asortymentu. Interfejs API aktualizacji w czasie rzeczywistym umożliwia przekazywanie aktualizacji i usuwanie elementów z zasobów reklamowych piaskownicy lub środowiska produkcyjnego w czasie zbliżonym do rzeczywistego.
Ta funkcja jest przeznaczona przede wszystkim do obsługi aktualizacji, których nie można przewidzieć, takich jak awaryjne zamknięcia dróg, usuwanie pozycji z menu czy aktualizowanie ceny. Te informacje muszą zostać szybko odzwierciedlone w interfejsie Google. Jeśli zmiana nie musi zostać odzwierciedlona od razu, możesz zamiast tego użyć przetwarzania zbiorczego. Aktualizacje w czasie rzeczywistym przetwarzają nie dłużej niż 5 minut.
Wymagania wstępne
Przed wdrożeniem aktualizacji w czasie rzeczywistym należy wykonać te czynności:
- Interfejs Maps Booking API jest włączony:
- W GCP otwórz Interfejsy API i usługi > Biblioteka.
- Wyszukaj „Google Maps Booking API”
- Odszukaj instancję piaskownicy („Google Maps Booking API (Dev)”) i kliknij Włącz.
- Znajdź instancję produkcyjną („Google Maps Booking API”) i kliknij Włącz .
- Zostanie utworzone konto usługi z rolą edytującego w projekcie GCP. Więcej informacji znajdziesz w artykule o konfigurowaniu konta.
- Pliki danych w środowisku produkcyjnym lub piaskownicy są hostowane i pozyskiwane. Więcej informacji znajdziesz w artykule Pozyskiwanie zbiorcze.
- Do uwierzytelniania interfejsu API zalecamy zainstalowanie biblioteki klienta Google w wybranym języku. Użyj „https://www.googleapis.com/auth/mapsbooking” jako zakresu protokołu OAuth. Przykładowe fragmenty kodu znajdujące się poniżej korzystają z tych bibliotek. W przeciwnym razie wymiana tokenów będzie konieczna ręcznie, zgodnie z opisem w sekcji Uzyskiwanie dostępu do interfejsów API Google za pomocą OAuth 2.0.
Opis
Interfejs API aktualizacji w czasie rzeczywistym obsługuje 2 rodzaje operacji. Pierwsza operacja dotyczy aktualizowania istniejących elementów. Druga operacja to usuwanie elementów z zasobów reklamowych. Obie operacje są wykonywane na różnych elementach wymienionych w treści żądania. W jednym wywołaniu interfejsu API możesz zaktualizować maksymalnie 1000 jednostek. Interfejs API akceptuje wszystkie żądania przychodzące i umieszcza je w kolejce do dalszego przetwarzania. Dlatego żądania RTU są przetwarzane asynchronicznie.
Interfejs API aktualizacji w czasie rzeczywistym działa w 2 środowiskach: piaskownicy i środowisku produkcyjnym. Środowisko piaskownicy służy do testowania żądań do interfejsu API i środowiska produkcyjnego do aktualizowania treści widocznej dla użytkowników kompleksowych zamawiania. Nazwy hostów obu środowisk:
- Piaskownica –
partnerdev-mapsbooking.googleapis.com
- Produkcyjna –
mapsbooking.googleapis.com
Punkty końcowe
Interfejs API aktualizacji w czasie rzeczywistym udostępnia 2 punkty końcowe do obsługi przychodzących żądań aktualizacji zasobów reklamowych:
- UPSERT –
/v1alpha/inventory/partners/
PARTNER_ID/feeds/owg.v2/record:batchPush
- USUŃ –
/v1alpha/inventory/partners/
PARTNER_ID/feeds/owg.v2/record:batchDelete
Parametr PARTNER_ID znajdziesz w Centrum działań jako Identyfikator partnera na stronie Konto i użytkownicy, jak widać na zrzucie ekranu poniżej.
Przyjmując 10000001 jako wartość PARTNER_ID jako przykład z powyższego zrzutu ekranu, pełne adresy URL służące do wysyłania żądań do interfejsu API w piaskownicy i środowisku produkcyjnym będą wyglądać jak w poniższych przykładach.
# Sandbox UPSERT
https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchPush
# Sandbox DELETE
https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchDelete
# Production UPSERT
https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchPush
# Production DELETE
https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchDelete
Aktualizuję elementy
Aby zaktualizować encje w zasobach reklamowych, użyj UPSERT punktu końcowego i wysyłaj żądania POST HTTP. Każde żądanie POST musi zawierać parametr PARTNER_ID wraz z ładunkiem JSON zawierającym uporządkowane dane dowolnego typu encji wymienionego w schemacie asortymentowym.
Ładunek żądania upsert
Treść żądania to obiekt JSON z listą rekordów. Każdy rekord odpowiada aktualizowanym elementom. Składa się z pola data_record
z ładunkiem encji zakodowanym w standardzie Base64 oraz z pola generation_timestamp
wskazującego czas aktualizacji jednostki:
{ "records": [ { "data_record":"BASE_64_ENCODED_ENTITY", "generation_timestamp":"UPDATE_TIMESTAMP" } ] }
W powyższym ładunku zastąp to:
BASE_64_ENCODED_ENTITY: ciąg znaków JSON zakodowany w Base64. Zdekodowana encja JSON powinna mieć taką samą strukturę jak w specyfikacji pliku danych, na przykład:
{"@type":"MenuSection","name":"My Updated Menu Section","menuId":{"@id":"10824","displayOrder":1},"@id":"853705"}
UPDATE_TIMESTAMP: pamiętaj, aby podać sygnaturę czasową określającą, kiedy encja została wygenerowana w Twoich systemach backendu. Ta sygnatura czasowa służy do sprawdzania prawidłowej kolejności aktualizacji asortymentu. Jeśli go nie podasz, zostanie ustawione czas otrzymania żądania przez Google. Gdy aktualizujesz encję za pomocą żądania
batchPush
, polegeneration_timestamp
jest używane do obsługi wersji encji. Sprawdź oczekiwany format wartości czasu w relacyjnym schemacie zasobów reklamowych.
Każda prośba o aktualizację w czasie rzeczywistym musi spełniać te warunki:
- Rozmiar treści ładunku nie powinien przekraczać 5 MB. Podobnie jak w przypadku plików danych wsadowych zalecamy usuwanie odstępów, aby można było dopasować więcej danych.
- Żądanie
batchPush
może zawierać maksymalnie 1000 elementów.
Przykłady
Przykład 1. Aktualizowanie informacji o restauracji
Załóżmy, że musisz pilnie zaktualizować numer telefonu do restauracji. Twoja aktualizacja zawiera plik JSON dla całej restauracji.
Przyjrzyjmy się zbiorczemu plikowi danych podobnemu do tego:
{ "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501234570", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 }
W takim przypadku aktualizacja w czasie rzeczywistym za pomocą metody POST HTTP będzie wyglądała następująco:
JSON
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": { "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501234570", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 } "generation_timestamp": "2022-08-19T17:11:10.750Z" } ] }
Base64
To samo dotyczy ładunku zakodowanego w standardzie Base64.
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": "eyJAdHlwZSI6IlJlc3RhdXJhbnQiLCJAaWQiOiJyZXN0YXVyYW50MTIzNDUiLCJuYW1lIjoiU29tZSBSZXN0YXVyYW50IiwidXJsIjoiaHR0cHM6Ly93d3cucHJvdmlkZXIuY29tL3NvbWVyZXN0YXVyYW50IiwidGVsZXBob25lIjoiKzE2NTAxMjM0NTcwIiwic3RyZWV0QWRkcmVzcyI6IjM0NSBTcGVhciBTdCIsImFkZHJlc3NMb2NhbGl0eSI6IlNhbiBGcmFuY2lzY28iLCJhZGRyZXNzUmVnaW9uIjoiQ0EiLCJwb3N0YWxDb2RlIjoiOTQxMDUiLCJhZGRyZXNzQ291bnRyeSI6IlVTIiwibGF0aXR1ZGUiOjM3LjQ3Mjg0MiwibG9uZ2l0dWRlIjotMTIyLjIxNzE0NH0=" "generation_timestamp": "2022-08-19T17:11:10.750Z" } ] }
Przykład 2. Aktualizowanie wielu restauracji
Aby zaktualizować 2 encje restauracji w pojedynczym wywołaniu interfejsu API, żądanie POST HTTP powinno wyglądać tak:
JSON
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": { "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501235555", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 }, "generation_timestamp": "2022-08-19T17:11:10.850Z" }, { "data_record": { "@type": "Restaurant", "@id": "restaurant123", "name": "Some Other Restaurant", "url": "https://www.provider.com/someotherrestaurant", "telephone": "+16501231235", "streetAddress": "385 Spear St", "addressLocality": "San Mateo", "addressRegion": "CA", "postalCode": "94115", "addressCountry": "US" }, "generation_timestamp": "2022-08-19T17:11:10.850Z" } ] }
Base64
To samo dotyczy ładunku zakodowanego w standardzie Base64.
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": "eyJAdHlwZSI6IlJlc3RhdXJhbnQiLCJAaWQiOiJyZXN0YXVyYW50MTIzNDUiLCJuYW1lIjoiU29tZSBSZXN0YXVyYW50IiwidXJsIjoiaHR0cHM6Ly93d3cucHJvdmlkZXIuY29tL3NvbWVyZXN0YXVyYW50IiwidGVsZXBob25lIjoiKzE2NTAxMjM1NTU1Iiwic3RyZWV0QWRkcmVzcyI6IjM0NSBTcGVhciBTdCIsImFkZHJlc3NMb2NhbGl0eSI6IlNhbiBGcmFuY2lzY28iLCJhZGRyZXNzUmVnaW9uIjoiQ0EiLCJwb3N0YWxDb2RlIjoiOTQxMDUiLCJhZGRyZXNzQ291bnRyeSI6IlVTIiwibGF0aXR1ZGUiOjM3LjQ3Mjg0MiwibG9uZ2l0dWRlIjotMTIyLjIxNzE0NH0=", "generation_timestamp": "2022-08-19T17:11:10.850Z" }, { "data_record": "eyJAdHlwZSI6IlJlc3RhdXJhbnQiLCJAaWQiOiJyZXN0YXVyYW50MTIzIiwibmFtZSI6IlNvbWUgT3RoZXIgUmVzdGF1cmFudCIsInVybCI6Imh0dHBzOi8vd3d3LnByb3ZpZGVyLmNvbS9zb21lcmVzdGF1cmFudCIsInRlbGVwaG9uZSI6IisxNjUwMTIzMTIzNSIsInN0cmVldEFkZHJlc3MiOiIzODUgU3BlYXIgU3QiLCJhZGRyZXNzTG9jYWxpdHkiOiJTYW4gTWF0ZW8iLCJhZGRyZXNzUmVnaW9uIjoiQ0EiLCJwb3N0YWxDb2RlIjoiOTQxMTUiLCJhZGRyZXNzQ291bnRyeSI6IlVTIn0=", "generation_timestamp": "2022-08-19T17:11:10.850Z" } ] }
Przykład 3. Aktualizowanie ceny pozycji w menu
Załóżmy, że chcesz zmienić cenę pozycji w menu.
Przyjrzyjmy się zbiorczemu plikowi danych podobnemu do tego:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 2, "priceCurrency": "USD" }
W takim przypadku aktualizacja w czasie rzeczywistym za pomocą metody POST będzie wyglądała tak:
JSON
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": { "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 2, "priceCurrency": "USD" }, "generation_timestamp": "2022-08-19T17:20:10Z" } ] }
Base64
To samo dotyczy ładunku zakodowanego w standardzie Base64.
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": "eyJAdHlwZSI6Ik1lbnVJdGVtT2ZmZXIiLCJAaWQiOiJtZW51aXRlbW9mZmVyNjY4MDI2MiIsInNrdSI6Im9mZmVyLWNvbGEiLCJtZW51SXRlbUlkIjoibWVudWl0ZW04OTY1MzIiLCJwcmljZSI6MiwicHJpY2VDdXJyZW5jeSI6IlVTRCJ9", "generation_timestamp": "2022-08-19T17:20:10Z" } ] }
Dodawanie elementów
Nie używaj aktualizacji w czasie rzeczywistym do dodawania nowych elementów, ponieważ może to spowodować niespójności w danych. Zamiast tego korzystaj z procesu przesyłania plików danych w sposób opisany w sekcji Pozyskiwanie danych zbiorczych.
Usuwanie encji
Aby usunąć encje z zasobów reklamowych, użyj USUŃ punktu końcowego i wyślij żądania POST HTTP. Każde żądanie POST musi zawierać parametr PARTNER_ID wraz z ładunkiem JSON zawierającym identyfikator dowolnej encji w Twoim asortymencie.
Usuń ładunek żądania
Treść żądania usunięcia ma strukturę podobną do żądania o aktualizację.
Ma też listę rekordów z polami data_record
i delete_time
:
{ "records": [ { "data_record":"BASE_64_ENCODED_REFERENCE", "delete_time": "DELETE_TIMESTAMP" } ] }
W powyższym ładunku zastąp to:
BASE_64_ENCODED_REFERENCE: zakodowany w Base64 ciąg JSON odniesienia do usuwanej encji. Odwołanie składa się wyłącznie z typu encji i identyfikatora, na przykład z reprezentacji w formacie JSON odniesienia do MenuSection:
{"@type":"MenuSection","@id":"853705"}
DELETE_TIMESTAMP: pamiętaj, aby podać sygnaturę czasową usunięcia encji w systemie backendu. Wskazuje ona kolejność, w jakiej usunięcie zostanie zastosowane do zasobów reklamowych.
Żądanie batchDelete
może zawierać maksymalnie 1000 elementów.
Przykłady
Przykład 1: usunięcie 2 elementów MenuItem
Aby usunąć 2 pozycje menu w pojedynczym wywołaniu interfejsu API, żądanie POST HTTP powinno wyglądać tak:
JSON
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": { "@type": "MenuItem", "@id": "item_1234" }, "delete_time": "2022-08-21T15:23:00.000Z" }, { "data_record": { "@type": "MenuItem", "@id": "item_5678" }, "delete_time": "2022-08-21T15:23:00.000Z" } ] }
Base64
To samo dotyczy ładunku zakodowanego w standardzie Base64.
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": "eyJAdHlwZSI6Ik1lbnVJdGVtIiwiQGlkIjoiaXRlbV8xMjM0In0=" "delete_time": "2022-08-21T15:23:00.000Z" }, { "data_record": "eyJAdHlwZSI6Ik1lbnVJdGVtIiwiQGlkIjoiaXRlbV81Njc4In0=" "delete_time": "2022-08-21T15:23:00.000Z" }, ] }
Przykład 2. Usuwanie encji Restaurant
Rozważ sytuację, w której chcesz usunąć restaurację z zbiorczego pliku danych. Możesz tylko usunąć element „restauracja”. Nie usuwaj podelementów, takich jak usługi czy menu, ponieważ zostaną usunięte automatycznie.
Przykładowe żądanie usunięcia elementu restauracji o identyfikatorze https://www.provider.com/restaurant/12345
:
JSON
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": { "@type": "Restaurant", "@id": "https://www.provider.com/restaurant/12345" }, "delete_time": "2022-08-19T17:11:10.750Z" } ] }
Base64
To samo dotyczy ładunku zakodowanego w standardzie Base64.
POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete Host: mapsbooking.googleapis.com Content-Type: application/json { "records": [ { "data_record": "ewogICJAdHlwZSI6ICJSZXN0YXVyYW50IiwKICAiQGlkIjogImh0dHBzOi8vd3d3LnByb3ZpZGVyLmNvbS9yZXN0YXVyYW50LzEyMzQ1Igp9" "delete_time": "2022-08-19T17:11:10.750Z" } ] }
Weryfikacja i kody odpowiedzi interfejsu API
Wywołania interfejsu API aktualizacji w czasie rzeczywistym podlegają 2 rodzajom weryfikacji:
Poziom żądania – weryfikacje sprawdzają, czy ładunek jest zgodny ze schematem upsert lub delete, a każdy element
data_record
zawiera pola@id
i@type
. Te kontrole są synchroniczne, a wyniki są zwracane w treści odpowiedzi interfejsu API. Kod odpowiedzi 200 i pusta treść JSON{}
oznaczają, że weryfikacja przebiegła pomyślnie, a encje w żądaniu zostały umieszczone w kolejce do przetworzenia. Kod odpowiedzi inny niż 200 oznacza, że co najmniej 1 z tych weryfikacji nie powiodła się i całe żądanie zostało odrzucone (w tym wszystkie elementy w ładunku). Jeśli na przykład w elemenciedata_record
brakuje elementu@type
, zwracana jest taka odpowiedź o błędzie:{ "error": { "code": 400, "message": "Record:{\"@id\":\"2717/86853/DELIVERY\",\"applicableServiceType\":[\"DELIVERY\",\"TAKEOUT\"],\"menuId\":[{\"@id\":\"2717/DELIVERY\",\"displayOrder\":1},{\"@id\":\"2717/TAKEOUT\",\"displayOrder\":2}],\"name\":\"Salad\",\"offeredById\":[\"2717\"]} has following errors: \nThe entity type could not be extracted from the entity value.\n", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.rpc.DebugInfo", "detail": "[ORIGINAL ERROR] generic::invalid_argument: Failed to parse one or more rtu records. Record:{\"@id\":\"2717/86853/DELIVERY\",\"applicableServiceType\":[\"DELIVERY\",\"TAKEOUT\"],\"menuId\":[{\"@id\":\"2717/DELIVERY\",\"displayOrder\":1},{\"@id\":\"2717/TAKEOUT\",\"displayOrder\":2}],\"name\":\"Salad\",\"offeredById\":[\"2717\"]} has following errors: \nThe entity type could not be extracted from the entity value.\n [google.rpc.error_details_ext] { message: \"Record:{\\\"@id\\\":\\\"2717/86853/DELIVERY\\\",\\\"applicableServiceType\\\":[\\\"DELIVERY\\\",\\\"TAKEOUT\\\"],\\\"menuId\\\":[{\\\"@id\\\":\\\"2717/DELIVERY\\\",\\\"displayOrder\\\":1},{\\\"@id\\\":\\\"2717/TAKEOUT\\\",\\\"displayOrder\\\":2}],\\\"name\\\":\\\"Salad\\\",\\\"offeredById\\\":[\\\"2717\\\"]} has following errors: \\nThe entity type could not be extracted from the entity value.\\n\" }" } ] } }
Na poziomie elementu – każda encja w ładunku jest weryfikowana pod kątem schematu relacji. Problemy napotkane na tym etapie weryfikacji nie są zgłaszane w odpowiedzi interfejsu API. Są one raportowane tylko w panelu raportowania czasu rzeczywistego.
Limity interfejsu API
W przypadku aktualizacji interfejsu API w czasie rzeczywistym obowiązuje limit 1500 żądań co 60 sekund, czyli średnio 25 żądań na sekundę. Po przekroczeniu limitu Google w odpowiedzi wysyła ten komunikat o błędzie:
{ "error": { "code": 429, "message": "Insufficient tokens for quota ...", "status": "RESOURCE_EXHAUSTED", "details": [...] } }
Aby rozwiązać ten problem, ponawiaj próby wywołania w rosnących wykładniczo odstępach czasu, aż się uda. Jeśli regularnie wyczerpujesz limit, możesz uwzględnić więcej elementów w jednym żądaniu do interfejsu API. W jednym wywołaniu interfejsu API możesz uwzględnić maksymalnie 1000 encji.
Przykładowe fragmenty kodu
Poniżej znajdziesz kilka przykładów wykorzystania interfejsu API aktualizacji w czasie rzeczywistym w różnych językach. Te przykłady wykorzystują biblioteki Google Auth Libraries do uwierzytelniania przy użyciu pliku klucza konta usługi wygenerowanego podczas konfiguracji konta. Alternatywne rozwiązania znajdziesz w artykule o używaniu OAuth 2.0 w aplikacjach międzyserwerowych. Rozważ użycie schematu dostępnego w sekcji Generowanie bibliotek klienta, aby wygenerować kod źródłowy dla typów obiektów zasobów reklamowych i aktualizacji w czasie rzeczywistym.
Aktualizuję elementy
Node.js
Ten kod korzysta z biblioteki uwierzytelniania Google dla środowiska Node.js.
/* Sample code for Real-time update batchPush implementation. * * Required libraries: * - google-auth-library */ const {JWT} = require('google-auth-library'); // ACTION REQUIRED: Change this to the path of the service account client secret // file downloaded from the Google Cloud Console. const serviceAccountJson = require('./service-account.json'); // ACTION REQUIRED: Change this to your Partner ID received from Google. // The Partner ID is available on the Partner Portal. const PARTNER_ID = 1234; const HOST = { prod: 'https://mapsbooking.googleapis.com', sandbox: 'https://partnerdev-mapsbooking.googleapis.com' }; // ACTION REQUIRED: Change to 'prod' for production const ENV = 'sandbox'; // Feed name for Order with Google including the version. const FEED_NAME = 'owg.v2'; // Endpoint url const url = `${HOST[ENV]}/v1alpha/inventory/partners/${PARTNER_ID}/feeds/${ FEED_NAME}/record:batchPush`; /** * Send a Real-time update request to update/insert entities */ async function batchUpsert(entities) { /** * Sign JWT token using private key from service account secret file * provided. The client can be created without providing a service account * secret file by implementing Application Default Credentials. * https://github.com/googleapis/google-auth-library-nodejs */ const client = new JWT({ email: serviceAccountJson.client_email, key: serviceAccountJson.private_key, scopes: ['https://www.googleapis.com/auth/mapsbooking'], }); const request = {records: toPushRecords(entities)}; const body = JSON.stringify(request); try { const response = await client.request({ method: 'POST', url, data: body, headers: {'Content-Type': 'application/json'} }); console.log('request body:', body); console.log('response status:', response.status); console.log( 'response data:', response.data); // successful response returns '{}' } catch (error) { console.log('error:', error); } } /** * Maps array of entities to records for batch push requests */ const toPushRecords = (entities) => { return entities.map((entity) => { // Using dateModified to set generation_timestamp. Defaulting to the // current timestamp for records that do not have dateModified. const generation_timestamp = entity.dateModified ? entity.dateModified : new Date().toISOString(); return {data_record: btoa(JSON.stringify(entity)), generation_timestamp}; }); }; // Call batchUpsert with example entities. dateModified is optional and is // used to hold the actual timestamp when the entity was updated/created. batchUpsert([ { '@type': 'MenuItemOffer', '@id': '6680261', 'menuItemId': '18931508', 'price': 15.5, 'priceCurrency': 'USD', 'applicableServiceType': ['DELIVERY', 'TAKEOUT'], 'inventoryLevel': 0, 'dateModified': '2022-06-19T15:43:50.970Z' }, { '@type': 'MenuItemOffer', '@id': '6680262', 'menuItemId': '18931509', 'price': 25.5, 'priceCurrency': 'USD', 'applicableServiceType': ['DELIVERY', 'TAKEOUT'], 'inventoryLevel': 0, 'dateModified': '2022-06-19T15:43:50.970Z' } ]);
Python
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Pythona.
"""Sample code for the Real-time update batchPush implementation.""" # Required libraries: # - google-auth import base64 import datetime import json from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account # ACTION REQUIRED: Change this to the Partner ID received from Google. # Partner ID is available on the Partner Portal. # https://partnerdash.google.com/apps/reservewithgoogle _PARTNER_ID = '1234' # ACTION REQUIRED: Change this to the path of the service account client secret # file downloaded from the Google Cloud Console. _SERVICE_ACCOUNT_KEY_JSON_FILE = 'service-account-creds.json' _HOST_MAP = { 'sandbox': 'https://partnerdev-mapsbooking.googleapis.com', 'prod': 'https://mapsbooking.googleapis.com' } # ACTION REQUIRED: Change to 'prod' for production _ENV = 'sandbox' # Feed name for Order with Google including the version. _FEED_NAME = 'owg.v2' _ENDPOINT = '{}/v1alpha/inventory/partners/{}/feeds/{}/record:batchPush'.format( _HOST_MAP[_ENV], _PARTNER_ID, _FEED_NAME) def batch_upsert(entities): """Makes a batchPush request using the Real-time updates REST service. Args: entities: The list of entity objects to update or add. """ # Creates credentials by providing a json file. Credentials can also be # provided by implementing Application Default Credentials. # https://googleapis.dev/python/google-auth/latest/user-guide.html credentials = service_account.Credentials.from_service_account_file( _SERVICE_ACCOUNT_KEY_JSON_FILE, scopes=['https://www.googleapis.com/auth/mapsbooking']) authorized_session = AuthorizedSession(credentials) # JSON request object batch_request = {'records': [create_push_record(x) for x in entities]} response = authorized_session.post(_ENDPOINT, json=batch_request) print('request body:', json.dumps(batch_request)) print('response status:', response.status_code) print('response data:', response.text) # successful response returns '{}' def create_push_record(entity): """Creates a record from an entity for batchPush requests. Args: entity: The entity object to create the record from. Returns: The constructed record for the batchPush request payload. """ data_bytes = json.dumps(entity).encode('utf-8') base64_bytes = base64.b64encode(data_bytes) # Using dateModified to set generation_timestamp. Defaulting to the # current timestamp for records that do not have dateModified. generation_timestamp = entity.dateModified if 'dateModified' in entity else datetime.datetime.now( ).strftime('%Y-%m-%dT%H:%M:%S.%fZ') return { 'generation_timestamp': generation_timestamp, 'data_record': base64_bytes.decode('utf-8') } # Call batch_upsert with example entities. dateModified is optional and is # used to hold the actual timestamp when the entity was updated/created. batch_upsert([{ '@type': 'MenuItemOffer', '@id': '6680261', 'menuItemId': '18931508', 'price': 15.5, 'priceCurrency': 'USD', 'applicableServiceType': ['DELIVERY', 'TAKEOUT'], 'inventoryLevel': 0, 'dateModified': '2022-06-19T15:43:50.970Z' }, { '@type': 'MenuItemOffer', '@id': '6680262', 'menuItemId': '18931509', 'price': 25.5, 'priceCurrency': 'USD', 'applicableServiceType': ['DELIVERY', 'TAKEOUT'], 'inventoryLevel': 0, 'dateModified': '2022-06-19T15:43:50.970Z' }])
Java
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Javy.
Modele kodu źródłowego klienta w pakietach rtusamples.inventory
i rtusamples.realtime
zostały utworzone zgodnie z instrukcjami w artykule Generowanie bibliotek klienta.
/* * Required Libraries: * - JDK >= 11 * - google-auth-library-oauth2-http */ package rtusamples; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; import java.io.FileInputStream; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.Charset; import java.time.Clock; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import rtusamples.inventory.MenuItemOffer; import rtusamples.inventory.MenuItemOfferType; import rtusamples.inventory.ServiceTypeElement; import rtusamples.realtime.BatchPushGenericRecordRequest; import rtusamples.realtime.GenericRecord; /** Sample code for Real-time update batchPush implementation. */ public final class BasicPush { // ACTION REQUIRED: Change this to your Partner ID received from Google. The Partner ID is // available on the Partner Portal. private static final long PARTNER_ID = 12345678; // ACTION REQUIRED: Change this to the path of the service account client secret file downloaded // from the Google Cloud Console. private static final String JSON_KEY_FULL_PATH = "<path to your JSON credentials>/credentials.json"; // ACTION REQUIRED: Change this to the endpoint that is needed. private static final String ENDPOINT = // "https://partnerdev-mapsbooking.googleapis.com"; // for sandbox "https://mapsbooking.googleapis.com"; // for prod // Feed name for Order with Google including the version. private static final String FEED_NAME = "owg.v2"; private static final ObjectMapper objectMapper = new ObjectMapper(); private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'"); private static final Charset UTF_8 = Charset.forName("UTF-8"); public static void main(String[] args) throws Exception { /** * Create credentials from service account secret file. Alternatively, the credentials can be * created by implementing Application Default Credentials. * https://github.com/googleapis/google-auth-library-java */ // GoogleCredentials sourceCredentials = // GoogleCredentials.getApplicationDefault() // .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking")); // ImpersonatedCredentials credentials = // ImpersonatedCredentials.create( // sourceCredentials, // "fo-test@projectname.iam.gserviceaccount.com", // null, // Arrays.asList("https://www.googleapis.com/auth/mapsbooking"), // 300); GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(JSON_KEY_FULL_PATH)) .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking")); // Create example MenuItemOffer entities, dateModified is optional and is used to hold // the actual timestamp when the entity was updated/created. MenuItemOffer menuItemOfferPizza = new MenuItemOffer(); menuItemOfferPizza.setID("6680261"); menuItemOfferPizza.setType(MenuItemOfferType.MENU_ITEM_OFFER); menuItemOfferPizza.setMenuItemID("18931508"); menuItemOfferPizza.setPrice(15.5); menuItemOfferPizza.setPriceCurrency("USD"); menuItemOfferPizza.setApplicableServiceType( new ServiceTypeElement[] {ServiceTypeElement.TAKEOUT, ServiceTypeElement.DELIVERY}); menuItemOfferPizza.setInventoryLevel(0.0); menuItemOfferPizza.setDateModified("2022-10-07T13:00:00.000Z"); MenuItemOffer menuItemOfferSalad = new MenuItemOffer(); menuItemOfferSalad.setID("6680262"); menuItemOfferSalad.setType(MenuItemOfferType.MENU_ITEM_OFFER); menuItemOfferSalad.setMenuItemID("18931509"); menuItemOfferSalad.setPrice(25.5); menuItemOfferSalad.setPriceCurrency("USD"); menuItemOfferSalad.setApplicableServiceType( new ServiceTypeElement[] {ServiceTypeElement.TAKEOUT, ServiceTypeElement.DELIVERY}); menuItemOfferSalad.setInventoryLevel(0.0); menuItemOfferSalad.setDateModified("2022-10-07T13:00:00.000Z"); // Example array of MenuItemOffer entities to update. List<MenuItemOffer> menuItemOffers = Arrays.asList(menuItemOfferPizza, menuItemOfferSalad); // Create list of GenericRecord from menuItemOffers. List<GenericRecord> menuItemOfferGenericRecords = menuItemOffers.stream() .map( (menuItemOffer) -> toBatchPushRecord(menuItemOffer, menuItemOffer.getDateModified())) .collect(Collectors.toList()); // List of records to be updated/created. List<GenericRecord> recordsToBeUpdated = new ArrayList<>(); // Add list of menuItemOffer generic records. recordsToBeUpdated.addAll(menuItemOfferGenericRecords); // Request object that contains all records. BatchPushGenericRecordRequest batchPushRequest = new BatchPushGenericRecordRequest(); batchPushRequest.setRecords(recordsToBeUpdated.toArray(new GenericRecord[0])); // Execute batchPush request. BasicPush basicPush = new BasicPush(); basicPush.batchPush(batchPushRequest, credentials); } public void batchPush( BatchPushGenericRecordRequest batchPushRequest, GoogleCredentials credentials) throws IOException { credentials.refreshIfExpired(); AccessToken token = credentials.getAccessToken(); String requestBody = objectMapper.writeValueAsString(batchPushRequest); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri( URI.create( String.format( "%s/v1alpha/inventory/partners/%s/feeds/%s/record:batchPush", ENDPOINT, PARTNER_ID, FEED_NAME))) .header("Content-Type", "application/json") .header("Authorization", String.format("Bearer %s", token.getTokenValue())) .POST(BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> response = null; try { response = client.send(request, BodyHandlers.ofString()); System.out.println("Request body:" + requestBody); System.out.println("Response status:" + response.statusCode()); System.out.println("Response body:" + response.body()); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } public static <T> GenericRecord toBatchPushRecord(T entity, String dateModified) { GenericRecord genericRecord = new GenericRecord(); try { String json = objectMapper.writeValueAsString(entity); genericRecord.setDataRecord(Base64.getEncoder().encodeToString(json.getBytes(UTF_8))); // Using dateModified to set generation_timestamp. Defaulting to the // current timestamp for records that do not have dateModified. String generationTimestamp = Optional.ofNullable(dateModified) .orElse(OffsetDateTime.now(Clock.systemUTC()).format(TIMESTAMP_FORMATTER)); genericRecord.setGenerationTimestamp(generationTimestamp); } catch (JsonProcessingException e) { System.out.println(e.getMessage()); } return genericRecord; } }
Usuwanie elementów
Node.js
Ten kod korzysta z biblioteki uwierzytelniania Google dla środowiska Node.js.
/* Sample code for Real-time update batchDelete implementation. * * Required libraries: * - google-auth-library */ const {JWT} = require('google-auth-library'); // ACTION REQUIRED: Change this to the path of the service account client secret // file downloaded from the Google Cloud Console. const serviceAccountJson = require('./service-account.json'); // ACTION REQUIRED: Change this to your Partner ID received from Google. // The Partner ID is available on the Partner Portal. const PARTNER_ID = 1234; const HOST = { prod: 'https://mapsbooking.googleapis.com', sandbox: 'https://partnerdev-mapsbooking.googleapis.com' }; // ACTION REQUIRED: Change to 'prod' for production const ENV = 'sandbox'; // Feed name for Order with Google including the version. const FEED_NAME = 'owg.v2'; // Endpoint url const url = `${HOST[ENV]}/v1alpha/inventory/partners/${PARTNER_ID}/feeds/${ FEED_NAME}/record:batchDelete`; /** * Send a Real-time update request to delete entities */ async function batchDelete(entities) { try { /** * Sign JWT token using private key from service account secret file * provided. The client can be created without providing a service account * secret file by implementing Application Default Credentials. * https://github.com/googleapis/google-auth-library-nodejs */ const client = new JWT({ email: serviceAccountJson.client_email, key: serviceAccountJson.private_key, scopes: ['https://www.googleapis.com/auth/mapsbooking'], }); const request = { records: toDeleteRecords(entities) }; const body = JSON.stringify(request); try { const response = await client.request({ method: 'POST', url, data: body, headers: {'Content-Type': 'application/json'} }); console.log('request body:', body); console.log('response status:', response.status); console.log('response data:', response.data); // successful response returns '{}' } catch (error) { console.log('error:', error); } } /** * Maps array of entities to records for batch delete requests */ const toDeleteRecords = (entities) => { return entities.map((entity) => { // Using dateModified to set delete_time. Defaulting to the current // timestamp for records that do not have dateModified. const delete_time = entity.dateModified ? entity.dateModified : new Date().toISOString(); return {data_record: btoa(JSON.stringify(entity)), delete_time}; }); }; // Call batchDelete with example entities. dateModified is optional and is // used to hold the actual timestamp when the entity was deleted. batchDelete([ { '@type': 'Menu', '@id': '853706', 'dateModified': '2022-06-19T15:43:50.970Z' }, { '@type': 'Menu', '@id': '853705', 'dateModified': '2022-06-19T15:13:00.280Z' } ]);
Python
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Pythona.
"""Sample code for the Real-time update batchDelete implementation.""" # Required libraries: # - google-auth import base64 import datetime import json from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account # ACTION REQUIRED: Change this to the Partner ID received from Google. # Partner ID is available on the Partner Portal. # https://partnerdash.google.com/apps/reservewithgoogle _PARTNER_ID = '1234' # ACTION REQUIRED: Change this to the path of the service account client secret # file downloaded from the Google Cloud Console. _SERVICE_ACCOUNT_KEY_JSON_FILE = 'service-account-creds.json' _HOST_MAP = { 'sandbox': 'https://partnerdev-mapsbooking.googleapis.com', 'prod': 'https://mapsbooking.googleapis.com' } # ACTION REQUIRED: Change to 'prod' for production _ENV = 'sandbox' # Feed name for Order with Google including the version. _FEED_NAME = 'owg.v2' _ENDPOINT = '{}/v1alpha/inventory/partners/{}/feeds/{}/record:batchDelete'.format( _HOST_MAP[_ENV], _PARTNER_ID, _FEED_NAME) def batch_delete(entities): """Makes a batch delete request using the Real-time updates REST service. Args: entities: The list of entity objects to delete. """ # Creates credentials by providing a json file. Credentials can also be # provided by implementing Application Default Credentials. # https://googleapis.dev/python/google-auth/latest/user-guide.html credentials = service_account.Credentials.from_service_account_file( _SERVICE_ACCOUNT_KEY_JSON_FILE, scopes=['https://www.googleapis.com/auth/mapsbooking']) authorized_session = AuthorizedSession(credentials) # JSON request object batch_request = {'records': [create_delete_record(x) for x in entities]} response = authorized_session.post(_ENDPOINT, json=batch_request) print('request body:', json.dumps(batch_request)) print('response status:', response.status_code) print('response data:', response.text) # successful response returns '{}' def create_delete_record(entity): """Creates a record from an entity for batchDelete requests. Args: entity: The entity object to create the record from. Returns: The constructed record for the batchDelete request payload. """ data_bytes = json.dumps(entity).encode('utf-8') base64_bytes = base64.b64encode(data_bytes) # Using dateModified to set delete_time. Defaulting to the current # timestamp for records that do not have dateModified. delete_time = entity.dateModified if 'dateModified' in entity else datetime.datetime.now( ).strftime('%Y-%m-%dT%H:%M:%S.%fZ') return { 'delete_time': delete_time, 'data_record': base64_bytes.decode('utf-8') } # Call batch_delete with example entities. dateModified is optional and is # used to hold the actual timestamp when the entity was deleted. batch_delete([{ '@type': 'Menu', '@id': '853706', 'dateModified': '2022-06-19T13:10:00.000Z' }, { '@type': 'Menu', '@id': '853705', 'dateModified': '2022-06-19T13:30:10.000Z' }])
Java
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Javy.
Modele kodu źródłowego klienta w pakietach rtusamples.inventory
i rtusamples.realtime
zostały utworzone zgodnie z instrukcjami w artykule Generowanie bibliotek klienta.
/* * Required Libraries: * - JDK >= 11 * - google-auth-library-oauth2-http */ package rtusamples; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; import java.io.FileInputStream; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.Charset; import java.time.Clock; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import rtusamples.inventory.Menu; import rtusamples.inventory.MenuType; import rtusamples.realtime.BatchDeleteGenericRecordsRequest; import rtusamples.realtime.GenericDeleteRecord; /** Sample code for the Real-time update batchDelete implementation. */ public final class BasicDelete { // ACTION REQUIRED: Change this to your Partner ID received from Google. The Partner ID is // available on the Partner Portal. private static final long PARTNER_ID = 123456789; // ACTION REQUIRED: Change this to the path of the service account client secret file downloaded // from the Google Cloud Console. private static final String JSON_KEY_FULL_PATH = "<path to your JSON credentials>/credentials.json"; // ACTION REQUIRED: Change this to the endpoint that is needed. private static final String ENDPOINT = "https://partnerdev-mapsbooking.googleapis.com"; // for sandbox // "https://mapsbooking.googleapis.com" // for prod // Feed name for Order with Google including the version. private static final String FEED_NAME = "owg.v2"; private static final ObjectMapper objectMapper = new ObjectMapper(); private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'"); private static final Charset UTF_8 = Charset.forName("UTF-8"); public static void main(String[] args) throws Exception { /** * Create credentials from service account secret file. Alternatively, the credentials can be * created by implementing Application Default Credentials. * https://github.com/googleapis/google-auth-library-java */ // GoogleCredentials sourceCredentials = // GoogleCredentials.getApplicationDefault() // .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking")); // ImpersonatedCredentials credentials = // ImpersonatedCredentials.create( // sourceCredentials, // "fo-test@projectname.iam.gserviceaccount.com", // null, // Arrays.asList("https://www.googleapis.com/auth/mapsbooking"), // 300); GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(JSON_KEY_FULL_PATH)) .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking")); // Create example Menu entities, dateModified is optional and is used to hold // the actual timestamp when the entity was deleted. Menu menuLunch = new Menu(); menuLunch.setID("853705"); menuLunch.setType(MenuType.MENU); menuLunch.setDateModified("2022-09-19T13:10:00.000Z"); Menu menuDinner = new Menu(); menuDinner.setID("853706"); menuDinner.setType(MenuType.MENU); menuDinner.setDateModified("2022-09-19T13:13:10.000Z"); // Example array of Menu entities to update. List<Menu> menus = Arrays.asList(menuLunch, menuDinner); // Create list of GenericDeleteRecord from menus. List<GenericDeleteRecord> menuGenericDeleteRecords = menus.stream() .map((menu) -> toBatchDeleteRecord(menu, menu.getDateModified())) .collect(Collectors.toList()); // List of records to be deleted. List<GenericDeleteRecord> recordsToBeDeleted = new ArrayList<>(); // Add list of menu generic records. recordsToBeDeleted.addAll(menuGenericDeleteRecords); // Request object that contains all records. BatchDeleteGenericRecordsRequest batchDeleteRequest = new BatchDeleteGenericRecordsRequest(); batchDeleteRequest.setRecords(recordsToBeDeleted.toArray(new GenericDeleteRecord[0])); // Execute batchDelete request. BasicDelete basicDelete = new BasicDelete(); basicDelete.batchDelete(batchDeleteRequest, credentials); } public void batchDelete( BatchDeleteGenericRecordsRequest batchDeleteRequest, GoogleCredentials credentials) throws IOException { credentials.refreshIfExpired(); AccessToken token = credentials.getAccessToken(); String requestBody = objectMapper.writeValueAsString(batchDeleteRequest); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri( URI.create( String.format( "%s/v1alpha/inventory/partners/%s/feeds/%s/record:batchDelete", ENDPOINT, PARTNER_ID, FEED_NAME))) .header("Content-Type", "application/json") .header("Authorization", String.format("Bearer %s", token.getTokenValue())) .POST(BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> response = null; try { response = client.send(request, BodyHandlers.ofString()); System.out.println("Request body:" + requestBody); System.out.println("Response status:" + response.statusCode()); System.out.println("Response body:" + response.body()); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } public static <T> GenericDeleteRecord toBatchDeleteRecord(T entity, String dateModified) { GenericDeleteRecord genericRecord = new GenericDeleteRecord(); try { String json = objectMapper.writeValueAsString(entity); genericRecord.setDataRecord(Base64.getEncoder().encodeToString(json.getBytes(UTF_8))); // Using dateModified to set delete_time. Defaulting to the current // timestamp for records that do not have dateModified. String deleteTime = Optional.ofNullable(dateModified) .orElse(OffsetDateTime.now(Clock.systemUTC()).format(TIMESTAMP_FORMATTER)); genericRecord.setDeleteTime(deleteTime); } catch (JsonProcessingException e) { System.out.println(e.getMessage()); } return genericRecord; } }
Przypadki użycia
Podane niżej przypadki użycia to przykłady aktualizacji w czasie rzeczywistym i zbiorczych aktualizacji pliku danych oraz treści na wysokim poziomie w wywołaniu interfejsu API:
Scenariusz | Element do zaktualizowania | Opis i efekty |
---|---|---|
Wyłączanie usługi | Service |
Usługę musisz wyłączyć z nieprzewidzianych powodów. Aktualizacje w czasie rzeczywistym: zaktualizuj dany element Pełne pliki danych: pamiętaj, aby przed kolejnym pobraniem przez Google zaktualizować element z pełnych plików danych, tak aby parametr |
Konkretny produkt jest niedostępny | MenuItemOffer |
Aktualizacje w czasie rzeczywistym: wyślij encję zawierającą element MenuItemOffer z wartością inventoryLevel równą 0 w przypadku danego elementu MenuItem , a wszystkie inne dane bez zmian. |
Zmiana ceny elementu menu | MenuItemOffer |
Aktualizacje w czasie rzeczywistym: wyślij encję MenuItemOffer zawierającą wartość price ustawioną na zaktualizowaną cenę dla danego obiektu MenuItem , a wszystkie inne dane bez zmian. |
Dodaj nowy element najwyższego poziomu Dotyczy tylko encji typów |
Menu , Restaurant , Service |
Możesz na przykład dodać nowe menu do restauracji. Pełne pliki danych: dodaj encję do plików danych i poczekaj na przetwarzanie zbiorcze. |
Trwale usuń element najwyższego poziomu Dotyczy tylko encji typów |
Menu , Restaurant , Service |
Aktualizacje w czasie rzeczywistym: wyślij wyraźne usunięcie. Pełne pliki danych: pamiętaj, aby usunąć element z pełnych plików danych przed kolejnym pobraniem przez Google. W przeciwnym razie zostanie on ponownie dodany. |
Dodaj nowy obszar dostawy na wybranym koncie (Service ) |
ServiceArea |
Wsadowe pliki danych: wyślij problematyczny element ServiceArea z niezmienionymi wszystkimi polami, tak jak w przypadku pełnych plików danych, z nowym obszarem dostawy określonym w parametrach polygon , geoRadius lub postalCode . |
Zaktualizuj szacowany czas dostawy w: Service |
ServiceHours |
Zbiorcze pliki danych: wysyłaj ServiceHours w taki sam sposób jak w plikach danych, ale jego leadTimeMin jest odpowiednio aktualizowany. |
Zaktualizuj ceny dostawy w: Service |
Fee |
Zbiorcze pliki danych: prześlij pełną dostawę Fee z aktualizacją price . |
Zaktualizuj godziny dostawy lub na wynos w: Service |
ServiceHours |
Zbiorcze pliki danych: wysyłaj ServiceHours tak samo jak w plikach danych, ale właściwości opens i closes są odpowiednio aktualizowane. |
Service (zmień minimalną kwotę zamówienia) |
Fee |
Wsadowe pliki danych: wyślij pełne Fee z aktualizacją minPrice |
Trwale usuń MenuItem |
Menu |
Wsadowe pliki danych: wysyłaj MenuItem tak samo jak w plikach danych, ale z wartością parentMenuSectionId pustą.
|
Czasy przetwarzania zadań wsadowych i aktualizacji w czasie rzeczywistym
Encja zaktualizowana lub usunięta za pomocą zbiorczego pliku danych zostanie przetworzona w ciągu 2 godzin, a encja zaktualizowana za pomocą aktualizacji w czasie rzeczywistym – w 5 minut. Nieaktualny element jest usuwany po 14 dniach.
Możesz wysłać do Google:
- wiele zadań wsadowych dziennie, aby zapewnić aktualność zasobów reklamowych; LUB
- Jedno zadanie wsadowe dziennie i aktualizacje w czasie rzeczywistym, aby zapewnić aktualność asortymentu.