立即收取订阅更改费用

doo*_*gle 5 stripe-payments

我们正在对客户的订阅使用Stripe付款处理。当用户更改计划时,我们希望立即按比例收取差额费用。当计划具有不同的计费间隔时,Stripe会自动执行此操作,但是在具有相同间隔的计划之间进行更改时,Stripe会将付款推迟到下一个计费周期。

我们现在处理此问题的方法是在更新订阅后创建发票,但是如果由于计费失败而导致失败,则需要进行回滚。

stripe.subscriptions.update(/* change plan */);
if (plans_have_different_billing_intervals) {
  try {
    stripe.invoices.create(/* for all pending charges */);
  } catch (err) {
    /* rollback subscription to old plan */
  }
}
Run Code Online (Sandbox Code Playgroud)

总体而言,这感觉是错误的并且令人费解。有没有更容易/更清洁的方法来实现我们所没有的?

Flu*_*lux 9

要在用户升级时立即按比例向用户收取差价,请proration_behavior='always_invoice'在修改用户订阅时使用该选项。引用文档:

...为了总是立即开具按比例分配的发票,请传递 always_invoice。

蟒蛇示例:

stripe.Subscription.modify(
    subscription_id,
    items=[{
        'id': item_id,
        'plan': plan_id,
    }],
    # Charge the prorated amount immediately.
    proration_behavior='always_invoice',
)
Run Code Online (Sandbox Code Playgroud)

当用户更改为更昂贵的计划时,这会立即向用户收取一定比例的费用。但是,当用户更改为更便宜的计划时,用户将获得按比例分配的信用额度,使用户的下一张账单按比例金额更便宜。

场景

在这些场景中,假设计费日期是每个月的第一天。进一步假设该月有 30 天。

  • 场景 1:用户订阅了 5 美元的月费计划。用户决定在该月的第 22 天升级到 30 美元的计划。当月还剩 8 天时,5 美元计划的未使用部分约为(8 / 30) * 5 = $1.33,而 30 美元计划的按比例分配的金额为(8 / 30) * 30 = $8.00。因此,用户将8.00 - 1.33 = $6.67立即被收费。

  • 场景 2:用户订阅了 30 美元的月费计划。用户决定在当月的第 22 天降级到 5 美元的计划。当月还剩 8 天时,30 美元计划的未使用部分约为(8 / 30) * 30 = $8.00,5 美元计划的按比例分配的金额为(8 / 30) * 5 = $1.33。在这种情况下,不会向用户收费,但用户的下一个帐单(在下一个帐单日期)将减少8.00 - 1.33 = $6.67

上面的示例计算只是近似值,因为 Stripe 按比例分配到精确的秒,而不是按天。

旁注

Dearsina 的回答是正确的,但涉及至少三个 API 调用而不是一个。要明确遵循该答案中的步骤,您可以改为执行以下操作:

# Step 1 in dearsina's answer: Modify the subscription.
modified_subscription = stripe.Subscription.modify(
    subscription_id,
    items=[{
        'id': item_id,
        'plan': plan_id,
    }],
)

# Steps 2 and 3: Create and retrieve invoice.
invoice = stripe.Invoice.create(customer=modified_subscription.customer)

# Steps 4 and 5: Finalize and pay invoice.
stripe.Invoice.pay(invoice.id)
Run Code Online (Sandbox Code Playgroud)

但是,当您可以在一个 API 调用中完成所有步骤时,为什么要这样做呢?

  • 这似乎是 2020 年最好的选择。它将升级计划,立即按比例计费,并且无需取消订阅或手动生成发票。 (2认同)

pqv*_*vst 6

您可以在更新订阅时使用billing_cycle_anchorset to now来强制更改订阅周期,从而始终立即向客户收费。我个人认为这更有意义。同样,这也可以按比例分配。

await stripe.subscriptions.update(subscription.id, {
  billing_cycle_anchor: 'now',
  items: [{ id: itemId, plan: planId }]
});
Run Code Online (Sandbox Code Playgroud)

https://stripe.com/docs/billing/subscriptions/billing-cycle#changing


dea*_*ina 5

要为更改数量或订阅计划付款,您需要执行以下操作:

  1. 使用新更改更新订阅
  2. 创建发票。令我感到困惑的是,Stripe神奇地知道只为更新的订阅项目开票,而不为即将到来的计费周期项目开票。

  3. 检索新创建的发票

  4. 完成发票
  5. 为发票付款这假设您的客户已存储付款方式。

仅在完成所有步骤后,您才成功为订阅更改付费(并且仅对更改付费)。您可以一次性完成所有操作。客户应在其末尾收到Stripe的发票电子邮件。

正如OP所说,如果付款失败,它将变得特别复杂。从我的角度来看,您有三种选择:

  1. 忽略付款失败,让客户访问该服务,并希望他们在下次尝试付款时付款。
  2. 回滚订阅升级,警告客户付款失败。
  3. 暂停整个订阅,直到客户付款为止。

我只提到#3,因为有时订阅升级过程可能很复杂。而且,客户花了一些时间升级其订阅,因此不想撤消工作,因为这可能是完全无害的(例如,他们的信用卡已过期)。

从开发的角度来看,将订阅标记为可能unpaid比回滚或冻结(然后冻结)订阅的某些部分要容易。但是,然后您会犯规,即禁止客户使用他们已经付费的服务(他们现有的订阅),因为他们无法支付额外的服务。


Edw*_*ard 0

您可以在 Stripe 中使用webhook。创建发票后,您可以立即收取发票费用(立即开票)。如果发票支付失败,您可以使用Webhook回滚到旧帐户。

查看本指南以了解有关 Stripe 订阅的更多信息:https://www.truespotmedia.com/testing-webhooks-in-stripe-with-php/