نقل البيانات من Content API for Shopping إلى Merchant API

يمكنك استخدام هذا الدليل لنقل عملية تنفيذ Content API for Shopping الحالية إلى Merchant API. للمزيد من المعلومات حول تفاصيل Merchant API وواجهات برمجة التطبيقات الفرعية لها، يُرجى الاطّلاع على تصميم Merchant API.

البدء

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

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

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

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

تتيح لك واجهة برمجة التطبيقات Merchant API تشغيل سير العمل آليًا وتسهيله في Merchant Center، كما توفّر إمكانات محسّنة مقارنةً بـ Content API.

حالات الاستخدام الرئيسية:

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

مجالات التحسين الرئيسية:

دعم gRPC

تتوافق Merchant API مع gRPC وREST. يمكنك استخدام gRPC لواجهة برمجة تطبيقات 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")
            .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، يُرجى إعلامنا بالأسباب في ملاحظاتك.

المعرفات

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

يشير استخدام IDENTIFIER إلى أنّه يتم استخدام حقل ضمن رسالة مورد لتحديد المورد. ويتم إرفاقه بحقل الاسم، راجِع الحقول التي تمثّل أسماء الموارد.

تشير القيمة IDENTIFIER إلى أنّه لا يتم قبول الحقل كمدخل (أي OUTPUT_ONLY) في سياق طريقة الإنشاء، مع أنّه يتم أيضًا اعتباره IMMUTABLE وقبوله كمدخل لطرق التعديل التي تستخدِم المورد كمثال على الإدخال الأساسي: Standard Update (التعديل العادي).

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

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

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

GET https://merchantapi.googleapis.com/products/v1beta/accounts/4321/products/online~en~US~1234

حيث يساوي name accounts/4321/products/online~en~US~1234.

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

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

المحدِّدات

تستخدِم واجهة برمجة التطبيقات Merchant API علامات المد بدلاً من الأقواس المنقوطة كفاصلات.

يقارن الجدول التالي معرّف المنتج لكلّ من Content API وMerchant API:

Content API Merchant API
channel:contentLanguage:feedLabel:offerId. على سبيل المثال، online:en:US:sku123 channel~contentLanguage~feedLabel~offerId. على سبيل المثال، online~en~US~sku123

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

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

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

GET https://merchantapi.googleapis.com/inventories/v1beta/{parent}/localInventories

لاسترداد جميع المستودعات داخل المتجر للمنتج online~en~US~1234 والحساب 4321، سيظهر الطلب على النحو التالي:

GET https://merchantapi.googleapis.com/inventories/v1beta/accounts/4321/products/online~en~US~1234/localInventories

حيث يكون parent يساوي accounts/{account}/products/{product}. يُرجى العلم أنّه في هذه الحالة، تحتوي localInventories على عنصرَين رئيسيَّين مُدرَجين في معرّف اسم (accounts/ وproducts/) لأنّ الحساب هو العنصر الرئيسي لملف موارد المنتج.

الأنواع الشائعة

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

Destination.DestinationEnum

استخدِم الحقل Destination.DestinationEnum للتحكّم في مساحات العرض التي يجب أن تظهر فيها مواردك. يسرد الحقل DestinationEnum كل القيم المتاحة لاستهداف الوجهات. تعمل واجهات برمجة التطبيقات على توحيد DestinationEnum على مستوى واجهات برمجة تطبيقات فرعية متعددة، على سبيل المثال سمات العروض الترويجية.

ReportingContext.ReportingContextEnum

يمثّل الحقل ReportingContext.ReportingContextEnum السياق الذي تنطبق عليه مشاكل حسابك ومنتجاتك. يتم استخدام هذا الحقل في جميع طرق إعداد التقارير (مثل IssueSeverityPerReportingContext).

السعر

في ما يلي التغييرات التي طرأت على 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.