入选理由Shopify Tax 管理模式的 API 写入校验与税务设置变更,属合规技术细节
Shopify Tax 托管模式
Managed mode for Shopify Tax
Shopify Tax 托管模式通过直接管理部分商店设置和 API 行为,帮助 Shopify 对美国销售应用正确的税务处理方式。为保持这些设置一致,部分 Admin API 写入操作现在会根据托管模式的要求进行验证。
托管模式设定了一系列要求,Shopify 以此保持整个商店的税务处理方式一致。在某些情况下,API 现在会阻止应用写入与这些要求冲突的设置。在另一些情况下,税务处理方式现在取决于更具体的产品或商店数据,而不是简单的布尔设置。
对应用开发者来说,主要规律是:
- 已经使用必需设置,或省略应用无需管理的设置的请求,可以继续正常运行。
- 尝试覆盖托管模式要求的请求现在可能返回验证错误。
这些变更会影响为使用 Shopify Tax 托管模式的商店配置市场、发布产品、创建自定义订单项或预览结账页面品牌样式的应用。变更分为四类:
- 破坏性变更: Markets API 写入操作和产品发布写入操作现在可能在与 Shopify Tax 托管模式的要求冲突时失败。
- 弃用: 自定义订单项上的
taxable输入已被弃用,改用productCategoryId。 - 新功能: 应用可以为订单草稿和订单编辑中的自定义订单项指定产品类别。
- 行为说明: 结账页面页脚的可见性仅控制商家可配置的内容,不控制 Shopify 提供的交易信息。
破坏性变更:Markets API 写入操作需要使用固定的美国默认设置
对于使用 Shopify Tax 托管模式处理美国销售的商店,marketCreate
和 marketUpdate
变更操作现在会拒绝针对受影响市场覆盖必需的货币和税费显示默认设置的尝试。该验证仅适用于包含美国的商家管理的非零售市场。不包含美国的市场、零售市场以及第三方管理的市场均不受影响。
不使用 Shopify Tax 托管模式的商店不受影响,即使它们向美国客户销售也是如此。
受影响的请求
此变更适用于所有受支持的 API 版本,包括 unstable。只有当请求提供 currencySettings 或 priceInclusions 时才会进行验证,因此省略这些输入的请求不受影响。提交其中任一输入时,Shopify 会验证最终的设置,包括保留的值以及省略的子字段的默认值。
如果你的应用设置了这些字段,请使用必需的默认值,或省略应用无需管理的字段。
对于仅包含美国的市场,以下可选输入使用必需的默认值:
1
2
3
4
5
6
7
8
9
{
"currencySettings": {
"baseCurrency": "USD",
"localCurrencies": false
},
"priceInclusions": {
"taxPricingStrategy": "ADD_TAXES_AT_CHECKOUT"
}
}
{
"currencySettings": {
"baseCurrency": "USD",
"localCurrencies": false
},
"priceInclusions": {
"taxPricingStrategy": "ADD_TAXES_AT_CHECKOUT"
}
}
对于包含美国和另一个国家(例如加拿大)的市场,以下可选输入使用必需的默认值:
1
2
3
4
5
6
7
8
{
"currencySettings": {
"localCurrencies": true
},
"priceInclusions": {
"taxPricingStrategy": "INCLUDES_TAXES_IN_PRICE_BASED_ON_COUNTRY"
}
}
{
"currencySettings": {
"localCurrencies": true
},
"priceInclusions": {
"taxPricingStrategy": "INCLUDES_TAXES_IN_PRICE_BASED_ON_COUNTRY"
}
}
通过 userErrors.code、userErrors.field 和 userErrors.message 处理验证错误。违反货币要求时返回 UNSUPPORTED_CURRENCY。违反税费显示要求时,在 API 版本 2026-07 及更高版本中返回 INCOMPATIBLE_CONFIGURATION,在更早版本中返回 GENERIC_ERROR。
相关文档
破坏性变更:产品发布要求包含 Shop 渠道
对于使用 Shopify Tax 托管模式的商店,发布到 Online Store、Headless、Hydrogen 或 Buy Button 的产品也必须发布到 Shop。这些渠道依赖 Shop,因此,如果某个请求会导致产品发布在其中一个渠道上却未发布到 Shop,系统会根据 API 版本以不同方式处理。在 unstable 中,请求会失败。在带日期的版本中,Shopify 会将缺少的 Shop 或依赖渠道变更加到请求中并保存。Shopify 不会保存失败请求的任何部分。
下文所述的失败情况适用于 unstable API 版本。带日期的版本采用相同的规则,但会修改请求而不是使其失败。请参阅带日期的 API 版本
。不使用 Shopify Tax 托管模式的商店不受影响,仅更改其他销售渠道、产品系列或产品多属性的请求也不受影响。此变更正在逐步向使用托管模式的商店推出,架构没有变化。
受影响的请求
产品在某个渠道上发布、计划在该渠道上发布,或作为草稿产品被添加到该渠道时,均视为处于该渠道。一个请求如果同时包含 Shop 和依赖渠道,无论顺序如何,都会作为一个整体进行检查。
此验证适用于 publishablePublish、publishableUnpublish 和 publicationUpdate。它也适用于已弃用的 GraphQL 发布 API,包括 productPublish、productUnpublish,以及 productCreate 和 productUpdate 上的发布字段。对于 REST Admin API,如果创建或更新产品的请求会使产品在未处于 Shop 或被 Shop 阻止的情况下出现在 Online Store 上,该请求将失败。
还有其他验证规则:
-
当 Shop 拒绝某个产品或将其标记为需要采取措施时,即视为 Shop 阻止了该产品。如果 Shop 阻止了该产品,且操作后的状态使其仍处于某个依赖渠道上,
publishablePublish就会失败,即使请求仅发布到 Shop 也是如此。如果 Shop 阻止了该产品,且操作后的状态使其仍处于某个依赖渠道上,productUpdate也会失败。 -
从 Shop 移除产品时,必须同时移除它在依赖渠道上的发布,无论发布处于何种状态。这适用于
publishableUnpublish,也适用于通过publicationUpdate从 Shop 移除产品。 -
对于
publicationUpdate: -
如果产品未处于 Shop 或被 Shop 阻止,将其添加到依赖渠道的操作会失败。如果被阻止的产品仍处于某个依赖渠道上,将其添加到 Shop 的操作也会失败。已处于目标发布中的产品,即使包含在
publishablesToAdd中,也不会受到检查。 -
当 Shop 的发布未启用自动发布时,
publicationUpdate会拒绝在依赖渠道上设置autoPublish: true。当某个依赖渠道仍启用自动发布时,它也会拒绝在 Shop 上设置autoPublish: false。 -
在
productUpdate中,发布列表会替换产品的整个发布列表。只要替换列表中包含依赖渠道,就必须包含 Shop,即使产品已经处于 Shop 上也是如此。当请求同时更改状态时,验证使用新状态。
已弃用的 productPublish 和 productUnpublish 变更操作分别遵循与 publishablePublish 和 publishableUnpublish 相同的失败条件。
带日期的 API 版本
在带日期的 API 版本中,Shopify 会修改违反这些规则的请求,使其符合规则,然后保存该请求:
- 将产品发布到依赖渠道时,也会将其发布到 Shop。Shop 不支持定时发布,因此即使依赖渠道设置了定时发布,Shopify 也会立即将产品发布到 Shop。
- 从 Shop 移除产品时,也会将其从依赖渠道中移除。
- 在
productCreate和productUpdate中,包括产品级别的发布字段在内,当请求将产品发布到 Online Store 或其他依赖渠道时,也会将其发布到 Shop。在productUpdate中,如果发布渠道列表未包含 Shop,产品仍会保留在 Shop 上。 - 对于
publicationUpdate,将产品添加到依赖渠道时,也会将其添加到 Shop;从 Shop 移除产品时,也会将其从依赖渠道中移除。为依赖渠道启用autoPublish时,也会为 Shop 启用该功能。关闭 Shop 的autoPublish时,也会关闭依赖渠道的该功能。 - Shop 拒绝产品或将其标记为“需要采取操作”,都不会阻止请求执行。
- REST Admin API 的产品、产品列表和产品发布请求也遵循相同的行为。
如果经过这些更改后请求仍违反规则,请求将失败并返回与 unstable 中相同的错误。例如,当草稿产品在未发布到 Shop 的情况下被安排在依赖渠道定时发布时,就会发生这种情况。
请注意:
- 如果你的应用将产品发布到 Online Store、Headless、Hydrogen 或 Buy Button,请先将产品发布到 Shop,或在同一请求中包含 Shop。如果你的应用从 Shop 取消发布产品,请先从依赖渠道取消发布,或在同一请求中包含这些取消发布操作。
- 如果你的应用通过 REST Admin API 创建活跃状态的产品,请发送
"published": false,然后使用publishablePublish将产品发布到 Shop 和 Online Store。 - 在按日期命名的 API 版本中,即使你的请求没有指定这些渠道,Shopify 也可能将产品发布到 Shop,或从依赖渠道移除产品。要控制结果,请在请求中同时包含 Shop 及其依赖渠道。
请将这些失败作为验证错误处理。重试相同的请求会返回相同的错误。发布请求失败时会返回 For the store setup, Shop publication is a prerequisite。取消发布请求失败时会返回 For the store setup, unpublishing from dependent publications is a prerequisite。
相关文档
已弃用:自定义订单项上的 taxable
草稿订单和订单编辑中自定义订单项的 taxable
输入已弃用,请改用 productCategoryId。它会从 Shopify 标准产品分类体系中指定一个类别,让 Shopify 确定该订单项的税务处理方式。
在 GraphQL Admin API 版本 2027-01 及更高版本中,DraftOrderLineItemInput.taxable 和 orderEditAddCustomItem 上的 taxable 参数已标记为弃用。使用 API 版本 2026-10 或更早版本的应用不会看到架构变更。
- 读取
taxable状态并未弃用,因此,返回订单项是否应税的字段以及包含应税状态的 webhook 负载均保持不变。 - 对于使用 Shopify Tax 托管模式的商店,所有 API 版本都会忽略自定义订单项上的
taxable。产品类别决定税务处理方式,未指定类别的自定义订单项按标准税率征税。对于所有其他商店,taxable仍按原有方式运作。
如果你的应用在创建或编辑自定义订单项时设置了 taxable,请在 GraphQL Admin API 版本 2027-01 或更高版本中将其替换为 productCategoryId。要对使用 Shopify Tax 托管模式的商店中的整份草稿订单免税,请将客户、公司或公司地点标记为免税。要对单个订单项免税,请使用类别。
相关文档
新增:在草稿订单和订单编辑中为自定义订单项设置产品类别
现在,你可以从 Shopify 标准产品分类体系中为草稿订单和订单编辑中的自定义订单项指定类别。该类别控制订单项税务处理方式的方式与产品相同。
对于使用 Shopify Tax 托管模式的商店,productCategoryId 是设置自定义订单项税务处理方式的输入。系统会忽略 taxable 输入。未指定类别的自定义订单项会被视为未分类,并按标准税率征税。
对于不使用 Shopify Tax 托管模式的商店,taxable: false 仍表示自定义订单项不征税。当订单项需要征税时,Shopify 可以使用其类别计算税额。
受影响的请求
在草稿订单中,DraftOrderLineItemInput.productCategoryId 用于在 draftOrderCreate、draftOrderUpdate 和 draftOrderCalculate 中设置自定义订单项的产品类别。提供 variantId 时,该字段会被忽略。你可以从 DraftOrderLineItem.productCategory 和 CalculatedDraftOrderLineItem.productCategory 读取已保存的类别;对于产品变体订单项,这些字段返回 null。
在订单编辑中,orderEditAddCustomItem 接受一个新的 productCategoryId 参数。你可以从 CalculatedLineItem.productCategory 读取类别。
如果 productCategoryId 与当前分类体系中的任何类别都不匹配,该变更操作会返回用户错误。
产品类别可以表达优惠税率、免税情况以及特定类别的税收规则,而只能表示是或否的 taxable 值无法做到这一点。要使用产品类别,请通过 taxonomy 查询查找类别 ID,将该 ID 作为 productCategoryId 传入,然后从相应的 productCategory 字段读取已保存的类别。
1
2
3
4
5
6
7
8
9
10
query {
taxonomy {
categories(search: "t-shirts", first: 5) {
nodes {
id
fullName
}
}
}
}
query {
taxonomy {
categories(search: "t-shirts", first: 5) {
nodes {
id
fullName
}
}
}
}
相关文档
澄清:结账页面页脚可见性仅控制商家可配置的内容
CheckoutBrandingFooterContent 和 CheckoutAndAccountsConfigurationBrandingFooterContent 上的可见性字段现在仅控制商家可配置的页脚内容。当可见性设置为 HIDDEN 时,所有结账页面和感谢页面仍可在页脚显示由 Shopify 提供的其他交易信息。
商家可配置的页脚内容包括商家政策链接和版权文案。Shopify 提供的交易信息是结账流程的一部分,不受结账品牌设置控制,也无法通过这些可见性设置进行配置。
此更改会影响通过旧版 Checkout Branding API 或 Checkout and Accounts Configuration API 为 Shopify Plus 商店自定义结账品牌的应用,尤其是管理页脚可见性、渲染品牌预览或运行视觉测试的应用。不管理结账页面页脚可见性的应用不受影响。
字段、输入类型、枚举值、访问范围和变更操作均未发生变化。此澄清适用于存在相应品牌类型的所有 GraphQL Admin API 版本,不与任何新 API 版本绑定。
现有的变更操作和已保存的品牌配置无需修改即可继续使用。如果你的应用会预览或测试结账页面的品牌样式,请更新应用,确保在商家可配置的页脚内容被隐藏时,Shopify 提供的交易信息仍然可见。
相关文档
此页面有帮助吗?
有没有