我们正在为客户的订阅使用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 */
}
}
总的来说,这感觉错误和错综复杂。是否有一种更容易/更清洁的方式来实现我们没有看到的?
答案 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天。
用户已订阅每月5美元的套餐。用户决定在该月的22日升级到30美元的套餐。 $ 5计划的未使用部分大约为(8 / 30) * 5 = $1.33
,$ 30计划的未分配部分为(8 / 30) * 30 = $8.00
。因此将立即向用户收取8.00 - 1.33 = $6.67
的费用。
用户订阅了每月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)
要为更改数量或订阅计划付款,您需要执行以下操作:
Create an invoice。 令我感到困惑的是,Stripe神奇地知道只为更新的订阅项目开票,而不为即将到来的计费周期项目开票。
仅当完成所有步骤后,您才成功为订阅更改付费(并且仅针对更改付费)。您可以一次性完成所有操作。客户应该从Stripe的末尾收到发票电子邮件。
正如OP所说,如果付款失败,它将变得特别复杂。从我的角度来看,您有三种选择:
我只提到#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