En este documento, se presentan técnicas que puedes usar para mejorar el rendimiento de tu aplicación. En algunos casos, se usan ejemplos de otras API o de API genéricas para ilustrar las ideas presentadas. Sin embargo, se aplican los mismos conceptos a la API de la Billetera de Google.
Compresión con gzip
Una forma fácil y conveniente de reducir el ancho de banda necesario para cada solicitud es habilitar la compresión gzip. Aunque esto requiere un tiempo de CPU adicional para descomprimir los resultados, la compensación con los costos de la red suele hacer que valga la pena.
Si quieres recibir una respuesta codificada en gzip, debes establecer un encabezado de Accept-Encoding
y modificar tu usuario-agente para que contenga la string gzip
. A continuación, se presenta un ejemplo de encabezados HTTP formados de manera correcta para habilitar la compresión gzip:
Accept-Encoding: gzip User-Agent: my program (gzip)
Trabaja con recursos parciales
Otra forma de mejorar el rendimiento de tus llamadas a la API es enviar y recibir solo la parte de los datos que te interesa. Esto permite que tu aplicación evite la transferencia, el análisis y el almacenamiento de campos innecesarios, por lo que pueda usar recursos como la red, la CPU y la memoria con más eficiencia.
Existen los siguientes dos tipos de solicitudes parciales:
- Respuesta parcial: una solicitud en la que especificas qué campos incluir en la respuesta (usa el parámetro de la solicitud de
fields
). - Parche: una solicitud de actualización en la que envías solo los campos que deseas cambiar (usa el verbo HTTP
PATCH
).
En las siguientes secciones, se proporcionan más detalles sobre cómo realizar solicitudes parciales.
Respuesta parcial
De forma predeterminada, el servidor muestra la representación completa de un recurso después de procesar las solicitudes. Para lograr un mejor rendimiento, puedes pedirle al servidor que envíe solo los campos que realmente necesitas y obtener una respuesta parcial en su lugar.
Si quieres solicitar una respuesta parcial, usa el parámetro de solicitud de fields
para especificar los campos que deseas que se muestren. Puedes usar este parámetro con cualquier solicitud que muestre datos de respuesta.
Ten en cuenta que el parámetro de fields
solo afecta a los datos de respuesta; no afecta a los datos que necesitas enviar, si los hay. Para reducir la cantidad de datos que envías cuando modificas recursos, usa una solicitud de parche.
Ejemplo
En el siguiente ejemplo, se muestra el uso del parámetro de fields
con una API “de demostración” genérica (ficticia).
Solicitud simple: esta solicitud HTTP GET
omite el parámetro de fields
y muestra el recurso completo.
https://www.googleapis.com/demo/v1
Respuesta de recursos completos: los datos de recursos completos incluyen los siguientes campos, junto con muchos otros que se omitieron para abreviar.
{ "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", ... }, ... ] }
Solicitud de una respuesta parcial: la siguiente solicitud de este mismo recurso usa el parámetro de fields
para reducir la cantidad de datos que se muestran de manera significativa.
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
Respuesta parcial: en respuesta a la solicitud anterior, el servidor envía una respuesta que contiene solo información similar junto con un arreglo de elementos reducido que incluye solo el título HTML y la información de característica de longitud en cada elemento.
200 OK
{ "kind": "demo", "items": [{ "title": "First title", "characteristics": { "length": "short" } }, { "title": "Second title", "characteristics": { "length": "long" } }, ... ] }
Ten en cuenta que la respuesta es un objeto JSON que incluye solo los campos seleccionados y sus objetos superiores adjuntos.
A continuación, se presentan los detalles sobre cómo dar formato al parámetro de fields
. Luego, se presentan más detalles sobre qué es lo que se muestra en la respuesta.
Resumen de la sintaxis de los parámetros de campos
El formato del valor del parámetro de solicitud de fields
se basa de manera general en la sintaxis de XPath. La sintaxis compatible se resume a continuación y se proporcionan ejemplos adicionales en la siguiente sección.
- Usa una lista separada por comas para seleccionar varios campos.
- Usa
a/b
si quieres seleccionar un campob
que se anida en el campoa
; usaa/b/c
para seleccionar un campoc
anidado enb
.
Excepción: En cuanto a las respuestas a la API que usan wrappers de “datos”, en los que la respuesta se anida en un objeto
data
que luce comodata: { ... }
, no incluyas “data
” en la especificaciónfields
. Incluir el objeto de datos con una especificación de campos comodata/a/b
provoca un error. En su lugar, solo usa una especificación defields
comoa/b
. - Puedes usar un subselector para solicitar un conjunto de subcampos específicos de objetos o arreglos, si colocas las expresiones entre paréntesis “
( )
”.Por ejemplo:
fields=items(id,author/email)
solo muestra el ID del elemento y el correo electrónico del autor para cada elemento del arreglo de elementos. También puedes especificar un subcampo único, en el quefields=items(id)
es equivalente afields=items/id
. - Usa comodines en las selecciones de campo, si es necesario.
Por ejemplo:
fields=items/pagemap/*
selecciona todos los objetos en un pagemap.
Más ejemplos del uso del parámetro de campos
En los siguientes ejemplos, se incluyen descripciones de cómo el valor del parámetro de fields
afecta la respuesta.
Nota: Al igual que con todos los valores de los parámetros de búsqueda, el valor del parámetro de fields
debe estar codificado como URL. Para facilitar la lectura, en los ejemplos de este documento se omite la codificación.
- Identifica los campos que deseas que se muestren o realiza selecciones de campo.
- El valor del parámetro de solicitud de
fields
es una lista de campos separada por comas y cada campo se especifica en relación con la raíz de la respuesta. Por lo tanto, si realizas una operación de lista, la respuesta es una colección y suele incluir un arreglo de recursos. Si realizas una operación que muestra un recurso único, los campos se especifican en relación con ese recurso. Si el campo que seleccionas es un arreglo, o es parte de uno, el servidor muestra la parte seleccionada de todos los elementos del arreglo.
A continuación, se presentan algunos ejemplos a nivel de colección:
Ejemplos Efecto items
Muestra todos los elementos del arreglo de elementos, incluidos todos los campos de cada elemento, pero ningún otro campo. etag,items
Muestra el campo etag
y todos los elementos del arreglo de elementos.items/title
Muestra solo el campo title
para todos los elementos del arreglo de elementos.
Cada vez que se muestra un campo anidado, la respuesta incluye los objetos superiores adjuntos. Los campos superiores no incluyen ningún otro campo secundario, a menos que también se seleccionen de manera explícita.context/facets/label
Muestra solo el campo label
para todos los miembros del arreglofacets
, que se anida en el objetocontext
.items/pagemap/*/title
Para cada elemento del arreglo de elementos, muestra solo el campo title
(si está presente) de todos los objetos que son secundarios depagemap
.
A continuación, se presentan algunos ejemplos a nivel de recursos:Ejemplos Efecto title
Muestra el campo title
del recurso solicitado.author/uri
Muestra el subcampo uri
del objetoauthor
en el recurso solicitado.links/*/href
Muestra el campo href
de todos los objetos que son secundarios delinks
. - Solicita solo las partes de los campos específicos mediante subselecciones.
- De forma predeterminada, si tu solicitud especifica campos particulares, el servidor muestra los objetos o los elementos del arreglo en su totalidad. Puedes especificar una respuesta que incluya solo ciertos subcampos. Para hacerlo, usa la sintaxis de la subselección de “
( )
”, como se muestra en el siguiente ejemplo.Ejemplo Efecto items(title,author/uri)
Muestra solo los valores del title
y eluri
del autor para cada elemento del arreglo de elementos.
Controla las respuestas parciales
Después de que un servidor procesa una solicitud válida que incluye el parámetro de búsqueda de fields
, devuelve un código de estado HTTP 200 OK
, junto con los datos solicitados. Si el parámetro de búsqueda de fields
tiene un error o no es válido, el servidor muestra un código de estado HTTP 400 Bad Request
, junto con un mensaje de error en el que se comunica al usuario qué fue lo que falló con su selección de campos (por ejemplo, "Invalid field selection a/b"
).
A continuación, se presenta el ejemplo de una respuesta parcial que se muestra en la sección de introducción anterior. La solicitud usa el parámetro de fields
para especificar qué campos mostrar.
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
La respuesta parcial se ve de la siguiente manera:
200 OK
{ "kind": "demo", "items": [{ "title": "First title", "characteristics": { "length": "short" } }, { "title": "Second title", "characteristics": { "length": "long" } }, ... ] }
Nota: En cuanto a las API que admiten parámetros de búsqueda para la paginación de datos (maxResults
y nextPageToken
, por ejemplo), usa esos parámetros a fin de reducir los resultados de cada búsqueda a un tamaño administrable. De lo contrario, los aumentos del rendimiento posibles con una respuesta parcial podrían no realizarse.
Parche (actualización parcial)
También puedes evitar el envío de datos innecesarios cuando modificas recursos. Si quieres enviar datos actualizados solo para los campos específicos que modificas, usa el verbo HTTP PATCH
. La semántica de parches descrita en este documento es diferente (y más simple) de lo que era para la implementación anterior de GData de actualización parcial.
En el siguiente ejemplo, se muestra cómo el uso de un parche minimiza los datos que necesitas enviar para realizar una actualización pequeña.
Ejemplo
En este ejemplo, se muestra una solicitud de parche simple para actualizar solo el título de un recurso de API “de demostración” genérica (ficticia). El recurso también tiene un comentario, un conjunto de características, un estado y muchos otros campos, pero esta solicitud solo envía el campo title
, ya que ese es el único campo que se modifica:
PATCH https://www.googleapis.com/demo/v1/324 Authorization: Bearer your_auth_token Content-Type: application/json { "title": "New title" }
Respuesta:
200 OK
{ "title": "New title", "comment": "First comment.", "characteristics": { "length": "short", "accuracy": "high", "followers": ["Jo", "Will"], }, "status": "active", ... }
El servidor muestra un código de estado 200 OK
junto con la representación completa del recurso actualizado. Debido a que solo se incluyó el campo title
en la solicitud de parche, ese es el único valor diferente al anterior.
Nota: Si usas el parámetro de fields
de la respuesta parcial en combinación con el parche, puedes aumentar aún más la eficiencia de tu solicitud de actualización. Una solicitud de parche solo reduce el tamaño de la solicitud. Una respuesta parcial reduce el tamaño de la respuesta. Entonces, para reducir la cantidad de datos enviados en ambas direcciones, usa una solicitud de parche con el parámetro de fields
.
Semántica de una solicitud de parche
El cuerpo de la solicitud de parche incluye solo los campos de recursos que deseas modificar. Cuando especificas un campo, debes incluir cualquier objeto superior adjunto, como los superiores adjuntos se muestran con una respuesta parcial. Los datos modificados que envíes se combinan con los datos para el objeto superior, si es que hay uno.
- Agrega: para agregar un campo que aún no existe, especifica el campo nuevo y su valor.
- Modifica: para modificar el valor de un campo existente, especifica el campo y configúralo en el valor nuevo.
- Borra: para borrar un campo, especifícalo y configúralo como
null
. Por ejemplo,"comment": null
. También puedes borrar un objeto completo (si es mutable), si lo configuras comonull
. Si usas la biblioteca cliente de la API de Java, usaData.NULL_STRING
. Para obtener más información, consulta la página sobre JSON null.
Nota sobre los arreglos: Las solicitudes de parche que contienen arreglos reemplazan el arreglo existente por el que proporcionaste. No puedes modificar, agregar o borrar elementos de un arreglo por etapas.
Usa parches en un ciclo de lectura, modificación, escritura
Comenzar por recuperar una respuesta parcial con los datos que deseas modificar puede ser una práctica útil. En particular, esto es importante para los recursos que usan ETags, ya que debes proporcionar el valor de ETag actual en el encabezado HTTP If-Match
para actualizar el recurso con éxito. Después de obtener los datos, puedes modificar los valores que deseas cambiar y enviar la representación parcial modificada con una solicitud de parche. A continuación, se presenta un ejemplo en el que se supone que el recurso de demostración usa ETags:
GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token
La respuesta parcial es la siguiente información:
200 OK
{ "etag": "ETagString" "title": "New title" "comment": "First comment.", "characteristics": { "length": "short", "level": "5", "followers": ["Jo", "Will"], } }
La siguiente solicitud de parche se basa en esa respuesta. Como se muestra a continuación, también usa el parámetro de fields
para limitar los datos que se muestran en la respuesta del parche:
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. */ }, }
El servidor responde con un código de estado HTTP 200 OK y la representación parcial del recurso actualizado:
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. */ } }
Crea una solicitud de parche directamente
En cuanto a algunas solicitudes de parches, debes realizarlas en función de los datos que recuperaste antes. Por ejemplo, si deseas agregar un elemento a un arreglo y no quieres perder ninguno de los elementos del arreglo existentes, primero debes obtener los datos existentes. De manera similar, si una API usa ETags, debes enviar el valor de ETag anterior con tu solicitud para actualizar el recurso de manera correcta.
Nota: Puedes usar un encabezado HTTP "If-Match: *"
para forzar la aplicación de un parche cuando las ETags están en uso. Si haces esto, no necesitas realizar operaciones de lectura antes de realizar las de escritura.
Para otras situaciones, sin embargo, puedes crear la solicitud de parche directamente, sin recuperar primero los datos existentes. Por ejemplo, puedes configurar con facilidad una solicitud de parche que actualiza un campo a un valor nuevo o agrega un campo nuevo. A continuación, se muestra un ejemplo:
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 } }
Con esta solicitud, si el campo de comentario tiene un valor existente, el valor nuevo lo reemplaza; de lo contrario, se establece en el valor nuevo. De manera similar, si hubiera una característica de volumen, su valor se reemplaza; si no, se crea. Si está establecido, el campo de precisión se quita.
Controla la respuesta a un parche
Después de procesar una solicitud de parche válida, la API muestra un código de respuesta HTTP 200 OK
junto con la representación completa del recurso modificado. Si la API usa ETags, el servidor actualiza los valores de ETag cuando procesa con éxito una solicitud de parche, al igual que lo hace con PUT
.
La solicitud de parche muestra la representación de recursos completa, a menos que uses el parámetro de fields
para reducir la cantidad de datos que se muestran.
Si una solicitud de parche genera un estado de recursos nuevo que no es válido de manera sintáctica o semántica, el servidor muestra un código de estado HTTP 400 Bad Request
o 422 Unprocessable Entity
y el estado de recursos permanece igual. Por ejemplo, si intentas borrar el valor de un campo obligatorio, el servidor muestra un error.
Notación alternativa cuando no se admite el verbo HTTP PATCH
Si tu firewall no permite solicitudes HTTP PATCH
, entonces haz una solicitud HTTP POST
y configura el encabezado de anulación como PATCH
, como se muestra a continuación:
POST https://www.googleapis.com/... X-HTTP-Method-Override: PATCH ...
Diferencia entre parche y actualización
En la práctica, cuando envías datos para una solicitud de actualización que usa el verbo HTTP PUT
, solo necesitas enviar los campos obligatorios o los opcionales; si envías valores para los campos que establece el servidor, se ignoran. Aunque esto puede parecer otra forma de hacer una actualización parcial, este enfoque tiene algunas limitaciones. Con las actualizaciones que usan el verbo HTTP PUT
, la solicitud falla si no proporcionas los parámetros obligatorios y borra los datos establecidos antes si no proporcionas los parámetros opcionales.
Por esta razón, es mucho más seguro usar un parche. Solo debes proporcionar datos para los campos que deseas cambiar; los campos que omites no se borran. La única excepción a esta regla se produce con la repetición de elementos o arreglos: si omites todos, se mantienen tal como están; si proporcionas alguno de ellos, todo el conjunto se reemplaza por el conjunto que proporciones.
Solicitudes en lote a la Billetera de Google
La API de la Billetera de Google admite el agrupamiento de llamadas a la API en lotes para reducir la cantidad de conexiones que debe hacer un cliente. Para obtener más información sobre la solicitud por lotes y de respuesta rápida, consulta Detalles por lotes.
El siguiente código de muestra demuestra el procesamiento de solicitudes por lotes. Java y PHP ejemplos, usa la tarjeta de crédito Google Wallet bibliotecas para simplificar la creación de clases y objetos.
Java
Para comenzar tu integración en Java, consulta nuestra guía completa muestras de código en 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<LoyaltyObject> callback = new JsonBatchCallback<LoyaltyObject>() { // Invoked if the request was successful public void onSuccess(LoyaltyObject 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/loyalty-cards/rest/v1/loyaltyobject LoyaltyObject batchObject = new LoyaltyObject() .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))) .setAccountId("Account ID") .setAccountName("Account name") .setLoyaltyPoints( new LoyaltyPoints() .setLabel("Points") .setBalance(new LoyaltyPointsBalance().setInt(800))); service.loyaltyobject().insert(batchObject).queue(batch, callback); } // Invoke the batch API calls batch.execute(); }
PHP
Para comenzar tu integración en PHP, consulta nuestra documentación muestras de código en 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/loyalty-cards/rest/v1/loyaltyobject $batchObject = new LoyaltyObject([ '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 ]) ], 'accountId' => 'Account ID', 'accountName' => 'Account name', 'loyaltyPoints' => new LoyaltyPoints([ 'balance' => new LoyaltyPointsBalance([ 'int' => 800 ]) ]) ]); $batch->add($this->service->loyaltyobject->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
Para comenzar tu integración en Python, consulta nuestra documentación muestras de código en 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/loyalty-cards/rest/v1/loyaltyobject 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 }], 'accountId': 'Account id', 'accountName': 'Account name', 'loyaltyPoints': { 'label': 'Points', 'balance': { 'int': 800 } } } batch.add(self.client.loyaltyobject().insert(body=batch_object)) # Invoke the batch API calls response = batch.execute() print('Batch complete')
C#
Para comenzar tu integración en C#, consulta nuestra muestras de código en 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/loyalty-cards/rest/v1/loyaltyobject LoyaltyObject batchObject = new LoyaltyObject { 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 } }, AccountId = "Account id", AccountName = "Account name", LoyaltyPoints = new LoyaltyPoints { Label = "Points", Balance = new LoyaltyPointsBalance { Int__ = 800 } } }; data += "--batch_createobjectbatch\n"; data += "Content-Type: application/json\n\n"; data += "POST /walletobjects/v1/loyaltyObject/\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
Para comenzar tu integración en Node, consulta nuestra documentación muestras de código en 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/loyalty-cards/rest/v1/loyaltyobject 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 } ], 'accountId': 'Account id', 'accountName': 'Account name', 'loyaltyPoints': { 'label': 'Points', 'balance': { 'int': 800 } } }; data += '--batch_createobjectbatch\n'; data += 'Content-Type: application/json\n\n'; data += 'POST /walletobjects/v1/loyaltyObject\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
Para comenzar tu integración en Go, consulta nuestras muestras de código completas en GitHub. muestras de código en GitHub.
// Batch create Google Wallet objects from an existing class. func (d *demoLoyalty) batchCreateObjects(issuerId, classSuffix string) { data := "" for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") loyaltyObject := new(walletobjects.LoyaltyObject) loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) loyaltyObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) loyaltyObject.AccountName = "Account name" loyaltyObject.AccountId = "Account id" loyaltyObject.State = "ACTIVE" loyaltyJson, _ := json.Marshal(loyaltyObject) batchObject := fmt.Sprintf("%s", loyaltyJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" data += "POST /walletobjects/v1/loyaltyObject\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) } }