实时更新

实时更新

RTU 主要用于您无法预见的更新,例如紧急封闭或定期更改的元数据(如 ETA)。如果您的更改不需要立即体现出来,您可以改用批量 Feed 提取。实时更新的处理时间不超过 5 分钟。

Google Cloud Platform 设置

  1. 设置 GCP 项目。访问 RTU API 需要使用 GCP 项目。
    • 授予编辑者访问权限 food-support@google.com
    • 将 GCP 项目编号告知您的 Google 联系人。您的 GCP 项目必须与 Actions Center 账号相关联,实时更新才能正常运作。
    • 启用 Maps Booking API:
      • 在 GCP 中,转到 API 和服务 >媒体库
      • 搜索“Google Maps Booking API”。 <ph type="x-smartling-placeholder">
        </ph> 查找 Google Maps Booking API
      • 找到沙盒实例(“Google Maps Booking API(开发版”),然后点击启用
      • 找到正式版实例(“Google Maps Booking API”),然后点击启用 <ph type="x-smartling-placeholder">
        </ph> 启用 Google Maps Booking API
      • 创建对您的 GCP 项目的具有 Editor 角色的服务账号。如需了解详情,请参阅服务账号设置
      • 请确保将批量上传文件上传至正在进行实时更新的环境。
      • 对于 API 身份验证,我们建议您使用自己选择的语言安装 Google 客户端库。使用“https://www.googleapis.com/auth/mapsbooking”作为 OAuth 范围。下面提供的代码示例使用这些库。否则,您需要按照使用 OAuth 2.0 访问 Google API 中的说明手动处理令牌交换。

服务账号设置

您需要拥有一个服务账号才能向 Google API(例如实时更新 API)发出经过身份验证的 HTTPS 请求。

如需设置服务账号,请执行以下操作:

  1. 访问 Google Cloud Platform 控制台。
  2. 您在 Actions Center 中的账号也有一个与之关联的 Google Cloud 项目。选择该项目(如果尚未选择)。
  3. 点击左侧菜单中的服务账号
  4. 点击创建服务账号
  5. 输入服务账号的名称,然后点击创建
  6. 对于选择角色,选择项目 >编辑器
  7. 点击继续
  8. 可选:添加用户以授予他们访问服务账号的权限,然后点击完成
  9. 点击更多 >为您刚刚创建的服务账号创建密钥
  10. 选择 JSON 作为格式,然后点击创建
  11. 生成新的公钥/私钥对后,将其下载到您的计算机。

使用 API

Real-time Updates API 支持两种类型的操作:更新和删除。不支持通过实时更新 API 添加新实体。如果您在单个 API 请求中包含多项更新,则可以批量处理实时更新。单次 API 调用最多可以批量处理 1,000 项更新。如果可能,我们建议采用基于触发器的方法通过 RTU 发送更新(即系统中的数据发生更改时会触发向 Google 发送实时更新),而不是基于频率的方法(即每 X 分钟对系统进行一次扫描以查找更改)。

实时更新 API 在沙盒环境和生产环境中均可运行。沙盒环境用于测试 API 请求和生产环境,以更新向端到端订购用户显示的内容。

  • 沙盒 - partnerdev-mapsbooking.googleapis.com
  • 正式版 - mapsbooking.googleapis.com

端点

实时更新 API 公开了两个端点,用于处理传入的商品目录更新请求:

  • 更新 - /v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchPush
  • 删除 - /v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchDelete

如以下屏幕截图所示,您可以在 Actions Center账号和用户页面上找到参数 PARTNER_ID。

合作伙伴门户上的合作伙伴 ID

以上面的屏幕截图中的 PARTNER_ID 值 10000001 为例,在沙盒环境和生产环境中发送 API 请求的完整网址如以下示例所示。

沙盒更新

https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchPush

沙盒删除

https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchDelete

正式版更新

https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchPush

正式版删除

https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchDelete

更新实体

如需更新清单中的实体,请在 HTTP POST 请求中使用 update 端点。每个 POST 请求都必须包含 10000001 参数,以及包含要更新的实体的 JSON 载荷。

注意:请确保您的每日数据 Feed 还包含通过 Real-time updates API 提交的所有更改。否则,您的数据可能已过时或已过时。

更新请求载荷

请求正文是一个包含记录列表的 JSON 对象。每条记录对应一个要更新的实体。它由 proto_record 字段和指示实体更新时间的 generation_timestamp 组成:

  {
    "records": [
      {
        "proto_record":"ServiceData PROTO",
        "generation_timestamp":"UPDATE_TIMESTAMP"
      }
    ]
  }
  • ServiceData PROTO:您要更新的 ServiceData 实体的 proto 或 JSON 转换。
  • UPDATE_TIMESTAMP:确保包含后端系统中生成实体时的时间戳。如果未添加此字段,则将其设置为 Google 收到请求的时间。通过 batchPush 请求更新实体时,generation_timestamp 字段用于实体版本控制。请参阅关系型产品目录架构中时间值的预期格式。
  • 载荷正文的大小不得超过 5 MB。
  • 删除空格以缩减大小。
  • 一个 batchPush 请求中最多可以有 1,000 项更新。

示例

更新预计到达时间

假设您急需将配送服务的预计到达时间从 30-60 分钟更新为 60-90 分钟。您的更新必须包含整个服务实体的 JSON。

假设某个服务实体的内容大致如下所示:

{
	"service": {
		"service_id": "service/entity002",
		"service_type": "DELIVERY",
		"parent_entity_id": "entity002",
		"lead_time": {
			"min_lead_time_duration": "600s",
			"max_lead_time_duration": "1800s"
		},
		"action_link_id": "delivery_link/entity002"
	}
}

通过 HTTP POST 进行的实时更新如下所示(请求正文打印整齐以便于阅读):

POST v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [{
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "service" : {
        "service_id" : "23456/delivery",
        "service_type" : "DELIVERY",
        "parent_entity_id" : "23456",
        "disabled" : "false",
        "action_link_id": "delivery_link/entity002",
        "lead_time" : {
          "min_lead_time_duration" : {
            "seconds": "3600"
          },
          "max_lead_time_duration" : {
            "seconds": "5400"
          }
        }
      }
    },
    "generation_timestamp": "2023-09-13T17:11:10.750Z"
  }]
}

更新多个实体

如需在单个 API 调用中更新多个餐馆实体,请在请求正文的 proto_record 字段中包含多条记录。

POST v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [{
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "service" : {
        "service_id" : "23456/delivery",
        "service_type" : "DELIVERY",
        "parent_entity_id" : "23456",
        "disabled" : "false",
        "action_link_id": "delivery_link/entity002",
        "lead_time" : {
          "min_lead_time_duration" : {
            "seconds": "1800"
          },
          "max_lead_time_duration" : {
            "seconds": "3600"
          }
        }
      }
    },
    "generation_timestamp": "2023-09-13T17:11:10.750Z"
  },
  {
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "fee" : {
        "fee_id" : "12345/delivery_fee",
        "fee_type" : "DELIVERY",
        "fixed_amount" : {
          "currency_code" : "USD",
          "units" : "10",
          "nanos" : "0"
        },
        "service_ids": ["service/entity002"]
      }
    },
    "generation_timestamp" : "2023-09-13T17:11:10.750Z"
  }]
}

删除实体

如需从目录中删除实体,请在 HTTP POST 请求中使用 DELETE 端点。每个 POST 请求都必须包含 PARTNER_ID 参数以及 JSON 载荷,后者包含您要删除的实体的标识符。

注意:确保每日数据 Feed 也包含通过实时更新 API 提交的所有更改。否则,每天的批量注入会覆盖您的实时更改。

POST v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchDelete
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [{
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "service" : {
        "service_id" : "23456/delivery"
      }
    },
    "delete_time": "2023-09-13T17:11:10.750Z"
  },
  {
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "fee" : {
        "fee_id" : "12345/delivery_fee"
     }
  },
  "delete_time" : "2023-09-13T17:11:10.750Z"
  }]
}

添加实体

请勿使用实时更新来添加新实体,因为这可能会导致数据不一致。而是改用批量 Feed。

验证和API 响应代码

在实时更新 API 调用中会执行两种类型的验证:

  • 请求级 - 这些验证检查载荷是否遵循架构以及每个 proto_record 是否包含 idtype 字段。这些检查是同步的,并且结果会在 API 响应正文中返回。响应代码 200 和空的 JSON 正文 {} 表示这些验证已通过,且请求中的实体已加入队列等待处理。响应代码不是 200 表示这些验证中的一项或多项失败,整个请求(包括有效负载中的所有实体)均被拒绝。例如,如果 proto_record 缺少 @type,系统会返回以下错误响应:
  {
      "error": {
        "code": 400,
    "message": "Record:{...}",
    "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:... The entity type could not be extracted from the entity value." 
      }
    ]
  }
  • 实体级:载荷中的每个实体 (proto_record) 都会根据架构进行验证。在此验证阶段遇到的问题不会在 API 响应中报告。它们仅在 Actions Center 的 RTU 报告信息中心内报告。

注意:200 响应代码并不意味着所有实体都已成功提取。

API 配额

实时 API 更新的配额为每 60 秒 1500 个请求,即平均每秒 25 个请求。超出配额时,Google 会返回以下错误消息:

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

要解决此问题,请以指数级时间再次重试调用,直到成功为止。如果您经常用尽配额,请考虑在一个 API 请求中包含多个实体。一次 API 调用最多可以包含 1,000 个实体。

处理实时更新

通过实时更新更新的实体在 5 分钟内进行处理。