get_item_options
一次批量拉取多个商品的全量规格候选(sku_options),每个规格条目内嵌自己的配料 / 做法候选(sku_options[].ingredient_options),并对「按当前选择下单实际会生效」的项标 selected: true。只读、不改任何状态,与 preview_order 解耦。一次调用里的所有商品必须属于同一个 cart_id(多个店铺 / 购物车请分别调用)。
典型场景:
- 预订单阶段批量修改规格 / 配料:
preview_order之后用户想给车里若干商品换杯型 / 换配料——一次调本工具拿到这些商品各自的全部规格及配料候选,换好 ID 后直接重新preview_order(quote_cart可选)。 - 一次查看整车多个单品的可选项:不必逐个调用、也不必回翻整个菜单响应(编排里少接多个节点)。
- 菜单被分页 / 过滤后按单品回查:对话上下文里菜单被挤掉时,凭
item_id一次找回多个商品的全部可选项和 ID。 - 富化菜单大纲商品:
get_shop_menu传full_menu=true拿到的大纲商品(无规格 / 配料、不可直接下单)——把目标item_id传入本工具即完成按需富化,返回全部规格 / 配料且同一 id 随后可直接下单。
修改闭环:本工具返回的所有
sku_id / option_id 与 get_shop_menu 为该 cart 生成的 ID 完全相同(不重新生成),任意一项可直接回传 quote_cart / preview_order 修改选择;修改后重新调用 preview_order 获取新的 preview_id + confirmation_token 再下单(旧令牌 10 分钟有效且一次性)。参数
返回
顶层返回{ "items": [...] },items 与请求的 items 一一对应、顺序一致(第 i 个结果对应第 i 个请求项)。每个结果要么是成功项(完整规格 / 配料候选),要么是失败项({item_id, error})——靠有没有 error 字段区分。
部分失败不影响其余商品。 某个商品的
item_id 不属于该 cart,或它的 ingredient_option_ids 把同一单选必选组选了两次,只有那一项返回 {item_id, error: {code, message}},其余商品照常返回,整个调用仍算成功(不报错)。但 cart_id / 授权本身无效时整次调用失败(见错误)。selected 与 selected_by_default 的区别。 selected_by_default 是「菜单默认是哪个」;selected 是「这次下单实际会带哪个」,计算与下单链路同源:显式传的选项算上,没传到的必选组自动补该组默认;sku_id / ingredient_option_ids 都不传时即「全默认下单」会带的整套选择。因此可以直接把 selected: true 的项展示为「当前已选」,不会漏掉自动补齐的默认项。配料按规格区分、随规格内嵌。 配料与 SKU 绑定(不同杯型可选项可能不同),因此每个
sku_options[] 条目内嵌该规格自己的 ingredient_options——换规格直接读目标规格的内嵌列表,无需再调一次。selected: true 只会出现在选中规格(sku_options[].selected: true)的配料候选里;其余规格的候选只标 selected_by_default / available(那个规格不会随单,故一律 selected: false)。无规格商品(sku_options 为空数组)的配料候选放在该结果项的顶层 ingredient_options 字段,仅此时出现。选项之间可能互相排斥,候选会跟着当前选择收敛。 有些商品的选项分层级——比如先选咖啡豆,再选萃取方式,能选的萃取方式只有那款咖啡豆对应的几种。与当前选择冲突的候选不会出现在列表里,所以列出来的都能选,不必自己推算哪些能共存。改了选择再调一次,可选集会跟着变。同一组里换一项不受影响。 单选组内换选项是正常操作:传新的
option_id、把同组的旧 option_id 去掉即可,同组其他选项始终在列。每个规格都按它自己的选择判定,换规格直接读目标规格的列表即可。要逐级收敛,每次都得把当前选择回传。 本接口按本次传入的
sku_id / ingredient_option_ids / ingredient_quantities 计算可选性,不记住上一次。选了一项就带着它重新调一次,才能看到收敛后的候选集。⚠️ 同名不同项:不同上层选择对应的选项可能重名(如 3 款咖啡豆各有一个「原萃浓缩」),务必按 option_id 区分。按名称比较会得出「换了上层选择、候选没变」的错误结论——实测换三款咖啡豆,可选萃取是三组完全不重叠的 option_id,而三组名字完全相同。算价只在你自己选出互斥对时报错。 同时传入互相排斥的两项,
quote_cart 返回 can_checkout: false 并在 blocking_reason 里点名双方。但只传一个与默认项冲突的选项时,算价会成功:你显式选的那项会保留,而你没指定的组会被换成能与它共存的选项。要确认实际下单的组合,看 quote_cart / preview_order 的 items[].selected_ingredients 回显,不要假设「传什么就是什么」。份数型选项用 2 份免费、第 3 份才 ¥4;「摩卡酱」是 14 份 ¥3、5~8 份一共 ¥6。带
ingredient_quantities 加份。 max_quantity 大于 1 的选项(如星巴克「浓缩份数」)在 App 上是加减号,可加多份。下单时用 quote_cart / preview_order 的 items[].ingredient_quantities 指定份数;不传则按各选项的 default_quantity(商家推荐份数)下单。加多份的钱不能拿 price_delta 乘份数。 商家常按档位定价:「浓缩份数」是 1price_steps 的选项照它查表;没有这个字段也不要乘——那表示加多少份都收 price_delta 这一个数。换句话说,任何时候都不需要拿份数去乘。
失败项字段:
grouped=true 时配料换一种形状返回。 传 grouped=true 后,配料不再是平铺的 ingredient_options,而是按组返回 ingredient_groups:组信息(group_name / required / multi_select / max_select)只出现在组上一次,不再逐条重复;选项本身放在 options[] 里,字段与平铺形式逐字段一致。两种形式二选一,不会同时出现,内容完全相同。错误
示例
请求(用户已在 preview 选了大杯,想看这个商品以及另一个商品还能换什么):item_id 无效):

