Koleksiyonlar ile düzeninizi koruyun
İçeriği tercihlerinize göre kaydedin ve kategorilere ayırın.
Bu bölümde envanter varlıklarınızın zamana duyarlı güncellemelerini Google'a nasıl gönderebileceğiniz açıklanmıştır. Gerçek zamanlı Updates API'si, güncellemeleri Korumalı Alan veya Üretim envanterinizde neredeyse gerçek zamanlı olarak aktarmanıza ve silmenize olanak tanır.
Bu işlev esas olarak, acil durum kapatmaları, öğeleri menüden kaldırma veya bir menü öğesinin fiyatını güncelleme gibi tahmin edemeyeceğiniz güncellemelerle ilgilidir. Google kullanıcı arayüzünde bu değişiklikler hemen yansıtılmalıdır. Değişikliğinizin hemen yansıtılması gerekmiyorsa bunun yerine toplu besleme özelliğini kullanabilirsiniz. Gerçek zamanlı güncellemeler en fazla beş dakika içinde işlenir.
Ön koşullar
Gerçek zamanlı güncellemeleri uygulamadan önce aşağıdakiler gereklidir:
Korumalı alan örneğini ("Google Maps Booking API'sı (Dev)") bulun ve Etkinleştir'i tıklayın
Üretim örneğini ("Google Haritalar Rezervasyon API'si") bulun ve Etkinleştir'i tıklayın.
GCP projeniz için düzenleyici rolüyle bir hizmet hesabı oluşturulur. Daha fazla bilgi için Hesap kurulumu bölümüne bakın.
Üretim veya korumalı alan veri feed'leri barındırılır ve beslenir. Daha fazla bilgi için Toplu besleme bölümüne bakın.
API kimlik doğrulaması için, seçtiğiniz dilde Google İstemci Kitaplığı'nı yüklemeniz önerilir. OAuth kapsamı olarak "https://www.googleapis.com/auth/mapsbooking" adresini kullanın. Aşağıda verilen kod örnekleri bu kitaplıkları kullanır. Aksi takdirde, jeton değişimlerini Google API'lerine Erişmek için OAuth 2.0'ı Kullanma bölümünde açıklandığı gibi manuel olarak ele almanız gerekir.
Genel bakış
Gerçek zamanlı güncellemeler API'si iki işlem türünü destekler. İlk işlem, mevcut varlıkların güncellenmesidir. Envanterden öğe kaldırmak için ikinci işlem silinir. Her iki işlem de istek gövdesinde listelenen varlık aralığında gerçekleştirilir. Tek bir API çağrısıyla 1.000'e kadar varlıkta güncelleme yapabilirsiniz. API tüm gelen istekleri kabul eder ve işlenmek üzere sıraya koyar.
Bu nedenle, RTU istekleri eşzamansız olarak işlenir.
Gerçek zamanlı Updates API'si iki ortamda çalışır: korumalı alan ve üretim.
Korumalı alan ortamı, OwG kullanıcılarına gösterilen içeriği güncellemek için API isteklerini ve üretim ortamını test etmek amacıyla kullanılır. Her iki ortamın ana makine adları:
Korumalı Alan - partnerdev-mapsbooking.googleapis.com
Prodüksiyon - mapsbooking.googleapis.com
Uç noktalar
Gerçek zamanlı güncellemeler API'si, envanter güncellemeleri için gelen istekleri işlemek üzere iki uç nokta sunar:
Yukarıdaki ekran görüntüsünde PARTNER_ID değeri olarak 10000001 değeri kullanıldığından, korumalı alan ve üretimde API istekleri göndermek için kullanılan tüm URL'ler aşağıdaki örneklerde görünecektir.
# 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
Varlıkları güncelleme
Envanterinizdeki varlıkları güncellemek için UPSERTuç noktasını kullanın ve HTTP POST istekleri gönderin. Her POST isteği, envanter şemasında listelenen varlık türlerinin yapılandırılmış verilerini içeren JSON yüküyle birlikte PARTNER_ID parametresini içermelidir.
Onay isteği yükü
İstek metni, kayıt listesini içeren bir JSON nesnesidir. Her kayıt, güncellenen bir varlığa karşılık gelir. Base64'te kodlanan varlık yükünün ve varlık güncellemesinin zamanını belirten generation_timestamp'nin yer aldığı data_record alanından oluşur:
BASE_64_ENCODED_ENTITY: Varlığın Base64 kodlu JSON dizesi. Kodu çözülmüş varlık JSON, feed spesifikasyonundakiyle aynı yapıya sahip olmalıdır. Örneğin:
{"@type":"MenuSection","name":"My Updated Menu Section","menuId":{"@id":"10824","displayOrder":1},"@id":"853705"}
UPDATE_TIMESTAMP: Varlığın arka uç sistemlerinizde oluşturulduğu anın zaman damgasını eklediğinizden emin olun. Bu zaman damgası, envanter güncellemelerinin doğru sıralanmasını sağlamak için kullanılır. Bu alan eklenmezse Google'ın isteği aldığı saat olarak ayarlanır. batchPush isteği aracılığıyla bir varlık güncellenirken alan sürümü için generation_timestamp alanı kullanılır. İlişkisel envanter şemasında beklenen zaman değerleri biçimine bakın.
Her gerçek zamanlı güncelleme isteğinin aşağıdaki koşulları karşılaması gerekir:
Yük gövdesinin boyutu 5 MB'ı aşmamalıdır. Toplu feed'lerde olduğu gibi, daha fazla veri sığdırmak için boşlukları kaldırmanızı öneririz.
Bir batchPush isteğinde en fazla 1.000 varlık olabilir.
Örnekler
1. Örnek: Bir restoranı güncelleme
Bir restoranın telefon numarasını acil bir şekilde güncellemeniz gerektiğini varsayalım. Güncellemeniz tüm restoranın JSON değerini içerir.
Aşağıdaki gibi görünen bir toplu feed'i değerlendirin:
Yeni varlıklar eklemek için gerçek zamanlı güncellemeleri kullanmayın. Bu durum, tutarsızlıklara neden olabilir. Bunun yerine, toplu feed işlemini toplu besleme için açıklandığı gibi kullanın.
Varlıkları silme
Envanterinizdeki varlıkları silmek için DELETEuç noktayı kullanın ve HTTP POST istekleri gönderin. Her POST isteği, envanterinizdeki herhangi bir varlığın tanımlayıcısını içeren JSON yüküyle birlikte PARTNER_ID parametresini içermelidir.
İstek yükünü sil
Silme isteğinin gövdesi, güncelleme isteğine benzer şekilde yapılandırılır.
Ayrıca data_record ve delete_time alanlarının yer aldığı kayıtların listesini de içerir:
BASE_64_ENCODED_REFERENCE: Kaldırılacak varlığa yapılan referansın Base64 kodlu JSON dizesi. Referans yalnızca öğe türünden ve tanımlayıcıdan oluşur (örneğin, bir MenuSection referansının JSON temsili):
{"@type":"MenuSection","@id":"853705"}
DELETE_TIMESTAMP: Varlığın arka uç sisteminizde silindiği zamanı belirten zaman damgasını eklediğinizden emin olun. Bu zaman damgası, silmenin envantere hangi sırayla uygulanacağını belirlemek için kullanılır.
Bir batchDelete isteğinde en fazla 1.000 varlık olabilir.
Örnekler
1. Örnek: İki MenuItem varlığını kaldırma
Tek bir API çağrısındaki iki menü öğesini kaldırmak için HTTP POST isteği aşağıdaki gibi olur:
Toplu feed'de bir restoranı silmek istediğiniz bir durumu düşünün.
Yalnızca restoran varlığını silmeniz gerekir. Hizmetler ve menüler gibi alt öğeleri otomatik olarak kaldırılmayacağı için silmeyin.
https://www.provider.com/restaurant/12345 kimliğine sahip bir restoran varlığını silmek için örnek istek:
Gerçek zamanlı güncelleme API'sı çağrılarında iki tür doğrulama yapılır:
İstek düzeyinde: Bu doğrulamalar, yükün genel veya silme şemasına uygun olduğunu ve her data_record'nin hem @id hem de @type alanlarını içerdiğini kontrol eder.
Bu kontroller eşzamanlıdır ve sonuçlar API yanıt gövdesinde döndürülür. Bir yanıt kodu 200 ve boş bir JSON gövdesi {}, bu doğrulamaların iletildiği ve bu istekteki varlıkların işlenmek üzere sıraya alındığı anlamına gelir. 200'den farklı bir yanıt kodu, bu doğrulamalardan birinin veya daha fazlasının başarısız olduğu ve isteğin tamamının (yükteki tüm varlıklar dahil) reddedildiği anlamına gelir. Örneğin, bir data_record, @type içermiyorsa aşağıdaki hata yanıtı döndürülür:
{
"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\" }"
}
]
}
}
Varlık düzeyi: Yükteki her varlık, ilişkisel şemaya göre doğrulanır.
Doğrulamanın bu aşamasında karşılaşılan sorunlar API yanıtında raporlanmaz. Bunlar yalnızca RTU Raporları kontrol panelinde raporlanır.
API kotaları
Gerçek zamanlı API güncellemelerinin kotası, her 60 saniyede 1.500 istek veya ortalama 25 istektir. Bir kota aşıldığında, Google aşağıdaki hata mesajıyla yanıt verir:
Bu sorunu çözmek için aramayı, başarılı olana kadar katlanarak daha yüksek aralıklarla deneyin. Kotayı düzenli olarak tüketiyorsanız tek bir API isteğine daha fazla varlık eklemeyi düşünebilirsiniz. Bir API çağrısına en fazla 1.000 varlık ekleyebilirsiniz.
Kod örnekleri
Aşağıda, gerçek zamanlı güncelleme API'sinin çeşitli dillerde nasıl kullanıldığına dair bazı örnekler verilmiştir. Bu örnekler, Hesap kurulumu sırasında oluşturulan bir hizmet hesabı anahtar dosyasıyla kimlik doğrulaması yapmak için Google Auth Kitaplıklarını kullanır.
Alternatif çözümler için Sunucudan Sunucuya Uygulamalar için OAuth 2.0'ı Kullanma.
Envanter ve gerçek zamanlı güncelleme nesne türleri için kaynak kodu oluşturmak üzere İstemci Kitaplıkları Oluşturma'da bulunan şemayı kullanmayı düşünün.
/* 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) {
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: 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'
}]);
"""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'
}])
rtusamples.inventory ve rtusamples.realtime paketlerindeki istemci kaynağı kodu modelleri, İstemci Kitaplıkları Oluşturma bölümündeki adımlar uygulanarak oluşturulmuştur.
/*
* 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;
}
}
/* 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'
}
]);
"""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'
}])
rtusamples.inventory ve rtusamples.realtime paketlerindeki istemci kaynağı kodu modelleri, İstemci Kitaplıkları Oluşturma bölümündeki adımlar uygulanarak oluşturulmuştur.
/*
* 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;
}
}
Kullanım alanları
Aşağıda gerçek zamanlı güncellemelere, toplu feed güncellemelerine ve API çağrısında üst düzey içeriğe dair örnekler verilmiştir:
Senaryo
Güncellenecek varlık
Açıklama ve efektler
Bir hizmeti devre dışı bırakma
Service
Beklenmeyen bir nedenle bir hizmeti devre dışı bırakmanız gerekiyor.
Gerçek zamanlı güncellemeler: Söz konusu Service varlığını isDisabled özelliğini true olarak ayarlayarak güncelleyin, ancak diğer özellikleri aynı tutun.
Tam feed'ler: Google'ın bir sonraki getirmesinden önce isDisabled öğesini true olarak ayarlamak için tam feed'lerdeki varlığı güncellediğinizden emin olun. Aksi takdirde varlık yeniden etkinleştirilir.
Belirli bir ürün stokta yok
MenuItemOffer
Gerçek zamanlı güncellemeler: Kapsayıcı MenuItemOffer
öğesini, belirtilen MenuItem için inventoryLevel 0 olarak ayarlanmış ve diğer tüm veriler değişmeden gönderin.
Menü öğesi fiyat değişikliği
MenuItemOffer
Gerçek zamanlı güncellemeler: Kapsamlı MenuItemOffer varlığını price ile birlikte verilen MenuItem için güncellenmiş fiyata gönderin ve diğer hiçbir veriyi değiştirmeyin.
Yeni üst düzey öğe ekle
Yalnızca Menu, Restaurant ve Service türlerindeki varlıklar için geçerlidir.
Menu, RestaurantService
Örneğin, bir restorana yeni bir menü eklemeniz gerekir.
Tam feed'ler: Varlıkları veri feed'lerinize ekleyin ve toplu beslemeyi bekleyin.
Üst düzey öğeyi kalıcı olarak silme
Yalnızca Menu, Restaurant ve Service türlerindeki varlıklar için geçerlidir.
Menu, RestaurantService
Gerçek zamanlı güncellemeler:Uygunsuz silme isteği gönderin.
Tam feed'ler: Google tarafından getirilen bir sonraki alım işleminden önce varlığı tam feed'lerden kaldırdığınızdan emin olun. Aksi takdirde varlık yeniden eklenir.
Belirli bir Service bölgesinde yeni teslimat bölgesi ekleyin
ServiceArea
Toplu feed'ler: Söz konusu ServiceArea varlığını, tüm feed'lerde olduğu gibi normalde olduğu gibi gönderin. polygon, geoRadius veya postalCode içinde yeni teslimat alanı belirtilir.
Tahmini teslimat süresini Service olarak güncelleyin
ServiceHours
Toplu özet akışları:ServiceHours Özet akışlarıyla aynı şekilde gönderilmesi dışında
leadTimeMin.
Service bölgesindeki teslimat fiyatlarını güncelleyin
Fee
Toplu feed'ler:price güncellenerek tam yayın Fee gönderin.
Service için teslimat veya paket servisi saatlerini güncelleyin
ServiceHours
Toplu feed'ler:ServiceHours feed'lerinde olduğu gibi gönderin. opens ve closes özellikleri de buna göre güncellenir.
Service (min. sipariş tutarını değiştir)
Fee
Toplu feed'ler:minPrice ile birlikte Fee öğesinin tamamını gönderin
MenuItem cihazını kalıcı olarak silin
Menu
Toplu feed'ler:MenuItem öğesini feed'lerdekiyle aynı şekilde gönderin, ancak parentMenuSectionId boş olmalıdır.
Toplu işler ve gerçek zamanlı güncellemeler için işleme süreleri
Toplu feed aracılığıyla güncellenen veya silinen bir varlık 2 saat içinde, gerçek zamanlı güncellemeyle güncellenen varlık ise 5 dakika içinde işlenir. Eski varlık 14 gün içinde silinir.
Google'a şunları gönderebilirsiniz:
Envanterinizi güncel tutmak için günde birden fazla toplu iş VEYA
Envanterinizi güncel tutmak için günde yalnızca bir toplu iş ve gerçek zamanlı güncellemeler.