التوافق مع Content API for Shopping

يمكنك استخدام هذا الدليل لدمج Merchant API مع عملية تنفيذ Content API for Shopping الحالية.

تتيح لك Merchant API إمكانية إعداد سير العمل المبرمَج لإدارة العمليات المتعلّقة بالحساب والمنتجات والمستودع في Merchant Center. تشمل حالات استخدام Merchant API ما يلي:

  • إدارة الحسابات المبرمَجة
  • إدارة المنتجات تلقائيًا
  • إدارة المستودع الإعلاني تلقائيًا
  • إعداد التقارير المخصّصة

التحسينات على Content API

تُعدّ Merchant API أفضل من Content API في الجوانب التالية:

البدء

اطّلِع على تصميم Merchant API لمعرفة تفاصيل حول Merchant API وواجهات برمجة التطبيقات الفرعية.

لبدء استخدام Merchant API، غيِّر عناوين URL للطلبات إلى التنسيق التالي:

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

لمزيد من المعلومات، يُرجى الاطّلاع على دليل البدء السريع ومرجع Merchant API.

توفُّر واجهة برمجة التطبيقات gRPC

تتوافق Merchant API مع gRPC وREST. يمكنك استخدام برمجة التطبيقات برمجة التطبيقات لواجهة برمجة التطبيقات Merchant API وREST لواجهة برمجة التطبيقات Content API for Shopping في الوقت نفسه.

تتطلّب مكتبات عملاء Merchant API استخدام مكتبة برمجة التطبيقات gRPC.

راجِع مقالة استخدام gRPC للحصول على مزيد من المعلومات.

التوافق

يصف هذا الدليل التغييرات العامة التي تنطبق على Merchant API بالكامل. يمكنك الاطّلاع على الأدلّة التالية لمعرفة التغييرات التي طرأت على ميزات معيّنة:

تم تصميم Merchant API للعمل مع ميزات الإصدار 2.1 الحالي من Content API في Shopping.

على سبيل المثال، يمكنك استخدام Merchant Inventories API مع عملية التنفيذ الحالية لإصدار 2.1 من Content API for Shopping products. يمكنك استخدام Content API for Shopping لتحميل منتج جديد داخل المتجر (الذي تبيعه في متجر محلي)، ثم استخدام Merchant Inventories API LocalInventory لإدارة المعلومات داخل المتجر لهذا المنتج.

طلبات مجمّعة

لا تتيح Merchant API استخدام الطريقة customBatch المضمّنة في Content API for Shopping. بدلاً من ذلك، يمكنك الاطّلاع على إرسال طلبات متعددة في آنٍ واحد أو تنفيذ طلباتك بشكل غير متزامن.

يوضّح المثال التالي كيفية إدراج إدخال منتج.

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);
  }
}

إذا كنت تستخدِم customBatch في Content API، وتحتاج إلى هذه الميزة في Merchant API، يُرجى إخبارنا بالسبب في ملاحظاتك.

المعرفات

بما يتوافق مع مبادئ تحسين واجهات برمجة التطبيقات في Google، أجرينا بعض التغييرات على المعرّفات لموارد Merchant API.

الاسم يحلّ محلّ المعرّف

تستخدم جميع موارد Merchant API الحقل name كمعرّف فريد لها.

في ما يلي مثال على كيفية استخدام حقل name في مكالماتك:

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

يتم عرض حقل name الجديد هذا كمعرّف المورد لجميع طلبات القراءة والكتابة في Merchant API.

على سبيل المثال، يمكنك تنفيذ طريقة getName() لاسترداد name من مورد، وتخزين الإخراج كمتغيّر بدلاً من إنشاء name من أرقام تعريف التاجر والمورد بنفسك.

حقول العناصر الرئيسية لموارد العناصر الفرعية

في Merchant API، تحتوي جميع الموارد الفرعية على الحقل parent. يمكنك استخدام الحقل parent لتحديد name المورد الذي تريد إدراج المورد الفرعي فيه، بدلاً من تمرير المورد الرئيسي بالكامل. يمكنك أيضًا استخدام حقل parent مع طرق list لسرد الموارد الفرعية لهذا parent.

على سبيل المثال، لعرض مستودعات المنتجات داخل المتجر لمنتج معيّن، حدِّد name المنتج في الحقل parent لطريقة list. في هذه الحالة، يكون product المحدَّد هو parent من موارد LocalInventory المعروضة.

الأنواع

في ما يلي بعض الأنواع الشائعة التي تتم مشاركتها في واجهات برمجة التطبيقات الفرعية لواجهة Merchant API.

السعر

في ما يلي التغييرات التي طرأت على Price في حزمة Merchant Common:

Content API Merchant API
حقل المبلغ value:string amountMicros:int64
حقل العملة currency:string currencyCode:string

يتم الآن تسجيل مبلغ Price بالوحدات الميكرو، حيث يساوي مليون وحدة ميكرو وحدة عملتك العادية.

في Content API for Shopping، كان Price رقمًا عشريًا في شكل سلسلة.

تم تغيير اسم حقل المبلغ من value إلى amountMicros

تم تغيير اسم حقل العملة من currency إلى currencyCode. يبقى التنسيق هو ISO 4217.