立即收取订阅更改费用

时间:2017-06-07 15:33:58

标签: 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 */
  }
}

总的来说,这感觉错误和错综复杂。是否有一种更容易/更清洁的方式来实现我们没有看到的?

4 个答案:

答案 0 :(得分:6)

要在用户升级时立即按比例向用户收取差价,请在修改用户的订阅时使用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',
)

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

场景

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

  1. 用户已订阅每月5美元的套餐。用户决定在该月的22日升级到30美元的套餐。 $ 5计划的未使用部分大约为(8 / 30) * 5 = $1.33,$ 30计划的未分配部分为(8 / 30) * 30 = $8.00。因此将立即向用户收取8.00 - 1.33 = $6.67的费用。

  2. 用户订阅了每月30美元的套餐。用户决定在该月的22日降级到$ 5的套餐。 $ 30计划的未使用部分约为(8 / 30) * 30 = $8.00,$ 5计划的按比例分配的金额为(8 / 30) * 5 = $1.33。在这种情况下,将不会向用户收费,但会在开单日期将用户的下一个账单减少8.00 - 1.33 = $6.67

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

旁注

dearsina's answer是正确的,但涉及至少三个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)

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

  1. Update subscription进行了新的更改。
  2. Create an invoice。 令我感到困惑的是,Stripe神奇地知道只为更新的订阅项目开票,而不为即将到来的计费周期项目开票。

  3. Retrieve the newly created invoice

  4. Finalise the invoice
  5. Take payment for the invoice这假定您的客户已存储一种付款方式。

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

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

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

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

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

答案 3 :(得分:0)

在更新订阅时,您可以将[''' Public Function Wave( _ planet As Double, _ Pattern As Integer, _ Amp As Double) _ As Double If Pattern = 2 Then 'calculating square wave If planet <= 180 Then Wave = (planet * Amp) / 180 ElseIf planet > 180 Then Wave = ((360 - planet) * Amp) / 180 End If End If If Pattern = 3 Then 'calculating trine wave If planet <= 120 Then Wave = (planet * Amp) / 120 ElseIf planet > 120 And planet <= 240 Then Wave = ((240 - planet) * Amp) / 120 ElseIf planet > 240 Then Wave = ((planet - 240) * Amp) / 120 End If End If End Function '''][1] ''' If Pattern = 33 Then 'calculating trine wave using 720 insted of 360 zodiac If planet <= 120 Then Wave = (planet * Amp) / 120 ElseIf planet > 120 And planet <= 240 Then Wave = ((240 - planet) * Amp) / 120 ElseIf planet > 240 And planet <= 360 Then Wave = ((planet - 240) * Amp) / 120 ElseIf planet > 360 And planet <= 480 Then Wave = ((480 - planet) * Amp) / 120 ElseIf planet > 480 And planet <= 600 Then Wave = ((planet - 480) * Amp) / 120 ElseIf planet > 600 Then Wave = ((720 - planet) * Amp) / 120 End If End If ''' 设置为billing_cycle_anchor,以强制其更改结算周期,从而始终向客户收取费用。我个人认为这更有意义。同样,按比例分配也可以很好地工作。

now

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