В этом документе описаны некоторые методы, которые можно использовать для повышения производительности вашего приложения. В некоторых случаях для иллюстрации представленных идей используются примеры из других API или универсальных API. Однако те же самые концепции применимы и к API Google Wallet.
Сжатие с использованием gzip
Простой и удобный способ уменьшить пропускную способность, необходимую для каждого запроса, — это включить сжатие gzip. Хотя это требует дополнительного процессорного времени для распаковки результатов, компромисс с сетевыми издержками обычно очень оправдан.
Для получения ответа в формате gzip необходимо выполнить два действия: установить заголовок Accept-Encoding и изменить пользовательский агент таким образом, чтобы он содержал строку gzip . Вот пример правильно сформированных HTTP-заголовков для включения сжатия gzip:
Accept-Encoding: gzip User-Agent: my program (gzip)
Работа с ограниченными ресурсами
Ещё один способ повысить производительность вызовов API — отправлять и получать только ту часть данных, которая вас интересует. Это позволяет вашему приложению избегать передачи, анализа и хранения ненужных полей, что позволяет более эффективно использовать ресурсы, включая сеть, процессор и память.
Существует два типа частичных запросов:
- Частичный ответ : Запрос, в котором вы указываете, какие поля следует включить в ответ (используйте параметр запроса
fields). - Patch : Запрос на обновление, в котором вы отправляете только те поля, которые хотите изменить (используйте HTTP-метод
PATCH).
Более подробная информация о подаче частичных запросов представлена в следующих разделах.
Частичный ответ
По умолчанию сервер после обработки запросов отправляет полное представление ресурса. Для повышения производительности вы можете попросить сервер отправлять только необходимые поля и получать вместо этого частичный ответ .
Чтобы запросить частичный ответ, используйте параметр запроса fields , чтобы указать поля, которые вы хотите получить. Этот параметр можно использовать с любым запросом, который возвращает данные ответа.
Обратите внимание, что параметр fields влияет только на данные ответа; он не влияет на данные, которые вам необходимо отправить, если таковые имеются. Чтобы уменьшить объем данных, отправляемых при изменении ресурсов, используйте запрос на исправление (patch request).
Пример
В следующем примере показано использование параметра fields с универсальным (вымышленным) API "Demo".
Простой запрос: В этом HTTP GET запросе параметр fields отсутствует, и он возвращает полный ресурс.
https://www.googleapis.com/demo/v1
Полный ответ на запрос ресурса: Полные данные ресурса включают следующие поля, а также многие другие, которые были опущены для краткости.
{
"kind": "demo",
...
"items": [
{
"title": "First title",
"comment": "First comment.",
"characteristics": {
"length": "short",
"accuracy": "high",
"followers": ["Jo", "Will"],
},
"status": "active",
...
},
{
"title": "Second title",
"comment": "Second comment.",
"characteristics": {
"length": "long",
"accuracy": "medium"
"followers": [ ],
},
"status": "pending",
...
},
...
]
} Запрос на частичный ответ: В следующем запросе к этому же ресурсу используется параметр fields , что значительно уменьшает объем возвращаемых данных.
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
Частичный ответ: В ответ на указанный выше запрос сервер отправляет ответ, содержащий только информацию о типе запроса, а также сокращенный массив элементов, включающий только HTML-заголовок и информацию о длине каждого элемента.
200 OK
{
"kind": "demo",
"items": [{
"title": "First title",
"characteristics": {
"length": "short"
}
}, {
"title": "Second title",
"characteristics": {
"length": "long"
}
},
...
]
}Обратите внимание, что ответ представляет собой JSON-объект, содержащий только выбранные поля и окружающие их родительские объекты.
Далее рассматриваются подробности форматирования параметра fields , а затем более подробно описывается, что именно возвращается в ответе.
Краткое описание синтаксиса параметров полей
Формат значения параметра запроса fields в общих чертах основан на синтаксисе XPath. Поддерживаемый синтаксис кратко описан ниже, а дополнительные примеры приведены в следующем разделе.
- Для выбора нескольких полей используйте список, разделенный запятыми.
- Используйте
a/bдля выбора поляb, вложенного в полеa; используйтеa/b/cдля выбора поляcвложенного вb.Исключение: Для ответов API, использующих обертки "data", где ответ вложен в объект
data, имеющий видdata: { ... }, не включайте "data" в спецификациюfields. Включение объекта данных со спецификацией полей, например,data/a/bприводит к ошибке. Вместо этого используйте спецификациюfields, например,a/b. - Используйте подселектор для запроса набора определенных подполей массивов или объектов, заключая выражения в скобки "
( )".Например:
fields=items(id,author/email)возвращает только идентификатор элемента и адрес электронной почты автора для каждого элемента в массиве items. Вы также можете указать одно подполе, гдеfields=items(id)эквивалентноfields=items/id. - При необходимости используйте символы подстановки при выборе полей.
Например:
fields=items/pagemap/*выбирает все объекты в карте страниц.
Дополнительные примеры использования параметра fields
Приведенные ниже примеры описывают, как значение параметра fields влияет на ответ.
Примечание: Как и все значения параметров запроса, значение параметра fields должно быть закодировано в формате URL. Для лучшей читаемости в примерах этого документа кодирование не используется.
- Укажите поля, которые вы хотите получить в результате, или выберите нужные поля .
- Значение параметра запроса
fieldsпредставляет собой список полей, разделенных запятыми, и каждое поле указывается относительно корня ответа. Таким образом, если вы выполняете операцию со списком , ответ представляет собой коллекцию и обычно включает массив ресурсов. Если вы выполняете операцию, которая возвращает один ресурс, поля указываются относительно этого ресурса. Если выбранное вами поле является (или является частью) массива, сервер возвращает выбранную часть всех элементов массива.
Вот несколько примеров на уровне коллекций:Примеры Эффект itemsВозвращает все элементы массива items, включая все поля каждого элемента, но не другие поля. etag,itemsВозвращает как поле etag, так и все элементы массива items.items/titleВозвращает только поле titleдля всех элементов в массиве items.
При возврате вложенного поля ответ включает в себя окружающие его родительские объекты. Родительские поля не включают в себя другие дочерние поля, если они также не выбраны явно.context/facets/labelВозвращает только поле labelдля всех элементов массиваfacets, который, в свою очередь, вложен в объектcontext.items/pagemap/*/titleДля каждого элемента в массиве items возвращает только поле title(если оно присутствует) всех объектов, являющихся дочерними элементамиpagemap.
Вот несколько примеров на уровне ресурсов:Примеры Эффект titleВозвращает поле titleзапрошенного ресурса.author/uriВозвращает подполе uriобъектаauthorв запрошенном ресурсе.links/*/hrefВозвращает поле hrefвсех объектов, являющихся дочерними элементамиlinks. - Запрашивайте только части определенных полей, используя подзапросы .
- По умолчанию, если ваш запрос указывает на определенные поля, сервер возвращает объекты или элементы массива целиком. Вы можете указать ответ, включающий только определенные подполя. Для этого используется синтаксис подвыбора "
( )", как в примере ниже.Пример Эффект items(title,author/uri)Возвращает только значения titleиuriавтора для каждого элемента в массиве items.
Обработка частичных ответов
После обработки сервером корректного запроса, включающего параметр запроса fields , он отправляет обратно код состояния HTTP 200 OK вместе с запрошенными данными. Если параметр запроса fields содержит ошибку или является недействительным по какой-либо другой причине, сервер возвращает код состояния HTTP 400 Bad Request вместе с сообщением об ошибке, указывающим пользователю на ошибку в выборе полей (например, "Invalid field selection a/b" ).
Вот пример частичного ответа, показанный во вводной части выше. В запросе используется параметр fields для указания того, какие поля следует вернуть.
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
Частичный ответ выглядит следующим образом:
200 OK
{
"kind": "demo",
"items": [{
"title": "First title",
"characteristics": {
"length": "short"
}
}, {
"title": "Second title",
"characteristics": {
"length": "long"
}
},
...
]
} Примечание: Для API, поддерживающих параметры запроса для постраничной обработки данных (например, maxResults и nextPageToken ), используйте эти параметры, чтобы уменьшить размер результатов каждого запроса до приемлемого уровня. В противном случае, преимущества в производительности, достигаемые за счет частичного ответа, могут быть не реализованы.
Патч (частичное обновление)
Также можно избежать отправки ненужных данных при изменении ресурсов. Чтобы отправлять обновленные данные только для конкретных полей, которые вы изменяете, используйте HTTP-метод PATCH . Семантика обновления, описанная в этом документе, отличается (и проще), чем та, что использовалась в более старой реализации частичного обновления в GData.
Приведённый ниже короткий пример показывает, как использование команды patch минимизирует объём данных, необходимых для внесения небольшого обновления.
Пример
В этом примере показан простой запрос на изменение только заголовка общего (вымышленного) ресурса API "Demo". Ресурс также содержит комментарий, набор характеристик, статус и множество других полей, но этот запрос отправляет только поле title , поскольку изменяется только это поле:
PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json
{
"title": "New title"
}Ответ:
200 OK
{
"title": "New title",
"comment": "First comment.",
"characteristics": {
"length": "short",
"accuracy": "high",
"followers": ["Jo", "Will"],
},
"status": "active",
...
}Сервер возвращает код состояния 200 OK , а также полное представление обновлённого ресурса. Поскольку в запрос на обновление было включено только поле title , это единственное значение, отличающееся от предыдущего.
Примечание: Использование параметра fields частичного ответа в сочетании с параметром patch позволяет еще больше повысить эффективность запросов на обновление. Запрос patch уменьшает только размер запроса. Частичный ответ уменьшает размер ответа. Поэтому, чтобы уменьшить объем данных, передаваемых в обоих направлениях, используйте запрос patch с параметром fields .
Семантика запроса на исправление
Тело запроса на изменение содержит только те поля ресурса, которые вы хотите изменить. При указании поля необходимо включить все родительские объекты, содержащие эти объекты, так же как и в частичном ответе возвращаются родительские объекты. Измененные данные, которые вы отправляете, объединяются с данными родительского объекта, если таковой имеется.
- Добавить: Чтобы добавить поле, которого еще нет, укажите новое поле и его значение.
- Изменить: Чтобы изменить значение существующего поля, укажите поле и задайте ему новое значение.
- Удаление: Чтобы удалить поле, укажите его и установите значение
null. Например,"comment": null. Вы также можете удалить весь объект (если он изменяемый), установив его значениеnull. Если вы используете клиентскую библиотеку Java API , используйте вместо этогоData.NULL_STRING; подробности см. в разделе JSON null .
Примечание о массивах: Запросы на изменение, содержащие массивы, заменяют существующий массив предоставленным вами. Вы не можете изменять, добавлять или удалять элементы в массиве по частям.
Использование патча в цикле чтение-изменение-запись
Полезно начать с получения частичного ответа с данными, которые вы хотите изменить. Это особенно важно для ресурсов, использующих ETags, поскольку для успешного обновления ресурса необходимо указать текущее значение ETag в заголовке HTTP If-Match . После получения данных вы можете изменить нужные значения и отправить измененное частичное представление обратно с запросом на исправление. Вот пример, предполагающий, что ресурс Demo использует ETags:
GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token
Это частичный ответ:
200 OK
{
"etag": "ETagString"
"title": "New title"
"comment": "First comment.",
"characteristics": {
"length": "short",
"level": "5",
"followers": ["Jo", "Will"],
}
}Следующий запрос на исправление основан на этом ответе. Как показано ниже, он также использует параметр fields для ограничения данных, возвращаемых в ответе на запрос на исправление:
PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token Content-Type: application/json If-Match: "ETagString"
{
"etag": "ETagString"
"title": "", /* Clear the value of the title by setting it to the empty string. */
"comment": null, /* Delete the comment by replacing its value with null. */
"characteristics": {
"length": "short",
"level": "10", /* Modify the level value. */
"followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
"accuracy": "high" /* Add a new characteristic. */
},
}Сервер отвечает HTTP-статусом 200 OK и частичным представлением обновленного ресурса:
200 OK
{
"etag": "newETagString"
"title": "", /* Title is cleared; deleted comment field is missing. */
"characteristics": {
"length": "short",
"level": "10", /* Value is updated.*/
"followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
"accuracy": "high" /* New characteristic is present. */
}
}Создание запроса на исправление напрямую
Для некоторых запросов на внесение изменений необходимо основываться на ранее полученных данных. Например, если вы хотите добавить элемент в массив и не хотите потерять ни один из существующих элементов массива, сначала необходимо получить существующие данные. Аналогично, если API использует ETags, для успешного обновления ресурса необходимо отправить предыдущее значение ETag вместе с запросом.
Примечание: Вы можете использовать HTTP-заголовок "If-Match: *" , чтобы принудительно отправить патч, когда используются ETags. В этом случае вам не нужно будет выполнять чтение перед записью.
Однако в других ситуациях вы можете создать запрос на исправление напрямую, без предварительного получения существующих данных. Например, вы можете легко настроить запрос на исправление, который обновляет поле новым значением или добавляет новое поле. Вот пример:
PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
{
"comment": "A new comment",
"characteristics": {
"volume": "loud",
"accuracy": null
}
}При таком запросе, если поле комментария уже имеет значение, новое значение перезаписывает его; в противном случае ему присваивается новое значение. Аналогично, если существовала характеристика объема, ее значение перезаписывается; если нет, она создается. Поле точности, если оно задано, удаляется.
Обработка ответа на обновление
После обработки действительного запроса на внесение изменений API возвращает HTTP-ответ с кодом 200 OK а также полное описание измененного ресурса. Если API использует ETags, сервер обновляет значения ETags после успешной обработки запроса на внесение изменений, как и в случае с PUT .
Запрос на исправление возвращает полное представление ресурса, если только вы не используете параметр fields для уменьшения объема возвращаемых данных.
Если запрос на изменение приводит к созданию нового состояния ресурса, которое является синтаксически или семантически некорректным, сервер возвращает HTTP-код состояния 400 Bad Request или 422 Unprocessable Entity , и состояние ресурса остается неизменным. Например, если вы попытаетесь удалить значение для обязательного поля, сервер вернет ошибку.
Альтернативная запись, если HTTP-метод PATCH не поддерживается.
Если ваш брандмауэр не разрешает HTTP-запросы PATCH , выполните HTTP-запрос POST и установите заголовок переопределения в PATCH , как показано ниже:
POST https://www.googleapis.com/... X-HTTP-Method-Override: PATCH ...
Разница между патчем и обновлением.
На практике, при отправке данных в запросе на обновление с использованием HTTP PUT , вам нужно отправлять только те поля, которые являются обязательными или необязательными; если вы отправляете значения для полей, которые задаются сервером, они игнорируются. Хотя это может показаться еще одним способом частичного обновления, у этого подхода есть некоторые ограничения. При обновлениях с использованием HTTP PUT запрос завершается с ошибкой, если вы не указываете обязательные параметры, и очищает ранее установленные данные, если вы не указываете необязательные параметры.
По этой причине использовать функцию patch гораздо безопаснее. Вы указываете данные только для тех полей, которые хотите изменить; поля, которые вы пропускаете, не очищаются. Единственное исключение из этого правила касается повторяющихся элементов или массивов: если вы пропускаете все из них, они остаются как есть; если вы указываете хотя бы один из них, весь набор заменяется тем набором, который вы указали.
Пакетные запросы к Google Кошелек
API Google Wallet поддерживает пакетную обработку вызовов API для уменьшения количества соединений, которые должен установить клиент. Дополнительную информацию о структуре пакетных запросов и ответов см. в разделе «Подробности пакетной обработки» .
Приведенный ниже пример кода демонстрирует пакетную обработку запросов. В примерах на Java и PHP используются библиотеки Google Wallet для упрощения создания классов и объектов.
Java
Чтобы начать интеграцию на Java, ознакомьтесь с полными примерами кода на GitHub .
/** * Batch create Google Wallet objects from an existing class. * * @param issuerId The issuer ID being used for this request. * @param classSuffix Developer-defined unique ID for this pass class. */ public void batchCreateObjects(String issuerId, String classSuffix) throws IOException { // Create the batch request client BatchRequest batch = service.batch(new HttpCredentialsAdapter(credentials)); // The callback will be invoked for each request in the batch JsonBatchCallback<GiftCardObject> callback = new JsonBatchCallback<GiftCardObject>() { // Invoked if the request was successful public void onSuccess(GiftCardObject response, HttpHeaders responseHeaders) { System.out.println("Batch insert response"); System.out.println(response.toString()); } // Invoked if the request failed public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) { System.out.println("Error Message: " + e.getMessage()); } }; // Example: Generate three new pass objects for (int i = 0; i < 3; i++) { // Generate a random object suffix String objectSuffix = UUID.randomUUID().toString().replaceAll("[^\\w.-]", "_"); // See link below for more information on required properties // https://developers.google.com/wallet/retail/gift-cards/rest/v1/giftcardobject GiftCardObject batchObject = new GiftCardObject() .setId(String.format("%s.%s", issuerId, objectSuffix)) .setClassId(String.format("%s.%s", issuerId, classSuffix)) .setState("ACTIVE") .setHeroImage( new Image() .setSourceUri( new ImageUri() .setUri( "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Hero image description")))) .setTextModulesData( List.of( new TextModuleData() .setHeader("Text module header") .setBody("Text module body") .setId("TEXT_MODULE_ID"))) .setLinksModuleData( new LinksModuleData() .setUris( Arrays.asList( new Uri() .setUri("http://maps.google.com/") .setDescription("Link module URI description") .setId("LINK_MODULE_URI_ID"), new Uri() .setUri("tel:6505555555") .setDescription("Link module tel description") .setId("LINK_MODULE_TEL_ID")))) .setImageModulesData( List.of( new ImageModuleData() .setMainImage( new Image() .setSourceUri( new ImageUri() .setUri( "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Image module description")))) .setId("IMAGE_MODULE_ID"))) .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value")) .setLocations( List.of( new LatLongPoint() .setLatitude(37.424015499999996) .setLongitude(-122.09259560000001))) .setCardNumber("Card number") .setPin("1234") .setBalance(new Money().setMicros(20000000L).setCurrencyCode("USD")) .setBalanceUpdateTime(new DateTime().setDate("2020-04-12T16:20:50.52-04:00")); service.giftcardobject().insert(batchObject).queue(batch, callback); } // Invoke the batch API calls batch.execute(); }
PHP
Чтобы начать интеграцию на PHP, ознакомьтесь с полными примерами кода на GitHub .
/** * Batch create Google Wallet objects from an existing class. * * @param string $issuerId The issuer ID being used for this request. * @param string $classSuffix Developer-defined unique ID for the pass class. */ public function batchCreateObjects(string $issuerId, string $classSuffix) { // Update the client to enable batch requests $this->client->setUseBatch(true); $batch = $this->service->createBatch(); // Example: Generate three new pass objects for ($i = 0; $i < 3; $i++) { // Generate a random object suffix $objectSuffix = preg_replace('/[^\w.-]/i', '_', uniqid()); // See link below for more information on required properties // https://developers.google.com/wallet/retail/gift-cards/rest/v1/giftcardobject $batchObject = new GiftCardObject([ 'id' => "{$issuerId}.{$objectSuffix}", 'classId' => "{$issuerId}.{$classSuffix}", 'state' => 'ACTIVE', 'heroImage' => new Image([ 'sourceUri' => new ImageUri([ 'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' ]), 'contentDescription' => new LocalizedString([ 'defaultValue' => new TranslatedString([ 'language' => 'en-US', 'value' => 'Hero image description' ]) ]) ]), 'textModulesData' => [ new TextModuleData([ 'header' => 'Text module header', 'body' => 'Text module body', 'id' => 'TEXT_MODULE_ID' ]) ], 'linksModuleData' => new LinksModuleData([ 'uris' => [ new Uri([ 'uri' => 'http://maps.google.com/', 'description' => 'Link module URI description', 'id' => 'LINK_MODULE_URI_ID' ]), new Uri([ 'uri' => 'tel:6505555555', 'description' => 'Link module tel description', 'id' => 'LINK_MODULE_TEL_ID' ]) ] ]), 'imageModulesData' => [ new ImageModuleData([ 'mainImage' => new Image([ 'sourceUri' => new ImageUri([ 'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' ]), 'contentDescription' => new LocalizedString([ 'defaultValue' => new TranslatedString([ 'language' => 'en-US', 'value' => 'Image module description' ]) ]) ]), 'id' => 'IMAGE_MODULE_ID' ]) ], 'barcode' => new Barcode([ 'type' => 'QR_CODE', 'value' => 'QR code value' ]), 'locations' => [ new LatLongPoint([ 'latitude' => 37.424015499999996, 'longitude' => -122.09259560000001 ]) ], 'cardNumber' => 'Card number', 'pin' => '1234', 'balance' => new Money([ 'micros' => 20000000, 'currencyCode' => 'USD' ]), 'balanceUpdateTime' => new DateTime([ 'date' => '2020-04-12T16:20:50.52-04:00' ]) ]); $batch->add($this->service->giftcardobject->insert($batchObject)); } // Make the batch request $batchResponse = $batch->execute(); print "Batch insert response\n"; foreach ($batchResponse as $key => $value) { if ($value instanceof Google_Service_Exception) { print_r($value->getErrors()); continue; } print "{$value->getId()}\n"; } }
Python
Чтобы начать интеграцию на Python, ознакомьтесь с полными примерами кода на GitHub .
def batch_create_objects(self, issuer_id: str, class_suffix: str): """Batch create Google Wallet objects from an existing class. The request body will be a multiline string. See below for information. https://cloud.google.com/compute/docs/api/how-tos/batch#example Args: issuer_id (str): The issuer ID being used for this request. class_suffix (str): Developer-defined unique ID for this pass class. """ batch = self.client.new_batch_http_request() # Example: Generate three new pass objects for _ in range(3): # Generate a random object suffix object_suffix = str(uuid.uuid4()).replace('[^\\w.-]', '_') # See link below for more information on required properties # https://developers.google.com/wallet/retail/gift-cards/rest/v1/giftcardobject batch_object = { 'id': f'{issuer_id}.{object_suffix}', 'classId': f'{issuer_id}.{class_suffix}', 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [{ 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' }], 'linksModuleData': { 'uris': [{ 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' }] }, 'imageModulesData': [{ 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' }], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [{ 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 }], 'cardNumber': 'Card number', 'pin': '1234', 'balance': { 'micros': 20000000, 'currencyCode': 'USD' }, 'balanceUpdateTime': { 'date': '2020-04-12T16:20:50.52-04:00' } } batch.add(self.client.giftcardobject().insert(body=batch_object)) # Invoke the batch API calls response = batch.execute() print('Batch complete')
C#
Чтобы начать интеграцию на C#, ознакомьтесь с полными примерами кода на GitHub .
/// <summary> /// Batch create Google Wallet objects from an existing class. /// </summary> /// <param name="issuerId">The issuer ID being used for this request.</param> /// <param name="classSuffix">Developer-defined unique ID for this pass class.</param> public async void BatchCreateObjects(string issuerId, string classSuffix) { // The request body will be a multiline string // See below for more information // https://cloud.google.com/compute/docs/api/how-tos/batch//example string data = ""; HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", credentials.GetAccessTokenForRequestAsync().Result ); // Example: Generate three new pass objects for (int i = 0; i < 3; i++) { // Generate a random object suffix string objectSuffix = Regex.Replace(Guid.NewGuid().ToString(), "[^\\w.-]", "_"); // See link below for more information on required properties // https://developers.google.com/wallet/retail/gift-cards/rest/v1/giftcardobject GiftCardObject batchObject = new GiftCardObject { Id = $"{issuerId}.{objectSuffix}", ClassId = $"{issuerId}.{classSuffix}", State = "ACTIVE", HeroImage = new Image { SourceUri = new ImageUri { Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Hero image description" } } }, TextModulesData = new List<TextModuleData> { new TextModuleData { Header = "Text module header", Body = "Text module body", Id = "TEXT_MODULE_ID" } }, LinksModuleData = new LinksModuleData { Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri> { new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "http://maps.google.com/", Description = "Link module URI description", Id = "LINK_MODULE_URI_ID" }, new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "tel:6505555555", Description = "Link module tel description", Id = "LINK_MODULE_TEL_ID" } } }, ImageModulesData = new List<ImageModuleData> { new ImageModuleData { MainImage = new Image { SourceUri = new ImageUri { Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Image module description" } } }, Id = "IMAGE_MODULE_ID" } }, Barcode = new Barcode { Type = "QR_CODE", Value = "QR code" }, Locations = new List<LatLongPoint> { new LatLongPoint { Latitude = 37.424015499999996, Longitude = -122.09259560000001 } }, CardNumber = "Card number", Pin = "1234", Balance = new Money { Micros = 20000000, CurrencyCode = "USD" }, BalanceUpdateTime = new Google.Apis.Walletobjects.v1.Data.DateTime { Date = "2020-04-12T16:20:50.52-04:00" } }; data += "--batch_createobjectbatch\n"; data += "Content-Type: application/json\n\n"; data += "POST /walletobjects/v1/giftCardObject/\n\n"; data += JsonConvert.SerializeObject(batchObject) + "\n\n"; } data += "--batch_createobjectbatch--"; // Invoke the batch API calls HttpRequestMessage batchObjectRequest = new HttpRequestMessage( HttpMethod.Post, "https://walletobjects.googleapis.com/batch"); batchObjectRequest.Content = new StringContent(data); batchObjectRequest.Content.Headers.ContentType = new MediaTypeHeaderValue( "multipart/mixed"); // `boundary` is the delimiter between API calls in the batch request batchObjectRequest.Content.Headers.ContentType.Parameters.Add( new NameValueHeaderValue("boundary", "batch_createobjectbatch")); HttpResponseMessage batchObjectResponse = httpClient.Send( batchObjectRequest); string batchObjectContent = await batchObjectResponse .Content .ReadAsStringAsync(); Console.WriteLine("Batch insert response"); Console.WriteLine(batchObjectContent); }
Node.js
Чтобы начать интеграцию в Node, ознакомьтесь с полными примерами кода на GitHub .
/** * Batch create Google Wallet objects from an existing class. * * @param {string} issuerId The issuer ID being used for this request. * @param {string} classSuffix Developer-defined unique ID for this pass class. */ async batchCreateObjects(issuerId, classSuffix) { // See below for more information // https://cloud.google.com/compute/docs/api/how-tos/batch#example let data = ''; let batchObject; let objectSuffix; // Example: Generate three new pass objects for (let i = 0; i < 3; i++) { // Generate a random object suffix objectSuffix = uuidv4().replace('[^\w.-]', '_'); // See link below for more information on required properties // https://developers.google.com/wallet/retail/gift-cards/rest/v1/giftcardobject batchObject = { 'id': `${issuerId}.${objectSuffix}`, 'classId': `${issuerId}.${classSuffix}`, 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [ { 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' } ], 'linksModuleData': { 'uris': [ { 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' } ] }, 'imageModulesData': [ { 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' } ], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [ { 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 } ], 'cardNumber': 'Card number', 'pin': '1234', 'balance': { 'micros': 20000000, 'currencyCode': 'USD' }, 'balanceUpdateTime': { 'date': '2020-04-12T16:20:50.52-04:00' } }; data += '--batch_createobjectbatch\n'; data += 'Content-Type: application/json\n\n'; data += 'POST /walletobjects/v1/giftCardObject\n\n'; data += JSON.stringify(batchObject) + '\n\n'; } data += '--batch_createobjectbatch--'; // Invoke the batch API calls let response = await this.client.context._options.auth.request({ url: 'https://walletobjects.googleapis.com/batch', method: 'POST', data: data, headers: { // `boundary` is the delimiter between API calls in the batch request 'Content-Type': 'multipart/mixed; boundary=batch_createobjectbatch' } }); console.log('Batch insert response'); console.log(response); }
Идти
Чтобы начать интеграцию на Go, обратитесь к нашим полным примерам кода на GitHub .
// Batch create Google Wallet objects from an existing class. func (d *demoGiftcard) batchCreateObjects(issuerId, classSuffix string) { data := "" for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") giftcardObject := new(walletobjects.GiftCardObject) giftcardObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) giftcardObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) giftcardObject.State = "ACTIVE" giftcardObject.CardNumber = "Card number" giftcardJson, _ := json.Marshal(giftcardObject) batchObject := fmt.Sprintf("%s", giftcardJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" data += "POST /walletobjects/v1/giftCardObject\n\n" data += batchObject + "\n\n" } data += "--batch_createobjectbatch--" res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) } else { b, _ := io.ReadAll(res.Body) fmt.Printf("Batch insert response:\n%s\n", b) } }