تحديثات في الوقت الفعلي

يصف هذا القسم كيفية إرسال تحديثات لمستودعك في الوقت المناسب. الجهات الخارجية إلى Google. تتيح لك واجهة برمجة التطبيقات للتحديثات الفورية إرسال التحديثات وحذفها. والكيانات في مستودع وضع الحماية أو مستودع الإنتاج في الوقت الفعلي تقريبًا.

هذه الوظيفة مخصصة في المقام الأول للتحديثات التي لا يمكنك توقعها، مثل عمليات الإغلاق الطارئة أو إزالة السلع من القائمة أو تعديل السعر لعنصر في القائمة، والذي يجب أن ينعكس بسرعة في واجهة مستخدم Google. في حال التغيير على الفور، يمكنك استخدام عرض البيانات بشكل مجمّع بدلاً من ذلك تتم معالجة التحديثات في الوقت الفعلي في لا تزيد عن خمس دقائق.

المتطلبات الأساسية

يجب تقديم العناصر التالية قبل تنفيذ التحديثات في الوقت الفعلي:

  1. تم تفعيل واجهة برمجة تطبيقات حجز الخرائط:
    • في Google Cloud Platform، انتقِل إلى واجهات برمجة التطبيقات الخدمات > المكتبة
    • ابحث عن "Google Maps Booking API"
      . تحديد موقع واجهات برمجة تطبيقات الحجز في خرائط Google
    • ابحث عن مثيل Sandbox ("واجهة برمجة تطبيقات الحجز في خرائط Google (Dev)") وانقر على تفعيل
    • ابحث عن مثيل الإنتاج ("واجهة برمجة تطبيقات الحجز في خرائط Google") وانقر على تفعيل
      تفعيل واجهة برمجة تطبيقات الحجز في خرائط Google
  2. يتم إنشاء حساب خدمة بدور المحرِّر لمشروع Google Cloud Platform. بالنسبة المزيد من التفاصيل، راجع إعداد الحساب:
  3. تتم استضافة ونقل خلاصات بيانات الإنتاج أو وضع الحماية. لمزيد من التفاصيل، راجِع العرض المجمَّع.
  4. بالنسبة إلى مصادقة واجهة برمجة التطبيقات، يوصى بتثبيت مكتبة برامج Google باللغة خِيَار. استخدام "https://www.googleapis.com/auth/mapsbooking" كبروتوكول OAuth النطاق. وتستخدم عيّنات التعليمات البرمجية أدناه هذه المكتبات. وإلا، عليك التعامل مع عمليات تبادل الرموز المميّزة يدويًا كما هو موضّح في استخدام OAuth 2.0 للوصول إلى Google APIs

نظرة عامة

تتيح واجهة برمجة التطبيقات للتحديثات في الوقت الفعلي نوعين من العمليات. العملية الأولى هي لتأكيد تحديث الكيانات الحالية. تشير رسالة الأشكال البيانية العملية الثانية هي حذف لإزالة الكيانات من مستودعك. كلاهما يتم إجراء العمليات على مجموعة من الكيانات المدرجة في نص الطلب. إِنْتَ إمكانية إجراء تعديلات على ما يصل إلى 1,000 عنصر في طلب بيانات واحد لواجهة برمجة التطبيقات. تقبل واجهة برمجة التطبيقات جميع الطلبات الواردة ويضعها في قائمة انتظار لمزيد من المعالجة. ولذلك تتم معالجة طلبات RTU بشكل غير متزامن.

تعمل واجهة برمجة التطبيقات للتحديثات في الوقت الفعلي في بيئتين هما: وضع الحماية والإنتاج. يتم استخدام بيئة Sandbox لاختبار طلبات واجهة برمجة التطبيقات والإنتاج لتحديث المحتوى المرئي للمستخدمين النهائيين للطلب. أسماء المضيفين كلتا البيئتين:

  • وضع الحماية - partnerdev-mapsbooking.googleapis.com
  • الإنتاج - mapsbooking.googleapis.com

نقاط النهاية

تعرض واجهة برمجة التطبيقات للتحديثات في الوقت الفعلي نقطتَي نهاية للتعامل مع الطلبات الواردة لتحديثات المخزون:

  • UPSERT - /v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
  • حذف - /v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete

يمكن العثور على المعلمة PARTNER_ID في مركز الإجراءات يظهر على أنه رقم تعريف الشريك على صفحة الحساب والمستخدمين، كما هو موضح في لقطة الشاشة أدناه.

رقم تعريف الشريك على "بوابة الشريك"

لنفترض أن 10000001 هي قيمة PARTNER_ID كمثال من لقطة الشاشة أعلاه، عناوين URL الكاملة لإرسال طلبات واجهة برمجة التطبيقات في وضع الحماية النهائية في الأمثلة أدناه.

# Sandbox UPSERT
https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchPush
# Sandbox DELETE
https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchDelete
# Production UPSERT
https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchPush
# Production DELETE
https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/owg.v2/record:batchDelete

تعديل الكيانات

لتعديل الكيانات في مستودعك، استخدِم UPSERT UPSERT. ونرسل طلبات HTTP POST. يجب أن يتضمن كل طلب POST معلَمة PARTNER_ID مع حمولة JSON التي تحتوي على البيانات المنظَّمة من أي نوع عنصر مُدرَج في مخطط المستودع.

حمولة طلب التحديث

نص الطلب هو كائن JSON يضم قائمة بالسجلات. كل سجلّ مع كيان يتم تحديثه. تتألف من الحقل data_record مع ترميز حمولة الكيان في Base64 وgeneration_timestamp يشير إلى وقت تعديل الكيان:

  {
    "records": [
      {
        "data_record":"BASE_64_ENCODED_ENTITY",
        "generation_timestamp":"UPDATE_TIMESTAMP"
      }
    ]
  }

في الحمولة أعلاه، استبدِل ما يلي:

  • BASE_64_ENCODED_ENTITY: سلسلة JSON المرمّزة من Base64 . يجب أن يكون للكيان JSON الذي تم فك ترميزه نفس البنية كما في مواصفات الخلاصة، على سبيل المثال:

    {"@type":"MenuSection","name":"My Updated Menu Section","menuId":{"@id":"10824","displayOrder":1},"@id":"853705"}
  • UPDATE_TIMESTAMP: احرص على تضمين الطابع الزمني لوقت الذي تم إنشاؤه في أنظمتك الخلفية. يُستخدم هذا الطابع الزمني في ضمان الترتيب الصحيح لتحديثات المخزون. إذا لم يتم تضمين هذا الحقل، سيتم ضبطه على الوقت الذي تتلقى فيه Google الطلب. عند التحديث كيان من خلال طلب batchPush، فإن الحقل generation_timestamp هو يُستخدم في إعداد نُسخ الكيان. يمكنك الاطّلاع على توقّعات تنسيق قيم الوقت في المستودع العلائقي Google.

يجب أن يستوفي كل طلب تعديل في الوقت الفعلي الشروط التالية:

  • يجب ألا يتجاوز حجم نص الحمولة 5 ميغابايت. على غرار الإجراء المجمّع الخلاصات، نقترح إزالة المسافات البيضاء بهدف ملاءمة المزيد من البيانات.
  • ويمكن إدخال ما يصل إلى 1,000 كيان في طلب batchPush.

أمثلة

المثال 1: تعديل معلومات مطعم

لنفترض أنك بحاجة بشكل عاجل إلى تحديث رقم هاتف مطعم. يحتوي التحديث على ملف JSON للمطعم بأكمله.

فكّر في خلاصة مجمّعة تشبه ما يلي:

{
  "@type": "Restaurant",
  "@id": "restaurant12345",
  "name": "Some Restaurant",
  "url": "https://www.provider.com/somerestaurant",
  "telephone": "+16501234570",
  "streetAddress": "345 Spear St",
  "addressLocality": "San Francisco",
  "addressRegion": "CA",
  "postalCode": "94105",
  "addressCountry": "US",
  "latitude": 37.472842,
  "longitude": -122.217144
}
  

عندها، ستكون عملية التحديث في الوقت الفعلي من خلال HTTP POST على النحو التالي:

JSON

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": {
        "@type": "Restaurant",
        "@id": "restaurant12345",
        "name": "Some Restaurant",
        "url": "https://www.provider.com/somerestaurant",
        "telephone": "+16501234570",
        "streetAddress": "345 Spear St",
        "addressLocality": "San Francisco",
        "addressRegion": "CA",
        "postalCode": "94105",
        "addressCountry": "US",
        "latitude": 37.472842,
        "longitude": -122.217144
      }
      "generation_timestamp": "2022-08-19T17:11:10.750Z"
    }
  ]
}
    

Base64

المثال نفسه مع حمولة بيانات بترميز Base64

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": "eyJAdHlwZSI6IlJlc3RhdXJhbnQiLCJAaWQiOiJyZXN0YXVyYW50MTIzNDUiLCJuYW1lIjoiU29tZSBSZXN0YXVyYW50IiwidXJsIjoiaHR0cHM6Ly93d3cucHJvdmlkZXIuY29tL3NvbWVyZXN0YXVyYW50IiwidGVsZXBob25lIjoiKzE2NTAxMjM0NTcwIiwic3RyZWV0QWRkcmVzcyI6IjM0NSBTcGVhciBTdCIsImFkZHJlc3NMb2NhbGl0eSI6IlNhbiBGcmFuY2lzY28iLCJhZGRyZXNzUmVnaW9uIjoiQ0EiLCJwb3N0YWxDb2RlIjoiOTQxMDUiLCJhZGRyZXNzQ291bnRyeSI6IlVTIiwibGF0aXR1ZGUiOjM3LjQ3Mjg0MiwibG9uZ2l0dWRlIjotMTIyLjIxNzE0NH0="
      "generation_timestamp": "2022-08-19T17:11:10.750Z"
    }
  ]
}
    

المثال 2: تعديل معلومات مطاعم متعدّدة

لتعديل كيانَين للمطعم في طلب بيانات واحد من واجهة برمجة التطبيقات، يجب إدخال طلب HTTP POST سيكون على النحو التالي:

JSON

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": {
        "@type": "Restaurant",
        "@id": "restaurant12345",
        "name": "Some Restaurant",
        "url": "https://www.provider.com/somerestaurant",
        "telephone": "+16501235555",
        "streetAddress": "345 Spear St",
        "addressLocality": "San Francisco",
        "addressRegion": "CA",
        "postalCode": "94105",
        "addressCountry": "US",
        "latitude": 37.472842,
        "longitude": -122.217144
      },
      "generation_timestamp": "2022-08-19T17:11:10.850Z"
    },
    {
      "data_record": {
        "@type": "Restaurant",
        "@id": "restaurant123",
        "name": "Some Other Restaurant",
        "url": "https://www.provider.com/someotherrestaurant",
        "telephone": "+16501231235",
        "streetAddress": "385 Spear St",
        "addressLocality": "San Mateo",
        "addressRegion": "CA",
        "postalCode": "94115",
        "addressCountry": "US"
      },
      "generation_timestamp": "2022-08-19T17:11:10.850Z"
    }
  ]
}
    

Base64

المثال نفسه مع حمولة بيانات بترميز Base64

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": "eyJAdHlwZSI6IlJlc3RhdXJhbnQiLCJAaWQiOiJyZXN0YXVyYW50MTIzNDUiLCJuYW1lIjoiU29tZSBSZXN0YXVyYW50IiwidXJsIjoiaHR0cHM6Ly93d3cucHJvdmlkZXIuY29tL3NvbWVyZXN0YXVyYW50IiwidGVsZXBob25lIjoiKzE2NTAxMjM1NTU1Iiwic3RyZWV0QWRkcmVzcyI6IjM0NSBTcGVhciBTdCIsImFkZHJlc3NMb2NhbGl0eSI6IlNhbiBGcmFuY2lzY28iLCJhZGRyZXNzUmVnaW9uIjoiQ0EiLCJwb3N0YWxDb2RlIjoiOTQxMDUiLCJhZGRyZXNzQ291bnRyeSI6IlVTIiwibGF0aXR1ZGUiOjM3LjQ3Mjg0MiwibG9uZ2l0dWRlIjotMTIyLjIxNzE0NH0=",
      "generation_timestamp": "2022-08-19T17:11:10.850Z"
    },
    {
      "data_record": "eyJAdHlwZSI6IlJlc3RhdXJhbnQiLCJAaWQiOiJyZXN0YXVyYW50MTIzIiwibmFtZSI6IlNvbWUgT3RoZXIgUmVzdGF1cmFudCIsInVybCI6Imh0dHBzOi8vd3d3LnByb3ZpZGVyLmNvbS9zb21lcmVzdGF1cmFudCIsInRlbGVwaG9uZSI6IisxNjUwMTIzMTIzNSIsInN0cmVldEFkZHJlc3MiOiIzODUgU3BlYXIgU3QiLCJhZGRyZXNzTG9jYWxpdHkiOiJTYW4gTWF0ZW8iLCJhZGRyZXNzUmVnaW9uIjoiQ0EiLCJwb3N0YWxDb2RlIjoiOTQxMTUiLCJhZGRyZXNzQ291bnRyeSI6IlVTIn0=",
      "generation_timestamp": "2022-08-19T17:11:10.850Z"
    }
  ]
}
    

المثال 3: تعديل سعر صنف في القائمة

لنفترض أنك بحاجة إلى تغيير سعر صنف في قائمة.

فكّر في خلاصة مجمّعة تشبه ما يلي:

{
  "@type": "MenuItemOffer",
  "@id": "menuitemoffer6680262",
  "sku": "offer-cola",
  "menuItemId": "menuitem896532",
  "price": 2,
  "priceCurrency": "USD"
}

بعد ذلك، سيتم عرض المعلومات في الوقت الفعلي من خلال طلب POST على النحو التالي:

JSON

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": {
        "@type": "MenuItemOffer",
        "@id": "menuitemoffer6680262",
        "sku": "offer-cola",
        "menuItemId": "menuitem896532",
        "price": 2,
        "priceCurrency": "USD"
      },
      "generation_timestamp": "2022-08-19T17:20:10Z"
    }
  ]
}
    

Base64

المثال نفسه مع حمولة بيانات بترميز Base64

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": "eyJAdHlwZSI6Ik1lbnVJdGVtT2ZmZXIiLCJAaWQiOiJtZW51aXRlbW9mZmVyNjY4MDI2MiIsInNrdSI6Im9mZmVyLWNvbGEiLCJtZW51SXRlbUlkIjoibWVudWl0ZW04OTY1MzIiLCJwcmljZSI6MiwicHJpY2VDdXJyZW5jeSI6IlVTRCJ9",
      "generation_timestamp": "2022-08-19T17:20:10Z"
    }
  ]
}

    

إضافة الكيانات

لا تستخدِم التعديلات في الوقت الفعلي لإضافة كيانات جديدة لأنّ ذلك قد يؤدي إلى عدم اتّساق البيانات. بدلاً من ذلك، استخدِم الخلاصات المجمّعة. كما هو موضَّح في عملية العرض المجمَّع.

حذف الكيانات

لحذف كيانات من مستودعك، استخدِم الزر DELETE نقطة النهاية وإرسال طلبات HTTP POST. يجب أن يكون كل طلب POST تضمين المَعلمة PARTNER_ID مع حمولة JSON الذي يتضمّن معرّف أي كيان في مستودعك

حذف حمولة الطلب

يتم بناء نص طلب الحذف بشكل مشابه لـ طلب تعديل. وتحتوي أيضًا على قائمة بسجلّات تتضمّن data_record وdelete_time:

  {
    "records": [
      {
        "data_record":"BASE_64_ENCODED_REFERENCE",
        "delete_time": "DELETE_TIMESTAMP"
      }
    ]
  }

في الحمولة أعلاه، استبدِل ما يلي:

  • BASE_64_ENCODED_REFERENCE: سلسلة JSON المرمّزة من Base64 يشير إلى الكيان الذي تتم إزالته. يتكون المرجع فقط من نوع الكيان ومعرِّفه، مثل تمثيل JSON الرجوع إلى MenuSection:

    {"@type":"MenuSection","@id":"853705"}
  • DELETE_TIMESTAMP: احرص على تضمين الطابع الزمني لوقت في نظام الواجهة الخلفية. يتم استخدام هذا الطابع الزمني تحديد ترتيب تطبيق الحذف على المستودع.

ويمكن إدخال ما يصل إلى 1,000 كيان في طلب batchDelete.

أمثلة

المثال 1: إزالة كيانَين MenuItem

لإزالة عنصري قائمة في استدعاء واجهة برمجة تطبيقات واحد، سيكون طلب HTTP POST كما يلي التالي:

JSON

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": {
        "@type": "MenuItem",
        "@id": "item_1234"
      },
      "delete_time": "2022-08-21T15:23:00.000Z"
    },
    {
      "data_record": {
        "@type": "MenuItem",
        "@id": "item_5678"
      },
      "delete_time": "2022-08-21T15:23:00.000Z"
    }
  ]
}
    

Base64

المثال نفسه مع حمولة بيانات بترميز Base64

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": "eyJAdHlwZSI6Ik1lbnVJdGVtIiwiQGlkIjoiaXRlbV8xMjM0In0="
      "delete_time": "2022-08-21T15:23:00.000Z"
    },
    {
      "data_record": "eyJAdHlwZSI6Ik1lbnVJdGVtIiwiQGlkIjoiaXRlbV81Njc4In0="
      "delete_time": "2022-08-21T15:23:00.000Z"
    },
  ]
}
    

المثال 2: حذف كيان Restaurant

فكّر في موقف تريد فيه حذف مطعم في الخلاصة المجمّعة. يجب حذف كيان المطعم فقط. لا تحذف العناصر الفرعية، مثل والخدمات والقوائم، حيث ستتم إزالتها تلقائيًا.

نموذج طلب لحذف كيان مطعم برقم التعريف https://www.provider.com/restaurant/12345:

JSON

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": {
        "@type": "Restaurant",
        "@id": "https://www.provider.com/restaurant/12345"
      },
      "delete_time": "2022-08-19T17:11:10.750Z"
    }
  ]
}
    

Base64

المثال نفسه مع حمولة بيانات بترميز Base64

POST v1alpha/inventory/partners/PARTNER_ID/feeds/owg.v2/record:batchDelete
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [
    {
      "data_record": "ewogICJAdHlwZSI6ICJSZXN0YXVyYW50IiwKICAiQGlkIjogImh0dHBzOi8vd3d3LnByb3ZpZGVyLmNvbS9yZXN0YXVyYW50LzEyMzQ1Igp9"
      "delete_time": "2022-08-19T17:11:10.750Z"
    }
  ]
}
    

التحقق من الصحة رموز الاستجابة من واجهة برمجة التطبيقات

هناك نوعان من عمليات التحقّق التي يتم إجراؤها على طلبات بيانات من واجهة برمجة التطبيقات للتحديث في الوقت الفعلي:

  • مستوى الطلب: تتحقّق عمليات التحقّق هذه من أنّ الحمولة تتبع upert أو delete ويحتوي كل data_record على حقلي @id و@type. تكون عمليات التحقّق هذه متزامنة ويتم عرض النتائج في واجهة برمجة التطبيقات. نص الاستجابة. رمز الاستجابة 200 ونص JSON فارغ {} يعنيان هذين تم اجتياز عمليات التحقق وتم وضع الكيانات الموجودة في هذا الطلب في قائمة الانتظار قيد المعالجة. ويعني رمز الاستجابة المختلف عن 200 أنّ قيمة واحدة أو أكثر من هذه القيم فشل عمليات التحقق ورفض الطلب بأكمله (بما في ذلك جميع الكيانات الموجودة في الحمولة). على سبيل المثال، إذا كانت السمة data_record تنقصها @type، سيتم عرض الاستجابة التالية للخطأ:

    {
      "error": {
        "code": 400,
        "message": "Record:{\"@id\":\"2717/86853/DELIVERY\",\"applicableServiceType\":[\"DELIVERY\",\"TAKEOUT\"],\"menuId\":[{\"@id\":\"2717/DELIVERY\",\"displayOrder\":1},{\"@id\":\"2717/TAKEOUT\",\"displayOrder\":2}],\"name\":\"Salad\",\"offeredById\":[\"2717\"]} has following errors: \nThe entity type could not be extracted from the entity value.\n",
        "status": "INVALID_ARGUMENT",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.DebugInfo",
            "detail": "[ORIGINAL ERROR] generic::invalid_argument: Failed to parse one or more rtu records. Record:{\"@id\":\"2717/86853/DELIVERY\",\"applicableServiceType\":[\"DELIVERY\",\"TAKEOUT\"],\"menuId\":[{\"@id\":\"2717/DELIVERY\",\"displayOrder\":1},{\"@id\":\"2717/TAKEOUT\",\"displayOrder\":2}],\"name\":\"Salad\",\"offeredById\":[\"2717\"]} has following errors: \nThe entity type could not be extracted from the entity value.\n [google.rpc.error_details_ext] { message: \"Record:{\\\"@id\\\":\\\"2717/86853/DELIVERY\\\",\\\"applicableServiceType\\\":[\\\"DELIVERY\\\",\\\"TAKEOUT\\\"],\\\"menuId\\\":[{\\\"@id\\\":\\\"2717/DELIVERY\\\",\\\"displayOrder\\\":1},{\\\"@id\\\":\\\"2717/TAKEOUT\\\",\\\"displayOrder\\\":2}],\\\"name\\\":\\\"Salad\\\",\\\"offeredById\\\":[\\\"2717\\\"]} has following errors: \\nThe entity type could not be extracted from the entity value.\\n\" }"
          }
        ]
      }
    }
    
  • على مستوى الكيان - يتم التحقّق من صحة كل عنصر في الحمولة من خلال المخطط العلائقي. لا يتم الإبلاغ عن المشاكل التي تحدث في هذه المرحلة من التحقق في واجهة برمجة التطبيقات. الاستجابة. ولا يتم الإبلاغ عنها إلا في إعداد تقارير RTU لوحة المعلومات.

حصص واجهة برمجة التطبيقات

تبلغ حصة تحديثات واجهة برمجة التطبيقات في الوقت الفعلي 1,500 طلب كل 60 ثانية أو 25 ثانية الطلبات في الثانية في المتوسط. عند تجاوز إحدى الحصص، تستجيب Google برسالة الخطأ التالية:

{
  "error": {
    "code": 429,
    "message": "Insufficient tokens for quota ...",
    "status": "RESOURCE_EXHAUSTED",
    "details": [...]
  }
}

لمعالجة هذا الأمر، يمكنك إعادة محاولة الاتصال مرة أخرى على فترات زمنية أكبر بشكل كبير إلى أن للنجاح. إذا كنت تستنفد الحصة بانتظام، ننصحك بتضمين المزيد من العناصر. في طلب واجهة برمجة تطبيقات واحد. يمكنك تضمين ما يصل إلى 1,000 عنصر في طلب بيانات واحد من واجهة برمجة التطبيقات.

عيّنات تعليمات برمجية

وفي ما يلي بعض النماذج عن كيفية استخدام واجهة برمجة التطبيقات للتحديث في الوقت الفعلي بعدة طرق اللغات. تستخدم هذه النماذج مكتبات مصادقة Google للمصادقة باستخدام ملف مفتاح حساب الخدمة الذي تم إنشاؤه أثناء إعداد الحساب: للحصول على حلول بديلة، يمكنك الرجوع إلى استخدام OAuth 2.0 لتطبيقات خادم إلى خادم: ننصحك باستخدام المخطط المتاح في قسم إنشاء مكتبات العملاء لإنشاء رمز مصدر للمستودع وأنواع عناصر التعديل في الوقت الفعلي.

تعديل الكيانات

Node.js

يستخدم هذا الرمز مكتبة المصادقة من Google لنظام Node.js.

/* Sample code for Real-time update batchPush implementation.
 *
 * Required libraries:
 * - google-auth-library
 */

const {JWT} = require('google-auth-library');

// ACTION REQUIRED: Change this to the path of the service account client secret
// file downloaded from the Google Cloud Console.
const serviceAccountJson = require('./service-account.json');

// ACTION REQUIRED: Change this to your Partner ID received from Google.
// The Partner ID is available on the Partner Portal.
const PARTNER_ID = 1234;

const HOST = {
  prod: 'https://mapsbooking.googleapis.com',
  sandbox: 'https://partnerdev-mapsbooking.googleapis.com'
};

// ACTION REQUIRED: Change to 'prod' for production
const ENV = 'sandbox';

// Feed name for Order with Google including the version.
const FEED_NAME = 'owg.v2';

// Endpoint url
const url = `${HOST[ENV]}/v1alpha/inventory/partners/${PARTNER_ID}/feeds/${
    FEED_NAME}/record:batchPush`;

/**
 * Send a Real-time update request to update/insert entities
 */
async function batchUpsert(entities) {
  /**
   * Sign JWT token using private key from service account secret file
   * provided. The client can be created without providing a service account
   * secret file by implementing Application Default Credentials.
   * https://github.com/googleapis/google-auth-library-nodejs
   */
  const client = new JWT({
    email: serviceAccountJson.client_email,
    key: serviceAccountJson.private_key,
    scopes: ['https://www.googleapis.com/auth/mapsbooking'],
  });
  const request = {records: toPushRecords(entities)};
  const body = JSON.stringify(request);
  try {
    const response = await client.request({
      method: 'POST',
      url,
      data: body,
      headers: {'Content-Type': 'application/json'}
    });
    console.log('request body:', body);
    console.log('response status:', response.status);
    console.log(
        'response data:', response.data);  // successful response returns '{}'
  } catch (error) {
    console.log('error:', error);
  }
}

/**
 * Maps array of entities to records for batch push requests
 */
const toPushRecords = (entities) => {
  return entities.map((entity) => {
    // Using dateModified to set generation_timestamp. Defaulting to the
    // current timestamp for records that do not have dateModified.
    const generation_timestamp =
        entity.dateModified ? entity.dateModified : new Date().toISOString();
    return {data_record: btoa(JSON.stringify(entity)), generation_timestamp};
  });
};

// Call batchUpsert with example entities. dateModified is optional and is
// used to hold the actual timestamp when the entity was updated/created.
batchUpsert([
  {
    '@type': 'MenuItemOffer',
    '@id': '6680261',
    'menuItemId': '18931508',
    'price': 15.5,
    'priceCurrency': 'USD',
    'applicableServiceType': ['DELIVERY', 'TAKEOUT'],
    'inventoryLevel': 0,
    'dateModified': '2022-06-19T15:43:50.970Z'
  },
  {
    '@type': 'MenuItemOffer',
    '@id': '6680262',
    'menuItemId': '18931509',
    'price': 25.5,
    'priceCurrency': 'USD',
    'applicableServiceType': ['DELIVERY', 'TAKEOUT'],
    'inventoryLevel': 0,
    'dateModified': '2022-06-19T15:43:50.970Z'
  }
]);

Python

يستخدم هذا الرمز مكتبة المصادقة من Google للغة Python.

"""Sample code for the Real-time update batchPush implementation."""

# Required libraries:
# - google-auth

import base64
import datetime
import json
from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import service_account

# ACTION REQUIRED: Change this to the Partner ID received from Google.
# Partner ID is available on the Partner Portal.
# https://partnerdash.google.com/apps/reservewithgoogle
_PARTNER_ID = '1234'

# ACTION REQUIRED: Change this to the path of the service account client secret
# file downloaded from the Google Cloud Console.
_SERVICE_ACCOUNT_KEY_JSON_FILE = 'service-account-creds.json'

_HOST_MAP = {
    'sandbox': 'https://partnerdev-mapsbooking.googleapis.com',
    'prod': 'https://mapsbooking.googleapis.com'
}

# ACTION REQUIRED: Change to 'prod' for production
_ENV = 'sandbox'

# Feed name for Order with Google including the version.
_FEED_NAME = 'owg.v2'

_ENDPOINT = '{}/v1alpha/inventory/partners/{}/feeds/{}/record:batchPush'.format(
    _HOST_MAP[_ENV], _PARTNER_ID, _FEED_NAME)


def batch_upsert(entities):
  """Makes a batchPush request using the Real-time updates REST service.

  Args:
      entities: The list of entity objects to update or add.
  """

  # Creates credentials by providing a json file. Credentials can also be
  # provided by implementing Application Default Credentials.
  # https://googleapis.dev/python/google-auth/latest/user-guide.html
  credentials = service_account.Credentials.from_service_account_file(
      _SERVICE_ACCOUNT_KEY_JSON_FILE,
      scopes=['https://www.googleapis.com/auth/mapsbooking'])
  authorized_session = AuthorizedSession(credentials)

  # JSON request object
  batch_request = {'records': [create_push_record(x) for x in entities]}
  response = authorized_session.post(_ENDPOINT, json=batch_request)
  print('request body:', json.dumps(batch_request))
  print('response status:', response.status_code)
  print('response data:', response.text)  # successful response returns '{}'


def create_push_record(entity):
  """Creates a record from an entity for batchPush requests.

  Args:
      entity: The entity object to create the record from.

  Returns:
      The constructed record for the batchPush request payload.
  """
  data_bytes = json.dumps(entity).encode('utf-8')
  base64_bytes = base64.b64encode(data_bytes)
  # Using dateModified to set generation_timestamp. Defaulting to the
  # current timestamp for records that do not have dateModified.
  generation_timestamp = entity.dateModified if 'dateModified' in entity else datetime.datetime.now(
  ).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
  return {
      'generation_timestamp': generation_timestamp,
      'data_record': base64_bytes.decode('utf-8')
  }


# Call batch_upsert with example entities. dateModified is optional and is
# used to hold the actual timestamp when the entity was updated/created.
batch_upsert([{
    '@type': 'MenuItemOffer',
    '@id': '6680261',
    'menuItemId': '18931508',
    'price': 15.5,
    'priceCurrency': 'USD',
    'applicableServiceType': ['DELIVERY', 'TAKEOUT'],
    'inventoryLevel': 0,
    'dateModified': '2022-06-19T15:43:50.970Z'
}, {
    '@type': 'MenuItemOffer',
    '@id': '6680262',
    'menuItemId': '18931509',
    'price': 25.5,
    'priceCurrency': 'USD',
    'applicableServiceType': ['DELIVERY', 'TAKEOUT'],
    'inventoryLevel': 0,
    'dateModified': '2022-06-19T15:43:50.970Z'
}])

Java

يستخدم هذا الرمز مكتبة مصادقة Google للغة Java.

تم إنشاء نماذج رمز مصدر العميل في الحزمتَين rtusamples.inventory وrtusamples.realtime باتّباع الخطوات الواردة في إنشاء مكتبات العملاء.

/*
 * Required Libraries:
 * - JDK >= 11
 * - google-auth-library-oauth2-http
 */
package rtusamples;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.charset.Charset;
import java.time.Clock;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import rtusamples.inventory.MenuItemOffer;
import rtusamples.inventory.MenuItemOfferType;
import rtusamples.inventory.ServiceTypeElement;
import rtusamples.realtime.BatchPushGenericRecordRequest;
import rtusamples.realtime.GenericRecord;

/** Sample code for Real-time update batchPush implementation. */
public final class BasicPush {
  // ACTION REQUIRED: Change this to your Partner ID received from Google. The Partner ID is
  // available on the Partner Portal.
  private static final long PARTNER_ID = 12345678;

  // ACTION REQUIRED: Change this to the path of the service account client secret file downloaded
  // from the Google Cloud Console.
  private static final String JSON_KEY_FULL_PATH =
      "<path to your JSON credentials>/credentials.json";

  // ACTION REQUIRED: Change this to the endpoint that is needed.
  private static final String ENDPOINT =
      //    "https://partnerdev-mapsbooking.googleapis.com"; // for sandbox
      "https://mapsbooking.googleapis.com"; // for prod

  // Feed name for Order with Google including the version.
  private static final String FEED_NAME = "owg.v2";

  private static final ObjectMapper objectMapper = new ObjectMapper();

  private static final DateTimeFormatter TIMESTAMP_FORMATTER =
      DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'");

  private static final Charset UTF_8 = Charset.forName("UTF-8");

  public static void main(String[] args) throws Exception {

    /**
     * Create credentials from service account secret file. Alternatively, the credentials can be
     * created by implementing Application Default Credentials.
     * https://github.com/googleapis/google-auth-library-java
     */
    // GoogleCredentials sourceCredentials =
    //     GoogleCredentials.getApplicationDefault()
    //         .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking"));

    // ImpersonatedCredentials credentials =
    //     ImpersonatedCredentials.create(
    //         sourceCredentials,
    //         "fo-test@projectname.iam.gserviceaccount.com",
    //         null,
    //         Arrays.asList("https://www.googleapis.com/auth/mapsbooking"),
    //         300);

    GoogleCredentials credentials =
        GoogleCredentials.fromStream(new FileInputStream(JSON_KEY_FULL_PATH))
            .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking"));

    // Create example MenuItemOffer entities, dateModified is optional and is used to hold
    // the actual timestamp when the entity was updated/created.
    MenuItemOffer menuItemOfferPizza = new MenuItemOffer();
    menuItemOfferPizza.setID("6680261");
    menuItemOfferPizza.setType(MenuItemOfferType.MENU_ITEM_OFFER);
    menuItemOfferPizza.setMenuItemID("18931508");
    menuItemOfferPizza.setPrice(15.5);
    menuItemOfferPizza.setPriceCurrency("USD");
    menuItemOfferPizza.setApplicableServiceType(
        new ServiceTypeElement[] {ServiceTypeElement.TAKEOUT, ServiceTypeElement.DELIVERY});
    menuItemOfferPizza.setInventoryLevel(0.0);
    menuItemOfferPizza.setDateModified("2022-10-07T13:00:00.000Z");

    MenuItemOffer menuItemOfferSalad = new MenuItemOffer();
    menuItemOfferSalad.setID("6680262");
    menuItemOfferSalad.setType(MenuItemOfferType.MENU_ITEM_OFFER);
    menuItemOfferSalad.setMenuItemID("18931509");
    menuItemOfferSalad.setPrice(25.5);
    menuItemOfferSalad.setPriceCurrency("USD");
    menuItemOfferSalad.setApplicableServiceType(
        new ServiceTypeElement[] {ServiceTypeElement.TAKEOUT, ServiceTypeElement.DELIVERY});
    menuItemOfferSalad.setInventoryLevel(0.0);
    menuItemOfferSalad.setDateModified("2022-10-07T13:00:00.000Z");

    // Example array of MenuItemOffer entities to update.
    List<MenuItemOffer> menuItemOffers = Arrays.asList(menuItemOfferPizza, menuItemOfferSalad);

    // Create list of GenericRecord from menuItemOffers.
    List<GenericRecord> menuItemOfferGenericRecords =
        menuItemOffers.stream()
            .map(
                (menuItemOffer) ->
                    toBatchPushRecord(menuItemOffer, menuItemOffer.getDateModified()))
            .collect(Collectors.toList());

    // List of records to be updated/created.
    List<GenericRecord> recordsToBeUpdated = new ArrayList<>();

    // Add list of menuItemOffer generic records.
    recordsToBeUpdated.addAll(menuItemOfferGenericRecords);

    // Request object that contains all records.
    BatchPushGenericRecordRequest batchPushRequest = new BatchPushGenericRecordRequest();
    batchPushRequest.setRecords(recordsToBeUpdated.toArray(new GenericRecord[0]));

    // Execute batchPush request.
    BasicPush basicPush = new BasicPush();
    basicPush.batchPush(batchPushRequest, credentials);
  }

  public void batchPush(
      BatchPushGenericRecordRequest batchPushRequest, GoogleCredentials credentials)
      throws IOException {

    credentials.refreshIfExpired();
    AccessToken token = credentials.getAccessToken();

    String requestBody = objectMapper.writeValueAsString(batchPushRequest);
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request =
        HttpRequest.newBuilder()
            .uri(
                URI.create(
                    String.format(
                        "%s/v1alpha/inventory/partners/%s/feeds/%s/record:batchPush",
                        ENDPOINT, PARTNER_ID, FEED_NAME)))
            .header("Content-Type", "application/json")
            .header("Authorization", String.format("Bearer %s", token.getTokenValue()))
            .POST(BodyPublishers.ofString(requestBody))
            .build();

    HttpResponse<String> response = null;
    try {
      response = client.send(request, BodyHandlers.ofString());
      System.out.println("Request body:" + requestBody);
      System.out.println("Response status:" + response.statusCode());
      System.out.println("Response body:" + response.body());
    } catch (IOException | InterruptedException e) {
      e.printStackTrace();
    }
  }

  public static <T> GenericRecord toBatchPushRecord(T entity, String dateModified) {
    GenericRecord genericRecord = new GenericRecord();
    try {
      String json = objectMapper.writeValueAsString(entity);
      genericRecord.setDataRecord(Base64.getEncoder().encodeToString(json.getBytes(UTF_8)));
      // Using dateModified to set generation_timestamp. Defaulting to the
      // current timestamp for records that do not have dateModified.
      String generationTimestamp =
          Optional.ofNullable(dateModified)
              .orElse(OffsetDateTime.now(Clock.systemUTC()).format(TIMESTAMP_FORMATTER));
      genericRecord.setGenerationTimestamp(generationTimestamp);
    } catch (JsonProcessingException e) {
      System.out.println(e.getMessage());
    }
    return genericRecord;
  }
}

إزالة الكيانات

Node.js

يستخدم هذا الرمز مكتبة المصادقة من Google لنظام Node.js.

/* Sample code for Real-time update batchDelete implementation.
 *
 * Required libraries:
 * - google-auth-library
 */

const {JWT} = require('google-auth-library');

// ACTION REQUIRED: Change this to the path of the service account client secret
// file downloaded from the Google Cloud Console.
const serviceAccountJson = require('./service-account.json');

// ACTION REQUIRED: Change this to your Partner ID received from Google.
// The Partner ID is available on the Partner Portal.
const PARTNER_ID = 1234;

const HOST = {
  prod: 'https://mapsbooking.googleapis.com',
  sandbox: 'https://partnerdev-mapsbooking.googleapis.com'
};

// ACTION REQUIRED: Change to 'prod' for production
const ENV = 'sandbox';

// Feed name for Order with Google including the version.
const FEED_NAME = 'owg.v2';

// Endpoint url
const url = `${HOST[ENV]}/v1alpha/inventory/partners/${PARTNER_ID}/feeds/${
    FEED_NAME}/record:batchDelete`;


/**
 * Send a Real-time update request to delete entities
 */
async function batchDelete(entities) {
  try {
    /**
     * Sign JWT token using private key from service account secret file
     * provided. The client can be created without providing a service account
     * secret file by implementing Application Default Credentials.
     * https://github.com/googleapis/google-auth-library-nodejs
     */
    const client = new JWT({
      email: serviceAccountJson.client_email,
      key: serviceAccountJson.private_key,
      scopes: ['https://www.googleapis.com/auth/mapsbooking'],
    });
    const request = {
      records: toDeleteRecords(entities)
    };
    const body = JSON.stringify(request);
    try {
      const response = await client.request({
        method: 'POST',
        url,
        data: body,
        headers: {'Content-Type': 'application/json'}
      });
      console.log('request body:', body);
      console.log('response status:', response.status);
      console.log('response data:', response.data);  // successful response returns '{}'
    } catch (error) {
      console.log('error:', error);
    }
  }

  /**
   * Maps array of entities to records for batch delete requests
   */
  const toDeleteRecords = (entities) => {
    return entities.map((entity) => {
      // Using dateModified to set delete_time. Defaulting to the current
      // timestamp for records that do not have dateModified.
      const delete_time =
          entity.dateModified ? entity.dateModified : new Date().toISOString();
      return {data_record: btoa(JSON.stringify(entity)), delete_time};
    });
  };

  // Call batchDelete with example entities. dateModified is optional and is
  // used to hold the actual timestamp when the entity was deleted.
  batchDelete([
    {
      '@type': 'Menu',
      '@id': '853706',
      'dateModified': '2022-06-19T15:43:50.970Z'
    },
    {
      '@type': 'Menu',
      '@id': '853705',
      'dateModified': '2022-06-19T15:13:00.280Z'
    }
  ]);

Python

يستخدم هذا الرمز مكتبة المصادقة من Google للغة Python.

"""Sample code for the Real-time update batchDelete implementation."""

# Required libraries:
# - google-auth

import base64
import datetime
import json
from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import service_account

# ACTION REQUIRED: Change this to the Partner ID received from Google.
# Partner ID is available on the Partner Portal.
# https://partnerdash.google.com/apps/reservewithgoogle
_PARTNER_ID = '1234'

# ACTION REQUIRED: Change this to the path of the service account client secret
# file downloaded from the Google Cloud Console.
_SERVICE_ACCOUNT_KEY_JSON_FILE = 'service-account-creds.json'

_HOST_MAP = {
    'sandbox': 'https://partnerdev-mapsbooking.googleapis.com',
    'prod': 'https://mapsbooking.googleapis.com'
}

# ACTION REQUIRED: Change to 'prod' for production
_ENV = 'sandbox'

# Feed name for Order with Google including the version.
_FEED_NAME = 'owg.v2'

_ENDPOINT = '{}/v1alpha/inventory/partners/{}/feeds/{}/record:batchDelete'.format(
    _HOST_MAP[_ENV], _PARTNER_ID, _FEED_NAME)


def batch_delete(entities):
  """Makes a batch delete request using the Real-time updates REST service.

  Args:
      entities: The list of entity objects to delete.
  """

  # Creates credentials by providing a json file. Credentials can also be
  # provided by implementing Application Default Credentials.
  # https://googleapis.dev/python/google-auth/latest/user-guide.html
  credentials = service_account.Credentials.from_service_account_file(
      _SERVICE_ACCOUNT_KEY_JSON_FILE,
      scopes=['https://www.googleapis.com/auth/mapsbooking'])
  authorized_session = AuthorizedSession(credentials)

  # JSON request object
  batch_request = {'records': [create_delete_record(x) for x in entities]}
  response = authorized_session.post(_ENDPOINT, json=batch_request)
  print('request body:', json.dumps(batch_request))
  print('response status:', response.status_code)
  print('response data:', response.text)  # successful response returns '{}'


def create_delete_record(entity):
  """Creates a record from an entity for batchDelete requests.

  Args:
    entity: The entity object to create the record from.

  Returns:
    The constructed record for the batchDelete request payload.
  """
  data_bytes = json.dumps(entity).encode('utf-8')
  base64_bytes = base64.b64encode(data_bytes)
  # Using dateModified to set delete_time. Defaulting to the current
  # timestamp for records that do not have dateModified.
  delete_time = entity.dateModified if 'dateModified' in entity else datetime.datetime.now(
  ).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
  return {
      'delete_time': delete_time,
      'data_record': base64_bytes.decode('utf-8')
  }


# Call batch_delete with example entities. dateModified is optional and is
# used to hold the actual timestamp when the entity was deleted.
batch_delete([{
    '@type': 'Menu',
    '@id': '853706',
    'dateModified': '2022-06-19T13:10:00.000Z'
}, {
    '@type': 'Menu',
    '@id': '853705',
    'dateModified': '2022-06-19T13:30:10.000Z'
}])

Java

يستخدم هذا الرمز مكتبة مصادقة Google للغة Java.

تم إنشاء نماذج رمز مصدر العميل في الحزمتَين rtusamples.inventory وrtusamples.realtime باتّباع الخطوات الواردة في إنشاء مكتبات العملاء.

/*
 * Required Libraries:
 * - JDK >= 11
 * - google-auth-library-oauth2-http
 */
package rtusamples;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.charset.Charset;
import java.time.Clock;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import rtusamples.inventory.Menu;
import rtusamples.inventory.MenuType;
import rtusamples.realtime.BatchDeleteGenericRecordsRequest;
import rtusamples.realtime.GenericDeleteRecord;

/** Sample code for the Real-time update batchDelete implementation. */
public final class BasicDelete {
  // ACTION REQUIRED: Change this to your Partner ID received from Google. The Partner ID is
  // available on the Partner Portal.
  private static final long PARTNER_ID = 123456789;

  // ACTION REQUIRED: Change this to the path of the service account client secret file downloaded
  // from the Google Cloud Console.
  private static final String JSON_KEY_FULL_PATH =
      "<path to your JSON credentials>/credentials.json";

  // ACTION REQUIRED: Change this to the endpoint that is needed.
  private static final String ENDPOINT =
      "https://partnerdev-mapsbooking.googleapis.com"; // for sandbox
  // "https://mapsbooking.googleapis.com" // for prod

  // Feed name for Order with Google including the version.
  private static final String FEED_NAME = "owg.v2";

  private static final ObjectMapper objectMapper = new ObjectMapper();

  private static final DateTimeFormatter TIMESTAMP_FORMATTER =
      DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'");

  private static final Charset UTF_8 = Charset.forName("UTF-8");

  public static void main(String[] args) throws Exception {

    /**
     * Create credentials from service account secret file. Alternatively, the credentials can be
     * created by implementing Application Default Credentials.
     * https://github.com/googleapis/google-auth-library-java
     */
    // GoogleCredentials sourceCredentials =
    //     GoogleCredentials.getApplicationDefault()
    //         .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking"));

    // ImpersonatedCredentials credentials =
    //     ImpersonatedCredentials.create(
    //         sourceCredentials,
    //         "fo-test@projectname.iam.gserviceaccount.com",
    //         null,
    //         Arrays.asList("https://www.googleapis.com/auth/mapsbooking"),
    //         300);

    GoogleCredentials credentials =
        GoogleCredentials.fromStream(new FileInputStream(JSON_KEY_FULL_PATH))
            .createScoped(Arrays.asList("https://www.googleapis.com/auth/mapsbooking"));

    // Create example Menu entities, dateModified is optional and is used to hold
    // the actual timestamp when the entity was deleted.
    Menu menuLunch = new Menu();
    menuLunch.setID("853705");
    menuLunch.setType(MenuType.MENU);
    menuLunch.setDateModified("2022-09-19T13:10:00.000Z");

    Menu menuDinner = new Menu();
    menuDinner.setID("853706");
    menuDinner.setType(MenuType.MENU);
    menuDinner.setDateModified("2022-09-19T13:13:10.000Z");

    // Example array of Menu entities to update.
    List<Menu> menus = Arrays.asList(menuLunch, menuDinner);

    // Create list of GenericDeleteRecord from menus.
    List<GenericDeleteRecord> menuGenericDeleteRecords =
        menus.stream()
            .map((menu) -> toBatchDeleteRecord(menu, menu.getDateModified()))
            .collect(Collectors.toList());

    // List of records to be deleted.
    List<GenericDeleteRecord> recordsToBeDeleted = new ArrayList<>();

    // Add list of menu generic records.
    recordsToBeDeleted.addAll(menuGenericDeleteRecords);

    // Request object that contains all records.
    BatchDeleteGenericRecordsRequest batchDeleteRequest = new BatchDeleteGenericRecordsRequest();
    batchDeleteRequest.setRecords(recordsToBeDeleted.toArray(new GenericDeleteRecord[0]));

    // Execute batchDelete request.
    BasicDelete basicDelete = new BasicDelete();
    basicDelete.batchDelete(batchDeleteRequest, credentials);
  }

  public void batchDelete(
      BatchDeleteGenericRecordsRequest batchDeleteRequest, GoogleCredentials credentials)
      throws IOException {

    credentials.refreshIfExpired();
    AccessToken token = credentials.getAccessToken();

    String requestBody = objectMapper.writeValueAsString(batchDeleteRequest);
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request =
        HttpRequest.newBuilder()
            .uri(
                URI.create(
                    String.format(
                        "%s/v1alpha/inventory/partners/%s/feeds/%s/record:batchDelete",
                        ENDPOINT, PARTNER_ID, FEED_NAME)))
            .header("Content-Type", "application/json")
            .header("Authorization", String.format("Bearer %s", token.getTokenValue()))
            .POST(BodyPublishers.ofString(requestBody))
            .build();

    HttpResponse<String> response = null;
    try {
      response = client.send(request, BodyHandlers.ofString());
      System.out.println("Request body:" + requestBody);
      System.out.println("Response status:" + response.statusCode());
      System.out.println("Response body:" + response.body());
    } catch (IOException | InterruptedException e) {
      e.printStackTrace();
    }
  }

  public static <T> GenericDeleteRecord toBatchDeleteRecord(T entity, String dateModified) {
    GenericDeleteRecord genericRecord = new GenericDeleteRecord();
    try {
      String json = objectMapper.writeValueAsString(entity);
      genericRecord.setDataRecord(Base64.getEncoder().encodeToString(json.getBytes(UTF_8)));
      // Using dateModified to set delete_time. Defaulting to the current
      // timestamp for records that do not have dateModified.
      String deleteTime =
          Optional.ofNullable(dateModified)
              .orElse(OffsetDateTime.now(Clock.systemUTC()).format(TIMESTAMP_FORMATTER));
      genericRecord.setDeleteTime(deleteTime);
    } catch (JsonProcessingException e) {
      System.out.println(e.getMessage());
    }
    return genericRecord;
  }
}

حالات الاستخدام

وفي ما يلي أمثلة على التحديثات التي يتم إجراؤها في الوقت الفعلي وتحديثات الخلاصات المجمّعة والمحتوى على مستوى عالٍ في طلب البيانات من واجهة برمجة التطبيقات:

السيناريو العنصر المطلوب تعديله الوصف والتأثيرات
إيقاف خدمة Service

تحتاج إلى إيقاف خدمة لسبب غير متوقع.

إشعارات في الوقت الفعلي: عدِّل كيان Service في من خلال ضبط خاصية isDisabled على true، مع الحفاظ على الخصائص الأخرى نفسها.

الخلاصات الكاملة: احرص على تعديل العنصر من الخلاصات الكاملة. أن يتم ضبط isDisabled على true قبل عملية الجلب التالية من Google، وإلا ستتم إعادة تفعيل الكيان.

سلعة معيّنة غير متوفّرة MenuItemOffer إشعارات في الوقت الفعلي: أرسِل MenuItemOffer غلافًا. كيان مع ضبط inventoryLevel على 0 MenuItem وجميع البيانات الأخرى بدون تغيير.
تغيير سعر الصنف في القائمة MenuItemOffer إشعارات في الوقت الفعلي: أرسِل MenuItemOffer غلافًا. كيان price تم ضبط السعر المعدَّل له MenuItem وجميع البيانات الأخرى بدون تغيير.

إضافة كيان جديد ذي مستوى أعلى

ينطبق فقط على الكيان من الأنواع Menu، Restaurant وService

Menu وRestaurant وService

على سبيل المثال، تحتاج إلى إضافة قائمة طعام جديدة إلى مطعم.

الخلاصات الكاملة: أضِف الكيان في خلاصات البيانات وانتظِر حتى يتم العرض بشكل مجمّع.

حذف الكيان ذي المستوى الأعلى نهائيًا

ينطبق فقط على الكيان من الأنواع Menu، Restaurant وService

Menu وRestaurant وService

إشعارات في الوقت الفعلي: أرسِل الحذف الفاضح

الخلاصات الكاملة: احرص على إزالة الكيان من الخلاصات الكاملة قبل عملية الجلب التالية من Google، وإلا ستتم إعادة إضافة الكيان.

إضافة منطقة توصيل جديدة في Service محدّد ServiceArea الخلاصات المجمّعة: أرسِل الكيان ServiceArea المعني مع كل الحقول سليمة، كما هو الحال عادةً ضمن الخلاصات الكاملة، مع تضمين منطقة تسليم جديدة المحدد في polygon أو geoRadius أو postalCode.
تعديل الوقت المقدّر للوصول في Service ServiceHours الخلاصات المجمّعة: أرسِل ServiceHours كما هي الحال في الخلاصات، إلا أنّه تم تعديل leadTimeMin فيها وفقًا لذلك.
تعديل أسعار التوصيل في Service Fee الخلاصات المجمّعة: إرسال قيمة التسليم الكامل Fee باستخدام تم تعديل price.
تعديل ساعات عمل خدمة التوصيل أو طلب الوجبات الجاهزة لتناولها خارج المطعم في Service ServiceHours الخلاصات المجمّعة: أرسِل ServiceHours كما هي الحال في الخلاصات، باستثناء أنه تم تعديل السمتين opens وcloses وفقًا لذلك.
Service (تغيير الحد الأدنى لمبلغ الطلب) Fee الخلاصات المجمّعة: إرسال Fee كاملة باستخدام minPrice تم التحديث
حذف MenuItem نهائيًا Menu الخلاصات المجمّعة: أرسِل MenuItem القيمة نفسها كما في السمة الخلاصات، ولكن السمة parentMenuSectionId فارغة.

أوقات معالجة المهام المجمّعة والتعديلات في الوقت الفعلي

إنّ كيان تم تعديله أو حذفه من خلال خلاصة مجمّعة ستتم معالجته في غضون ساعة بينما تتم معالجة كيان تم تحديثه من خلال تعديل في الوقت الفعلي في 5 دقائق. حاسمة كيان قديم يتم حذفه خلال 14 يومًا.

يمكنك إرسال ما يلي إلى Google:

  • مهام متعددة دُفعة واحدة في اليوم لإبقاء مستودعك محدّثًا
  • مهمة واحدة مجمّعة في اليوم مع تعديلات في الوقت الفعلي للحفاظ على مستودعك باستمرار