API Content for Shopping

Use este guia para integrar a API Merchant à sua implementação da API Content for Shopping.

Primeiros passos

Consulte o design da API Merchant para saber mais sobre a API Merchant e as sub-APIs.

Para começar a usar a API Merchant, mude os URLs de solicitação para o seguinte formato:

https://merchantapi.googleapis.com/{SUB_API}/{VERSION}/{RESOURCE_NAME}:{METHOD}

Consulte o guia de início rápido e a referência da API Merchant para mais informações.

Suporte ao gRPC

A API Merchant oferece suporte a gRPC e REST. É possível usar o gRPC para a API Merchant e o REST para a API Content for Shopping ao mesmo tempo.

As bibliotecas de cliente da API Merchant exigem o gRPC.

Consulte usar o gRPC para mais informações.

Compatibilidade

Este guia descreve mudanças gerais que se aplicam a toda a API Merchant. Consulte os seguintes guias para conferir mudanças em recursos específicos:

A API Merchant foi projetada para funcionar com os recursos atuais da API Content for Shopping v2.1.

Por exemplo, é possível usar a API Merchant Inventories com a implementação atual da API Content v2.1 para Shopping products. Você pode usar a API Content for Shopping para fazer upload de um novo produto local (que você vende em uma loja local) e, em seguida, usar o recurso LocalInventory da API Merchant Inventories para gerenciar as informações desse produto na loja.

Solicitações em lote

A API Merchant não oferece suporte ao método customBatch da API Content for Shopping. Em vez disso, consulte Enviar várias solicitações de uma só vez ou execute suas chamadas de forma assíncrona.

O exemplo a seguir demonstra como inserir uma entrada de produto.

Java

import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.shopping.merchant.products.v1beta.Attributes;
import com.google.shopping.merchant.products.v1beta.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1beta.ProductInput;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1beta.Shipping;
import com.google.shopping.type.Channel.ChannelEnum;
import com.google.shopping.type.Price;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to insert a product input */
public class InsertProductInputAsyncSample {

  private static String getParent(String accountId) {
    return String.format("accounts/%s", accountId);
  }

  private static String generateRandomString() {
    String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    Random random = new Random();
    StringBuilder sb = new StringBuilder(8);
    for (int i = 0; i < 8; i++) {
      sb.append(characters.charAt(random.nextInt(characters.length())));
    }
    return sb.toString();
  }

  private static ProductInput createRandomProduct() {
    Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();

    Shipping shipping =
        Shipping.newBuilder().setPrice(price).setCountry("GB").setService("1st class post").build();

    Shipping shipping2 =
        Shipping.newBuilder().setPrice(price).setCountry("FR").setService("1st class post").build();

    Attributes attributes =
        Attributes.newBuilder()
            .setTitle("A Tale of Two Cities")
            .setDescription("A classic novel about the French Revolution")
            .setLink("https://exampleWebsite.com/tale-of-two-cities.html")
            .setImageLink("https://exampleWebsite.com/tale-of-two-cities.jpg")
            .setAvailability("in stock")
            .setCondition("new")
            .setGoogleProductCategory("Media > Books")
            .setGtin(0, "9780007350896")
            .addShipping(shipping)
            .addShipping(shipping2)
            .build();

    return ProductInput.newBuilder()
        .setChannel(ChannelEnum.ONLINE)
        .setContentLanguage("en")
        .setFeedLabel("CH")
        .setOfferId(generateRandomString())
        .setAttributes(attributes)
        .build();
  }

  public static void asyncInsertProductInput(Config config, String dataSource) throws Exception {

    // Obtains OAuth token based on the user's configuration.
    GoogleCredentials credential = new Authenticator().authenticate();

    // Creates service settings using the credentials retrieved above.
    ProductInputsServiceSettings productInputsServiceSettings =
        ProductInputsServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credential))
            .build();

    // Creates parent to identify where to insert the product.
    String parent = getParent(config.getAccountId().toString());

    // Calls the API and catches and prints any network failures/errors.
    try (ProductInputsServiceClient productInputsServiceClient =
        ProductInputsServiceClient.create(productInputsServiceSettings)) {

      // Creates five insert product input requests with random product IDs.
      List<InsertProductInputRequest> requests = new ArrayList<>(5);
      for (int i = 0; i < 5; i++) {
        InsertProductInputRequest request =
            InsertProductInputRequest.newBuilder()
                .setParent(parent)
                // You can only insert products into datasource types of Input "API" and "FILE", and
                // of Type "Primary" or "Supplemental."
                // This field takes the `name` field of the datasource.
                .setDataSource(dataSource)
                // If this product is already owned by another datasource, when re-inserting, the
                // new datasource will take ownership of the product.
                .setProductInput(createRandomProduct())
                .build();

        requests.add(request);
      }

      System.out.println("Sending insert product input requests");
      List<ApiFuture<ProductInput>> futures =
          requests.stream()
              .map(
                  request ->
                      productInputsServiceClient.insertProductInputCallable().futureCall(request))
              .collect(Collectors.toList());

      // Creates callback to handle the responses when all are ready.
      ApiFuture<List<ProductInput>> responses = ApiFutures.allAsList(futures);
      ApiFutures.addCallback(
          responses,
          new ApiFutureCallback<List<ProductInput>>() {
            @Override
            public void onSuccess(List<ProductInput> results) {
              System.out.println("Inserted products below");
              System.out.println(results);
            }

            @Override
            public void onFailure(Throwable throwable) {
              System.out.println(throwable);
            }
          },
          MoreExecutors.directExecutor());

    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) throws Exception {
    Config config = Config.load();
    // Identifies the data source that will own the product input.
    String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{datasourceId}";

    asyncInsertProductInput(config, dataSource);
  }
}

Se você usa customBatch na API Content e precisa desse recurso para a API Merchant, envie seu feedback.

Identificadores

Para nos alinharmos aos princípios de melhoria de API do Google, fizemos algumas mudanças nos identificadores dos recursos da API Merchant.

O nome substitui o ID

Todos os recursos da API Merchant usam o campo name como identificador exclusivo.

Confira um exemplo de como usar o campo name nas chamadas:

POST https://merchantapi.googleapis.com/inventories/v1beta/{PARENT}/regionalInventories:insert

Esse novo campo name é retornado como o identificador de recursos para todas as chamadas de leitura e gravação na API Merchant.

Por exemplo, implemente um método getName() para extrair o name de um recurso e armazenar a saída como uma variável em vez de criar o name com os IDs do comerciante e do recurso.

campos pai para recursos filhos

Na API Merchant, todos os recursos filhos têm o campo parent. É possível usar o campo parent para especificar o name do recurso para inserir a criança, em vez de transmitir todo o recurso pai. Também é possível usar o campo parent com os métodos list para listar os recursos filhos desse parent.

Por exemplo, para listar inventários locais de um determinado produto, especifique o name do produto no campo parent do método list. Nesse caso, o product fornecido é o parent dos recursos LocalInventory retornados.

Tipos

Confira alguns tipos comuns compartilhados entre as sub-APIs da API Merchant.

Preço

Confira o que mudou para Price no pacote "Comum do comerciante":

API Content API Merchant
Campo "Valor" value:string amountMicros:int64
Campo de moeda currency:string currencyCode:string

O valor de Price agora é registrado em micros, em que 1 milhão de micros é equivalente à unidade padrão da sua moeda.

Na API Content for Shopping, Price era um número decimal na forma de uma string.

O nome do campo de valor mudou de value para amountMicros

O nome do campo de moeda mudou de currency para currencyCode. O formato permanece como ISO 4217.