Миграция с Content API для покупок на Merchant API

Вы можете использовать это руководство для миграции существующей реализации Content API for Shopping в Merchant API . Для получения дополнительной информации о деталях Merchant API и его под-API см. Проектирование Merchant API .

Начать

Чтобы начать использовать API Merchant, измените URL-адреса запросов на следующий формат:

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

Более подробную информацию см. в кратком руководстве и справочнике Merchant API.

Улучшения по сравнению с Content API

API Merchant позволяет автоматизировать и оптимизировать рабочие процессы в Merchant Center и предлагает расширенные возможности по сравнению с API Content.

Основные варианты использования:

  • Автоматизированное управление счетами
  • Автоматизированное управление продуктами
  • Автоматизированное управление запасами
  • Пользовательская отчетность

Ключевые области улучшения:

поддержка gRPC

Merchant API поддерживает gRPC и REST. Вы можете использовать gRPC для Merchant API и REST для Content API for Shopping одновременно.

Клиентские библиотеки API Merchant требуют gRPC.

Более подробную информацию см. в обзоре gRPC .

Совместимость

В этом руководстве описываются общие изменения, которые применяются ко всему API Merchant. Для изменений в определенных функциях найдите в навигации раздел Migrate from Content API , в котором перечислены отдельные руководства.

API Merchant предназначен для работы совместно с существующими функциями Content API for Shopping v2.1.

Например, вы можете использовать API Merchant Inventories вместе с существующей реализацией products Content API for Shopping v2.1. Вы можете использовать API Content API for Shopping для загрузки нового локального продукта (который вы продаете в локальном магазине), а затем использовать ресурс LocalInventory API Merchant Inventories для управления информацией в магазине для этого продукта.

Пакетные запросы

API Merchant не поддерживает метод customBatch , представленный в API Content for Shopping. Вместо этого см. раздел Отправка нескольких запросов одновременно или выполнение вызовов асинхронно.

В следующем примере показано, как вставить входные данные о продукте.

Ява

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")
            .addGtin("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 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);
  }
}

Если вы используете customBatch в Content API и вам нужна эта функция для Merchant API, сообщите нам в своем отзыве , почему.

Идентификаторы

Чтобы соответствовать принципам улучшения API Google, мы внесли некоторые изменения в идентификаторы ресурсов API торговцев.

имя заменяет идентификатор

Все ресурсы API торговца используют поле name в качестве своего уникального идентификатора.

Вот пример того, как использовать поле name в ваших вызовах:

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

Это новое поле name возвращается как идентификатор ресурса для всех вызовов чтения и записи в API торговца.

Например, реализуйте метод getName() для извлечения name из ресурса и сохраните вывод как переменную вместо того, чтобы самостоятельно создавать name из идентификаторов продавца и ресурса.

Для HTTP-запросов поле name берется из URL. Оно переопределяет name указанное в теле HTTP-запроса.

Разделители

API торговца использует в качестве разделителей тильды вместо двоеточий.

В следующей таблице сравниваются идентификаторы продуктов для Content API и Merchant API:

API контента API торговца
channel:contentLanguage:feedLabel:offerId . Например, online:en:US:sku123 channel~contentLanguage~feedLabel~offerId . Например, online~en~US~sku123

родительские поля для дочерних ресурсов

В API Merchant все дочерние ресурсы имеют parent поле. Вы можете использовать parent поле, чтобы указать name ресурса, в который нужно вставить дочерний элемент, вместо передачи всего родительского ресурса. Вы также можете использовать parent поле с методами list , чтобы перечислить дочерние ресурсы этого parent .

Например, чтобы перечислить локальные запасы для данного продукта, укажите name продукта в parent поле для метода list . В этом случае данный product является parent возвращаемых ресурсов LocalInventory .

Типы

Ниже приведены некоторые общие типы, используемые во всех подAPI API Merchant.

Цена

Вот что изменилось для Price в пакете Merchant Common:

API контента API торговца
Поле суммы value:string amountMicros:int64
Валютное поле currency:string currencyCode:string

Сумма Price теперь указывается в микро, где 1 миллион микро эквивалентен стандартной единице вашей валюты.

В API контента для покупок Price представляла собой десятичное число в виде строки.

Имя поля суммы изменилось с value на amountMicros

Имя поля валюты изменилось с currency на currencyCode . Формат остался ISO 4217 .