การอัปเดตแบบเรียลไทม์

ส่วนนี้อธิบายวิธีส่งการอัปเดตสินค้าคงคลังที่ต้องคำนึงถึงเวลาเป็นสำคัญ ให้กับ Google API การอัปเดตแบบเรียลไทม์ช่วยให้คุณพุชการอัปเดตและลบได้ ในพื้นที่โฆษณาแซนด์บ็อกซ์หรือเวอร์ชันที่ใช้งานจริงของคุณได้เกือบเรียลไทม์

ฟังก์ชันการทำงานนี้มีจุดประสงค์หลักสำหรับการอัปเดตที่คุณคาดไม่ถึง เช่น การปิดฉุกเฉิน การนำรายการออกจากเมนูหรืออัปเดตราคา ของรายการเมนู ซึ่งต้องแสดงให้เห็นใน UI ของ Google อย่างรวดเร็ว หากการเปลี่ยนแปลงของคุณ ไม่จำเป็นต้องแสดงทันที คุณสามารถใช้ การส่งผ่านข้อมูลแบบกลุ่มแทน ระบบจะประมวลผลการอัปเดตแบบเรียลไทม์ใน ไม่เกิน 5 นาที

ข้อกำหนดเบื้องต้น

คุณจำเป็นต้องมีรายการต่อไปนี้ก่อนใช้การอัปเดตแบบเรียลไทม์

  1. เปิดใช้ Maps Booking API แล้ว
    • ใน GCP ให้ไปที่ API และ บริการ > คลัง
    • ค้นหา "Google Maps Booking API"
      วันที่ ค้นหา Google Maps Booking API
    • ค้นหาอินสแตนซ์แซนด์บ็อกซ์ ("Google Maps Booking API (Dev)") แล้วคลิก เปิดใช้
    • ค้นหาอินสแตนซ์เวอร์ชันที่ใช้งานจริง ("การจอง API ของ Google Maps") แล้วคลิก เปิดใช้งาน
      เปิดใช้ Google Maps Booking API
  2. บัญชีบริการสร้างขึ้นโดยมีบทบาทผู้แก้ไขสำหรับโปรเจ็กต์ GCP ของคุณ สำหรับ รายละเอียดเพิ่มเติม โปรดดู การสร้างบัญชี
  3. ฟีดข้อมูลเวอร์ชันที่ใช้งานจริงหรือแซนด์บ็อกซ์จะโฮสต์และนำเข้า สำหรับรายละเอียดเพิ่มเติม ดูการส่งผ่านข้อมูลแบบกลุ่ม
  4. สำหรับการตรวจสอบสิทธิ์ API ขอแนะนำให้ติดตั้ง ไลบรารีไคลเอ็นต์ของ Google ในภาษา ใช้ “https://www.googleapis.com/auth/mapsbooking” เป็น OAuth ตัวอย่างโค้ดที่รวมอยู่ด้านล่างใช้ไลบรารีเหล่านี้ หรือไม่เช่นนั้น คุณจะต้องจัดการการแลกเปลี่ยนโทเค็นด้วยตนเองตามที่อธิบายไว้ใน การใช้ OAuth 2.0 เพื่อเข้าถึง Google API

ภาพรวม

API การอัปเดตแบบเรียลไทม์รองรับการดำเนินการ 2 ประเภท การดำเนินการแรกคือ Upsert สำหรับการอัปเดตเอนทิตีที่มีอยู่ การดำเนินการที่ 2 คือการลบเพื่อนำเอนทิตีออกจากพื้นที่โฆษณา ทั้ง 2 อย่าง ดำเนินการต่างๆ ในหลายเอนทิตีที่ระบุไว้ในส่วนเนื้อหาของคำขอ คุณ อัปเดตเอนทิตีได้สูงสุด 1,000 รายการในการเรียก API ครั้งเดียว API ยอมรับ คำขอที่เข้ามาทั้งหมด และวางไว้ในคิวสำหรับการประมวลผลเพิ่มเติม ดังนั้นคำขอ RTU จะได้รับการประมวลผลแบบไม่พร้อมกัน

API การอัปเดตแบบเรียลไทม์ทำงานในสภาพแวดล้อม 2 แบบ ได้แก่ แซนด์บ็อกซ์และเวอร์ชันที่ใช้งานจริง สภาพแวดล้อมแซนด์บ็อกซ์ใช้สำหรับการทดสอบคำขอ API และเวอร์ชันที่ใช้งานจริง เพื่ออัปเดตเนื้อหาที่ปรากฏแก่ผู้ใช้ต้นทางถึงปลายทางที่ปรากฏ ชื่อโฮสต์ ของทั้ง 2 สภาพแวดล้อม

  • แซนด์บ็อกซ์ - partnerdev-mapsbooking.googleapis.com
  • การผลิต - mapsbooking.googleapis.com

ปลายทาง

API การอัปเดตแบบเรียลไทม์แสดงปลายทาง 2 จุดเพื่อจัดการคำขอที่เข้ามา สำหรับการอัปเดตสินค้าคงคลัง

  • 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 ที่สมบูรณ์สำหรับการส่งคำขอ API ในแซนด์บ็อกซ์ และ ของเวอร์ชันที่ใช้งานจริงจะมีลักษณะเหมือนในตัวอย่างด้านล่าง

# 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 และส่งคำขอ HTTP POST คำขอ POST แต่ละรายการต้องมีฟิลด์ พารามิเตอร์ PARTNER_ID พร้อมกับเพย์โหลด JSON ที่มี Structured Data ของเอนทิตีประเภท ที่แสดงในสคีมาพื้นที่โฆษณา

เพย์โหลดคำขออัปเดต

เนื้อหาของคำขอเป็นออบเจ็กต์ 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 คือ ใช้สำหรับการกำหนดเวอร์ชันเอนทิตี ดู รูปแบบของค่าเวลาในพื้นที่โฆษณาเชิงสัมพันธ์ สคีมา

คำขออัปเดตแบบเรียลไทม์ทุกครั้งจะต้องเป็นไปตามเงื่อนไขต่อไปนี้

  • เนื้อหาเพย์โหลดควรมีขนาดไม่เกิน 5 MB คล้ายกับกลุ่ม เราขอแนะนำให้คุณตัดช่องว่างออกเพื่อใส่ข้อมูลเพิ่มเติม
  • โดยคำขอ batchPush จะมีเอนทิตีได้สูงสุด 1,000 รายการ

ตัวอย่าง

ตัวอย่างที่ 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: การอัปเดตร้านอาหารหลายแห่ง

หากต้องการอัปเดตเอนทิตีร้านอาหาร 2 รายการในการเรียก API เดียว ให้ใช้คำขอ 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"
    }
  ]
}

    

การเพิ่มเอนทิตี

อย่าใช้การอัปเดตแบบเรียลไทม์เพื่อเพิ่มเอนทิตีใหม่ เนื่องจากอาจส่งผลให้ข้อมูลไม่สอดคล้องกัน ให้ใช้ฟีดแบบกลุ่มแทน ตามที่อธิบายไว้สำหรับการส่งผ่านข้อมูลแบบกลุ่ม

การลบเอนทิตี

หากต้องการลบเอนทิตีออกจากพื้นที่โฆษณา ให้ใช้ปุ่มลบ ปลายทาง และส่งคำขอ 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: อย่าลืมระบุการประทับเวลาเมื่อ ลบเอนทิตีในระบบแบ็กเอนด์ของคุณแล้ว การประทับเวลานี้ใช้เพื่อ กำหนดลำดับการลบที่จะนำไปใช้กับพื้นที่โฆษณา

โดยคำขอ batchDelete จะมีเอนทิตีได้สูงสุด 1,000 รายการ

ตัวอย่าง

ตัวอย่างที่ 1: การนำเอนทิตี MenuItem 2 รายการออก

หากต้องการนำรายการในเมนู 2 รายการในการเรียก API เดียวออก คำขอ 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"
    }
  ]
}
    

การตรวจสอบความถูกต้องและ โค้ดตอบกลับของ API

การตรวจสอบในการเรียก API การอัปเดตแบบเรียลไทม์มี 2 ประเภทดังนี้

  • ระดับคำขอ - การตรวจสอบเหล่านี้จะตรวจสอบว่าเพย์โหลดเป็นไปตาม upsert หรือ delete สคีมาและทุกๆ data_record มีทั้งช่อง @id และ @type การตรวจสอบเหล่านี้ทำงานพร้อมกันและผลลัพธ์จะแสดงใน API เนื้อหาการตอบกลับ โค้ดตอบกลับ 200 และเนื้อหา JSON ที่ว่างเปล่า {} หมายความว่า ผ่านการตรวจสอบความถูกต้องและเอนทิตีในคำขอนั้นอยู่ในคิวแล้ว การประมวลผล โค้ดตอบกลับที่แตกต่างจาก 200 หมายความว่าโค้ดต่อไปนี้อย่างน้อย 1 รายการ การตรวจสอบความถูกต้องล้มเหลว และคำขอทั้งหมดถูกปฏิเสธ (รวมถึงคำขอทั้งหมด ในเพย์โหลด) ตัวอย่างเช่น หาก 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\" }"
          }
        ]
      }
    }
    
  • ระดับเอนทิตี - เอนทิตีแต่ละรายการในเพย์โหลดจะได้รับการตรวจสอบเทียบกับ สคีมาแบบสัมพันธ์ ปัญหาที่พบในขั้นตอนการตรวจสอบนี้จะไม่รายงานใน API คำตอบ จะมีการรายงานใน การรายงาน RTU หน้าแดชบอร์ด

โควต้า API

การอัปเดต API แบบเรียลไทม์มีโควต้าคำขอ 1,500 รายการทุก 60 วินาทีหรือ 25 รายการ คำขอต่อวินาทีโดยเฉลี่ย เมื่อเกินโควต้าแล้ว Google จะตอบกลับด้วยข้อความแสดงข้อผิดพลาดต่อไปนี้

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

หากต้องการแก้ไขปัญหานี้ ให้ลองโทรใหม่อีกครั้งเป็นบริเวณที่นานขึ้นจนกระทั่ง ประสบความสำเร็จ หากคุณใช้โควต้าจนหมดเป็นประจำ ให้ลองเพิ่มเอนทิตีให้มากขึ้น ในคำขอ API รายการเดียว คุณรวมเอนทิตีในการเรียก API ได้สูงสุด 1,000 รายการ

ตัวอย่างโค้ด

ด้านล่างนี้เป็นตัวอย่างวิธีใช้ API อัปเดตแบบเรียลไทม์ใน ภาษา ตัวอย่างเหล่านี้ใช้ไลบรารีการตรวจสอบสิทธิ์ของ 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;
  }
}

กรณีการใช้งาน

ต่อไปนี้เป็นตัวอย่างการอัปเดตแบบเรียลไทม์ การอัปเดตฟีดแบบกลุ่ม และเนื้อหาในระดับสูงในการเรียก API

สถานการณ์ เอนทิตีที่จะอัปเดต คำอธิบายและเอฟเฟกต์
การปิดใช้บริการ 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 ว่างเปล่า

เวลาในการประมวลผลสำหรับงานแบบกลุ่มและการอัปเดตแบบเรียลไทม์

ระบบจะประมวลผลเอนทิตีที่อัปเดตหรือลบผ่านฟีดกลุ่มภายใน 2 ชั่วโมงในขณะที่เอนทิตีที่อัปเดตผ่านการอัปเดตแบบเรียลไทม์จะได้รับการประมวลผลใน 5 นาที ต เอนทิตีไม่มีอัปเดต จะถูกลบใน 14 วัน

คุณจะส่งสิ่งต่อไปนี้ให้ Google ก็ได้

  • งานแบบกลุ่มหลายงานต่อวันเพื่อให้สินค้าคงคลังอัปเดตอยู่เสมอ หรือ
  • งานแบบกลุ่ม 1 งานต่อวันและข้อมูลอัปเดตแบบเรียลไทม์เพื่อให้สินค้าคงคลังของคุณเป็นปัจจุบัน