Skip to main content
门店的菜单是顾客点餐所依据的目录。您将它作为一个 JSON 文档发布,其中描述整个菜单——分类、菜品、规格、加料选项,以及适用的税费定义。Maple 以您分配的外部 ID 作为全部依据,因此每个订单行项目上的 menu_entity_id 会直接对应回您自己的商品目录。 发布需要 menus:write 权限,并且与该门店之间存在有效连接。读取需要 menus:read。有关连接,请参阅Maple 如何运作。

菜单的结构

菜单是一棵树,旁边还有共享的定义:
两条规则涵盖了模型的大部分内容:
  • 每个对象都有一个 externalId——这是您为它设置的稳定标识。由您来选择,Maple 绝不会更改。使用相同的 externalId 重新发布,会更新同一个对象。响应中还会生成 Maple 自己的 ID(item_…、var_…、ctg_…)供参考,但您应通过自己的 externalId 来定位对象。
  • 价格在规格(variation)上。 即使是最简单的菜品,也至少有一个规格(可称之为”Regular”)。所有价格都是整数的最小货币单位——450 即 $4.50。

最小菜单

最小的有效文档包含一种货币,以及一个包含一个菜品、一个规格的分类:
发布成功后会返回最终的菜单,其中所有集合都已展开,并填入了 Maple ID。您发送的 externalId 会原样返回。

添加共享加料选项

在顶层定义一次加料组,然后在需要的地方通过 groupId 引用——这样”Milk options”只需维护一处,即可用于所有饮品:
加料组条目要么是内联定义(包含 name 和 options),要么是引用({ "groupId": "grp-milk" })。不要在同一个条目中混用这两种形式——这样的负载会被拒绝,而不是被悄悄截断。菜品、规格和单个选项都可以带有加料组,因此您可以在菜单需要的地方嵌套选项。
税类别和税率、费用(例如瓶装押金)、折扣、促销和优惠券都是可选的顶层集合,每个都通过各自的 externalId 定位,并通过 ID(taxCategoryId、feeIds 等)关联到菜品。端点参考记录了每个字段。

发布语义

每次发布都会把整个菜单作为期望状态发送。Maple 会将其与当前菜单进行差异比较(以 externalId 为键),并将结果作为新版本应用。由此衍生出几条规则:
  • 文档就是整个菜单。 您发送的内容就会成为菜单。您之前发布过、但在后续发布中遗漏的对象会被移除——要保留某个对象,每次都要包含它。
  • stockStatus 是例外。 它是字段级的值:在您_确实_包含的对象上省略它,会保留该对象当前的库存状态(新对象默认为 in_stock)。因此,将某个菜品标记为售罄(86)仍然是一次包含所有对象的完整发布——只是您设置了一个字段。
  • 标识就是您的 externalId。 相同的 externalId 在多次发布中更新同一个对象;新的 externalId 会创建新的对象。请使用在您的系统中稳定的 ID(SKU 或主键),而不是显示名称。
  • 顺序会被保留。 分类、菜品、规格和选项会按照您发送的顺序显示。
  • 校验是全有或全无。 只要有任何无效内容,您就会收到列出所有问题的 400,菜单保持原样不变。请全部修复后重新发送。
  • 完全相同的重复发布不会产生任何影响。 发送相同的文档不会改变任何内容,也不会产生多余的变动,因此您可以在每次菜单变更时放心发布。
  • 每次变更都会生成版本。 内容变更会产生新版本;门店始终使用当前版本。
由于文档就是完整的期望状态,最简单的集成方式是:每当您的数据源变化时,重新发布整个菜单。您无需自己计算差异——Maple 会完成。

设置可用时间的时区

可用时间窗口(时段菜单和欢乐时光)按菜单的时区计算。请通过顶层的 timezone 字段设置——使用 IANA 名称,例如 America/New_York:
如果省略,菜单的时区默认为 UTC,这对于基于时间的规则几乎总是不对的。时区在您第一次发布时确定,因此请一开始就设置正确。

读取回来

返回当前已发布的菜单——分类、带价格的菜品和规格、共享加料组,以及税费和折扣定义——每个对象都会回显您发布时使用的 externalId。没有已发布菜单的门店会返回 404。

了解发布何时生效

订阅菜单同步事件,以便在已发布的菜单传播时收到通知: 如何订阅并验证这些事件,请参阅Webhook。

下一步

接收并决定订单

订单行项目通过您分配的 externalId 引用您的菜单。

完整菜单架构

端点参考中每个菜单对象的每个字段。