EN
Shopify 知识库 · 指南

Shopify App 用量计费:先定义单位,再接账单

从同步类 Shopify App 出发,说明如何定义可解释的计费单位,区分预览、跳过与真实写入,并用内部账本、幂等上报、周期额度和执行前报价避免重复或意外收费。

用量计费最难的部分通常不是调用收费接口,而是定义什么才算一次可收费的结果。一个含糊的“操作次数”会把预览、跳过、失败重试和真正写入混在一起,最终让商家无法预测账单,开发者也无法可靠对账。

Shopify 目前有两条计费路径,设计计量模型前必须先确定用哪一条,因为它们的额度能力完全不同。

Shopify App PricingBilling API(manual pricing)
定位官方对公开应用的推荐方式仍受支持,用于既有应用和前者未覆盖的定价模型
用量配置在 Partner Dashboard 的 Pricing 中定义 usage meter,通过 App Events API 上报 billing eventappSubscriptionCreate 等 GraphQL mutation
周期上限当前不支持 usage capcappedAmount 限定 30 天周期内的计费上限

Shopify App Pricing 的用量计费还有几条硬约束会直接影响实现:每个套餐最多 5 个启用的 usage meter,每个 meter 最多 6 个价格档,用量计费必须按月结算(不能与只按年付的套餐组合),商家卸载应用后只有 24 小时可以补交剩余 billing event。usage charges 文档、Billing API 用量订阅

平台负责订阅与账单,应用仍需负责业务计量、费用预估和上报幂等。

先定义计费单位

一个好单位应满足四个条件:

  • 商家在执行前能理解。
  • 应用在执行后能精确计算。
  • 重试不会产生第二份有效用量。
  • 单位与主要成本大致相关。

以跨店同步为例,可以定义“每个成功写入目标店的资源或字段值”为一个单位。但必须继续明确:

结果是否计费原因
只做差异预览否尚未改变目标店
目标已经一致而跳过否没有产生新的写入结果
写入失败否商家没有获得承诺结果
写入成功是产生一个可验证的目标结果
同一项失败后重试成功一次结果只应被确认一次
成功后用户主动再次覆盖按产品规则需要在定价说明中明确

不能直接复用任务的 done 数量收费。很多任务引擎会把“已经一致”“找到现有映射”也记为完成,但完成不等于发生了应计费写入。

预估与结算使用同一集合

执行前的报价应来自同一份权威 diff:

候选资源
  → 过滤已一致、不可执行和缺少依赖项
  → 得到预计写入集合
  → 计算预计单位和最高费用

执行后再以真实成功写入集合结算。预估不是最终账单,但两者的分类规则必须一致,否则用户会看到“预计 20,实际 87”而不知道差异来自哪里。

费用确认界面至少显示:

  • 本次预计单位。
  • 套餐内剩余额度(使用 Shopify App Pricing 时由应用自己维护并执行,平台不提供 usage cap)。
  • 可能产生的超额费用。
  • 失败和跳过是否收费。
  • 明确的取消与确认操作。

不要用一个没有可见操作按钮的提示条阻塞任务。计费确认是一个需要用户做决定的流程,应提供稳定、可返回的确认界面。

内部账本是事实来源

应用应先写内部用量账本,再把待上报事件发送到 Shopify:

UsageLedger
- shopId
- billingCycleId
- operationId
- itemKey
- units
- status: pending | reported | failed
- providerRecordId
- createdAt

推荐的唯一边界是 (operationId, itemKey, meter) 或能表达同等语义的幂等键。任务重启、网络超时或 worker 重试时,同一业务结果只能生成一条有效账本记录。

账本把“业务已经成功”和“Shopify 已经接受上报”拆开:

  1. 目标写入成功。
  2. 以幂等键写入本地账本。
  3. 异步上报 Shopify。
  4. 保存平台记录 ID 或失败原因。
  5. 定期补报 pending 项,并与 Shopify 账单状态对账。

补报窗口不是无限的:使用 Shopify App Pricing 时,商家卸载后只有 24 小时提交剩余 billing event。补报任务必须以卸载事件为触发点抢先清空该店的 pending 记录,不能只依赖固定间隔的定时扫描。

如果直接在业务请求末尾调用收费接口,网络超时会留下两种坏结果:写入成功但漏收费,或重试后重复收费。

周期、额度与试用

额度不是一个永久累加数字,需要绑定明确账单周期。使用 Shopify App Pricing 时平台不会替你封顶,超额保护完全由应用实现;使用 Billing API 时 cappedAmount 限定 30 天周期上限,提高上限需要商家同意(商家也可在后台自行调整);用量达到上限的 90% 时平台会发送 APP_SUBSCRIPTIONS_APPROACHING_CAPPED_AMOUNT Webhook,应用仍要在本地跟踪余量以便提前提示。跨周期运行的长任务,应在开始时锁定计费规则,或逐项按实际完成时间归入周期;两种做法都可以,但必须提前说明并保持一致。

试用也需要独立规则:

  • 试用期是否有单位上限。
  • 超出后暂停还是开始计费。
  • 转付费后是否获得新的周期额度。
  • 试用中创建、试用结束后才完成的任务如何处理。

不要用“试用免费”代替这些定义。免费只说明价格,不说明资源限制和跨周期归属。

成本保护

预览不收费,不代表预览可以无限消耗资源。对于需要大量 API 查询、计算和数据库访问的预览,应增加:

  • 按能力区分的限流键,避免文件列表和费用报价误用同一冷却时间。
  • 单店并发限制。
  • 单次扫描上限和分页。
  • 队列容量与超时。
  • 预算或异常用量提醒。

这些限制应描述为服务保护,而不是偷偷计入同步单位。

对账与验收

  • 同一成功项重试多次,账本和 Shopify 最终都只计一次。
  • 跳过、失败和预览不会产生收费记录。
  • 上报接口超时后能够安全补报。
  • 任务跨账单周期时,单位归属符合公开规则。
  • 商家卸载后,该店的 pending 账本能在 24 小时窗口内完成补报或明确放弃。
  • 套餐升级、取消和试用结束后,权限与账本周期同步变化。
  • 商家能看到已用、剩余、重置时间和本次预计费用。
  • 应用能从业务记录追溯到平台收费记录,也能反向解释账单来源。

Shopify 的收费能力解决“怎样进入商家账单”,计量模型解决“为什么该收这笔钱”。后者应该先于价格表和 API 接入完成。