我有一个网络服务,可以为我的用户发布和托管某些信息。每个用户的编辑界面与他们发布的信息是分开的。我使用 Stripe 订阅进行计费,但我无法找到处理未付费订阅的可行方法。这是我想要实现的逻辑:
- 第一次计费尝试失败后,我的应用应锁定用户的编辑界面;相反,它应该向他们提供一个页面,其中包含解决付款问题的选项。不过,他们已发布的信息仍会发布,因此延迟付款不会影响访问者的事件。
- 在 15 天后最后一次计费尝试失败后,我的应用也应该删除他们发布的信息。此时,用户的编辑界面将被替换为允许他们使用新信用卡重新激活帐户或完全删除帐户的界面。
- 如果用户选择重新激活帐户,他们不应获得试用期
- 如果用户重新激活,他们还必须为之前跳过的 15 天付费,方法是将首个计费周期缩短 15 天,或者将相当于 15 天服务的费用添加到他们的第一张账单。
如果我留意正确的 webhook,#1 和 #2 很容易实现 - 只需将拖欠客户或已删除或未付费订阅的客户的请求重定向到“解决此问题”页面。 #3 也非常简单 - 只需创建订阅并将 Trial_end
设置为 now
即可。
#4 很棘手。如何确定用户的最后一张发票在取消订阅之前未支付的时间有多久?如何缩短新订阅的第一个计费周期?或者,我如何按比例计算客户的最后一张发票总额以代表我实际提供给他们的部分,以便我可以将该金额添加到新发票中? (我知道我可以在开始新订阅之前创建一个发票项目来收取金额,所以至少这是可能的。)
最后,Stripe 的“标记订阅未付费”选项对解决这个问题有帮助吗?看起来它一直在创建发票,但并不尝试对其收费;我认为这不是我想要的。
最佳答案
您绝对可以通过 Stripe 的订阅来完成所有这些操作。正如您提到的,前两个问题应该通过 webhooks 来解决。您将在您的一端监听 invoice. payment_failed
以检测付款何时失败,并立即阻止您的 UI 要求您的客户更新其银行卡详细信息。
要更新他们的卡详细信息,您可以使用 Stripe Checkout并且只是不设置 data-amount
参数,这样它就不会向您的客户显示价格。这是一个示例:
<form action="/charge" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_XXXX"
data-image="/square-image.png"
data-name="Demo Site"
data-description="Update Card Details"
data-panel-label="Update Card Details"
data-label="Update Card Details">
</script>
</form>
每次您的客户尝试更新他的卡时,您都可以使用 Update Customer API并在 card
参数中传递新的卡 token 。这将删除客户的默认卡并将其替换为新卡。它还会尝试支付处于“逾期”状态的每个订阅的最新发票。在您的情况下,这意味着将尝试支付仍处于重试模式的最新发票。这不算重试,可以看作是独立的。如果成功,您只需重新启用 UI,否则您将继续要求客户更新其银行卡详细信息。
当您第四次付款失败时,您将收到 customer.subscription.canceled
(如果您在 dashboard 的重试设置中设置了此消息)。 。您可以通过检查事件上的 request
键并确保其为 null
来检测是否为自动取消。在这种情况下,您可以完全阻止客户的 UI/帐户。
在过去 15 天里,如果我正确理解了您的流程,那么自从您部分锁定 UI 以来,客户实际上无法使用您的应用程序。但如果您仍然希望他支付该金额,您应该在数据库中存储客户在 15 天无法使用订阅期间欠您 X 美元的信息。
后来,您的客户终于回来并想要重新启用他的帐户。此时,您通知他付款流程将从今天开始重新启动,并且您将向他收取他之前错过的额外 15 天的费用。为此,我将使用 Invoice Items这将允许您自动向第一张发票添加额外金额。您将按照以下步骤操作:
- Create为您的客户提供 X 美元的发票项目。
- Create如果您的套餐默认设置了试用期,请将您的套餐的新订阅设置为
Trial_end
为“立即”
。 - 这将自动创建计划金额的第一张发票,并添加之前创建的发票项目。
这里的另一个解决方案是重新打开最新未付款的已关闭发票并使用 Pay Invoice API 。当发生这种情况时,您知道您的客户现在向您支付了整整一个月的费用,而不是只欠您 15 天的费用。在这种情况下,您将创建一个新的订阅并设置 15 天的试用期,以便他在试用后再次开始付款。
我不会在这里使用“标记为未付款”选项,因为您将客户完全锁定在您的应用程序之外。对我来说,当您让客户使用您的应用程序并计划在几个月内向他收取每张发票的费用时,可以使用此功能。例如,这将用于电力提供商,他们会在多个计费周期内保持您的电力供应,并继续尝试向您收取每张发票的费用。
在这种情况下,您的客户实际欠您的金额取决于您允许的重试次数以及每次重试之间的天数。您可以在此处执行的操作是使用发票上的 created
值,并将其与获取 customer.subscription.canceled
时的当前时间进行比较,以确定过去了多少时间以及计算此时您的客户欠您的金额的按比例分配。
关于stripe-payments - 恢复 Stripe 订阅(并对之前未付费的服务收费),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28392073/