Skip to main content

get_shop_menu

拉取一个店铺的菜单。返回的每个菜单项带网关生成的 item_id(及可选 sku_id / option_id),这些 ID 是后续 quote_cart、preview_order、create_order 唯一可用的下单凭据。菜单可能很大(100+ 项),支持 keyword 过滤与 limit / offset 分页(渐进式披露)。
下单链路:search_shops 得 shop_id + cart_id(已含配送坐标)→ get_shop_menu 选商品得 item_id / sku_id → quote_cart 算价得 quote_id → select_address 得 address_id → preview_order 得 preview_id + confirmation_token → create_order。菜单必须基于一个已存在的 cart_id,且 shop_id 必须与该 cart_id 匹配(同一次 search_shops 返回)。

参数

address_id / lat / lng 三者用于解析配送坐标,通常无需传:cart_id 已封装搜索时的坐标。三者同时不传时使用 cart_id 内坐标。
菜单大纲(full_menu=true):一次返回全部分类的全部商品卡片(item_id / name / price / available / image_url 及营销字段),sku_options / ingredient_options 恒为空数组——适合大菜单先速览全貌(不逐品拉规格,响应快)。大纲商品的 item_id 稳定(同一 cart_id 内与富化后相同),但不可直接下单:大纲 id 未写入购物车,直接传给 quote_cart / preview_order / create_order 会报 PUBLIC_REFERENCE_INVALID。要下单先富化目标商品——再调 get_shop_menu(用 keyword / limit 定位该商品)或用 get_item_options 按需批量拉取规格,随后用同一 item_id 下单。full_menu=true 表示**「完整结果、不分页」**:limit / offset 被忽略、has_more 恒为 false;keyword 照常生效——它决定这份完整结果是整本菜单还是全部命中商品,search_match_level 也照常返回。在大菜单里找菜,full_menu=true + keyword 最快。大纲里的 price 是该商品自己的价格;多规格商品那是首档价,不是价格区间(标 21.9 的拿铁,大杯可能要 24.9)。各规格的真实价格请从 get_item_options 读。

返回

所有金额字段(price / original_price / price_delta)单位为分(整数),不是元。例如 price: 1600 表示 ¥16.00。
配料按规格区分。 配料与具体规格(SKU)绑定——不同杯型可选的配料及其内部标识可能不同。顶层 items[].ingredient_options 对应默认规格;选其他规格时请使用该规格 items[].sku_options[].ingredient_options 里的 option_id。若沿用默认规格的 option_id 下非默认规格,网关会按「组名 + 选项名」自动映射到该规格的对应配料;该规格不存在的配料会在 quote_cart / preview_order 阶段报错(而非到 create_order 才失败)。
店铺级必选商品组。 部分店铺(麻辣烫、部分套餐店)要求整单必须包含某类商品——如麻辣烫的「必选好汤」,不选汤底上游会拒单。这类约束通过 required_groups 暴露:下单前须从每个 required_groups[].candidate_item_ids 里至少选 min_select 个商品,作为普通条目加入 items[](候选详情直接看 required_groups[].candidates——含 name/price/available、始终完整;带 keyword 或分页拉菜单时必选候选可能不在当前页 items[] 中)。未选满时 quote_cart 返回 can_checkout=false + blocking_reason,preview_order 直接报 MISSING_REQUIRED_SELECTION(HTTP 400)。这与商品内的配料必选组(ingredient_options 里的必选做法组,如奶茶必选温度 / 糖度)是两个层次:前者是「必须再点一个商品」,后者是「某商品内部必须选够做法」。
菜单里的 available 不含互斥判定。 有些商品的选项分层级——先选咖啡豆,再选萃取方式,能选的萃取只有那款豆对应的几种。这种可选性取决于「当前选了什么」,而本接口没有表达当前选择的入参,所以菜单只列出候选、available 只反映售罄 / 下架。要判断当前选择下某项能不能选,用 get_item_options(它接收当前选择、能逐级收敛)。菜单里的 option_id 仍可直接用于下单。
| required_groups | array | 店铺级必选商品组(如麻辣烫「必选好汤」);整单须从每组 candidate_item_ids 至少选 min_select 个商品才能下单,无此约束时为 [] | | required_groups[].name | string | 必选组名(如「必选好汤」)| | required_groups[].required | boolean | 恒为 true | | required_groups[].min_select | integer | 该组至少需选的商品数(当前恒为 1)| | required_groups[].candidate_item_ids | array | 候选商品的 item_id 列表;从中至少选 min_select 个,作为普通商品加入下单 items[] | | required_groups[].candidates | array | 候选商品详情 [{item_id, name, price, available}],与 candidate_item_ids 一一对应且始终完整(与 keyword/分页解耦);agent 直接据此展示候选,无需回查 items[] |
keyword 怎么匹配、结果怎么排。匹配分五档,严格档有结果就到此为止,不会被宽松结果稀释——search_match_level 告诉你落在哪一档:拿到 abbrev / fuzzy / partial 时,下单前请先确认返回的菜确实是用户要的那道。partial 最宽松,可能给出相近而非同一样东西(没有面的店里搜「牛肉面」会返回「牛肉汉堡」)。拿到 none 不代表这家店没有——字面匹配跨不过同义词(「鸡肉汉堡」对「香辣鸡腿汉堡」),请去掉 keyword 重拉再自己找(想快就同时加 full_menu=true)。注意:保留 keyword 只加 full_menu=true 仍然是空——full_menu 不会关掉过滤,它只是不分页、不拉规格。items[] 的顺序:商品名含关键词的排在前面,只靠分类名或描述匹配上的排在后面;加料 / 小料 / 餐具 / 打包这类配件分类的商品排在最后(搜「珍珠」先给「珍珠奶茶」,「珍珠(分装)」垫底)。同一档内保持菜单原顺序。categories[] 不参与重排,始终是菜单原顺序,可直接用作分类导航。
渐进式披露:用 keyword 缩小范围,或用 limit + offset 翻页。has_more 为 true 时,带 offset=next_offset 继续调用,直到 has_more 为 false。同一 cart_id 上之前各次调用返回的 item_id 在购物车存活期内仍可下单。大菜单也可先 full_menu=true 一次速览全貌,再对目标商品富化(keyword / limit 或 get_item_options)。要在大菜单里快速定位某道菜,full_menu=true + keyword 一步到位。
grouped=true 时配料换一种形状返回。 传 grouped=true 后,配料不再是平铺的 ingredient_options,而是按组返回 ingredient_groups:组信息(group_name / required / multi_select / max_select)只出现在组上一次,不再逐条重复;选项本身放在 options[] 里,字段与平铺形式逐字段一致。两种形式二选一,不会同时出现,内容完全相同。

错误码

完整错误码见 错误处理。

调用示例