You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Stripe订阅升级时基于已用请求量自定义计费?

解决方案:自定义请求量计费的订阅升级实现

要实现基于已使用请求量的订阅升级计费,核心是自行维护使用量数据,结合Stripe的发票项和客户余额功能替代默认的时间比例计费,具体方案如下:

核心思路

放弃Stripe默认的按时间 prorate逻辑,改为:

  1. 自有服务记录用户每个订阅周期内的请求使用量(无需每次请求调用Stripe)
  2. 用户升级时,计算旧订阅的实际消耗费用和未使用额度的抵扣金额
  3. 通过Stripe的「一次性发票项」或「客户余额」调整最终需支付的升级差价

具体实现步骤

1. 维护用户请求使用量

在你的数据库中为每个用户/订阅记录:

  • 当前订阅套餐类型(基础/高级)
  • 周期内已使用请求数
  • 订阅周期的起始/结束时间

每次用户发起请求时,仅在自有数据库中做原子递增操作(例如UPDATE users SET used_requests = used_requests + 1 WHERE id = ?),完全无需调用Stripe,避开速率限制。

2. 计算升级时的实际费用差

假设用户从基础版(10美元/400次)升级到高级版(20美元/800次),已使用2次请求,订阅周期已过15天:

  • 旧套餐单次请求成本:10美元 / 400次 = 0.025美元/次
  • 旧套餐已消耗费用:2次 × 0.025美元 = 0.05美元
  • 旧套餐未使用的可抵扣额度:10美元 - 0.05美元 = 9.95美元
  • 新套餐剩余周期费用:20美元 × (剩余天数/总天数) = 20 × 15/30 = 10美元
  • 最终需支付的差价:10美元 - 9.95美元 = 0.05美元

3. 用Stripe API完成升级操作

方案A:变更订阅 + 一次性发票项

使用Stripe SDK将旧订阅切换为新套餐,关闭自动按比例计费,再添加计算好的差价作为一次性发票项:

const stripe = require('stripe')('your_secret_key');

// 1. 获取用户的旧订阅
const subscription = await stripe.subscriptions.retrieve('sub_xxxx');

// 2. 变更订阅为新套餐,关闭自动prorate
const updatedSubscription = await stripe.subscriptions.update(
  'sub_xxxx',
  {
    items: [{
      id: subscription.items.data[0].id,
      price: 'price_xxxx' // 高级版的价格ID
    }],
    proration_behavior: 'none', // 关闭Stripe默认的按时间计费
    payment_behavior: 'default_incomplete', // 允许后续添加发票项后再支付
    payment_method: subscription.default_payment_method
  }
);

// 3. 添加一次性发票项,金额为计算出的差价(单位:分)
await stripe.invoiceItems.create({
  customer: subscription.customer,
  subscription: updatedSubscription.id,
  amount: 5, // 0.05美元 = 5分
  currency: 'usd',
  description: '订阅升级差价(基于已使用请求量)'
});

// 4. 生成并支付发票
const invoice = await stripe.invoices.retrieve(updatedSubscription.latest_invoice);
await stripe.invoices.pay(invoice.id);

方案B:客户余额抵扣 + 新订阅

如果不想直接变更旧订阅,可以先给用户添加信用额度,再创建新订阅:

// 1. 计算旧订阅未使用的可抵扣额度(9.95美元 = 995分)
await stripe.customers.update(
  'cus_xxxx',
  {
    balance: -995 // 负数值表示客户有信用额度
  }
);

// 2. 创建新的高级版订阅,系统会自动用余额抵扣
const newSubscription = await stripe.subscriptions.create({
  customer: 'cus_xxxx',
  items: [{ price: 'price_xxxx' }],
  payment_behavior: 'default_incomplete',
  payment_method: 'pm_xxxx'
});

关键注意事项

  • 数据一致性:确保请求量记录准确,使用数据库原子操作避免并发计数错误
  • 周期重置:订阅周期结束时,务必重置用户的已使用请求数
  • 异常处理:处理Stripe API调用失败的情况(比如支付失败),回滚相关的使用量记录或信用额度调整

内容的提问来源于stack exchange,提问作者hamza zahid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 16:50:31