【问题标题】:Stripe API refund after subscription cancelled订阅取消后 Stripe API 退款
【发布时间】:2014-09-07 13:42:45
【问题描述】:

来自 Stripe 文档:

当您取消订阅时,客户的卡将不会 再次收费,但也不会退还任何款项。如果你想 发出退款,您可以通过 Stripe 的仪表板或通过 API。

我创建了每月订阅,我只想退还订阅当月内尚未过去的天数的金额。如何使用 Stripe API 仅退还未完成天数的订阅金额?

【问题讨论】:

  • 2016 年年中,令人惊讶的是,Stripe 还没有实现整个订阅生命周期(特别是生命周期结束)

标签: payment-gateway payment stripe-payments


【解决方案1】:

您需要计算退款金额,然后向 Stripe 发送refund API call。退款后,您必须再次调用 Subscription cancellation 的 API

【讨论】:

  • 是否可以拨打取消电话,然后拨打退款电话?还是按照您的建议严格遵循 api 调用?
【解决方案2】:

如果您想让 Stripe 处理退款计算,您可以将订阅数量更改为 0,然后在之后取消计划。

【讨论】:

  • 要详细说明这个技巧,您需要将数量设置为零,然后检索即将到来的发票以获得退款金额(upcomingInvoice.total * -1)。要退款,请获取最新的已付款发票(不是即将到来的发票)并使用费用 ID 进行退款。
【解决方案3】:

研究了一阵子,我来到了这个用 JavaScript 为 Node.js 编写的流程:

refundAndUnsubscribe = async function () {
    try {

        // Set proration date to this moment:
        const proration_date = Math.floor(Date.now() / 1000);

        let sub = await stripe.subscriptions.retrieve("sub_CILnalN9HpvADj");

        // See what the next invoice would look like with a plan switch
        // and proration set:
        let items = [{
            quantity: 0,
            id: sub.items.data[0].id,
            plan: "your_plan" // Switch to new plan
        }];


        let invoices = await stripe.invoices.retrieveUpcoming('cus_CIP9dtlq143gq7', 'sub_CILnalN9HpvADj', {
            subscription_items: items,
            subscription_proration_date: proration_date
        });

        //List all invoices
        let payedInvoicesList = await stripe.invoices.list({
            customer: 'cus_CIP9dtlq143gq7'
        });

        // Calculate the proration cost:
        let current_prorations = [];
        let cost = 0;
        for (var i = 0; i < invoices.lines.data.length; i++) {
            let invoice_item = invoices.lines.data[i];
            if (invoice_item.period.start == proration_date) {
                current_prorations.push(invoice_item);
                cost += invoice_item.amount;
            }
        }

        //create a refund
        if (cost !== 0) {
            cost = (cost < 0) ? cost * -1 : cost //A positive integer in cents

            let refund = await stripe.refunds.create({
                charge: payedInvoicesList.data[0].charge,
                amount: cost
            });
        }

        // delete subscription
        return stripe.subscriptions.del('sub_CILnalN9HpvADj');

    } catch (e) {
        console.log(e);
    }
}

【讨论】:

  • 为什么会出现这种情况 if (invoice_item.period.start == proration_date) {
  • @ramamoorthy_villi 是为了确认找到了他创建的临时发票来计算分摊金额。
【解决方案4】:

Stripe 现在会处理这个问题。它可以立即取消订阅并创建一张发票,将当月未使用部分的费用退还给他们。

https://stripe.com/docs/api/subscriptions/cancel

添加“按比例”标签以退还剩余的每月费用。

在 PHP 中:

$subscription = \Stripe\Subscription::retrieve(
  'SUBSCRIPTION_ID'
);

$subscription->delete([
    'prorate' => true
]);

编辑:

@Dobes Vandermeer 在下面评论并指出了我的错误。上述方法实际上不会退还客户按比例分配的金额,而只会创建一个帐户信用,该信用将应用于下一张发票。

下面的代码实际上会将按比例分配的金额退还到卡中。它会生成一个按比例分配的示例发票,就好像客户将其订阅数量切换为零一样。然后,它会从其有效订阅的最后一张发票中退还按比例分配的金额。

subscription_proration_date”标签是可选的,但在您需要从某个时间点按比例分配订阅时很有用。

// get active subscription
$subscription = \Stripe\Subscription::retrieve(' SUBSCRIPTION_ID ');

// sample prorated invoice for a subscription with quantity of 0
$sample_subscription_item = array(
    "id"       => $subscription->items->data[0]->id,
    "plan"     => $subscription->items->data[0]->plan->id,
    "quantity" => 0,
);

$upcoming_prorated_invoice = \Stripe\Invoice::upcoming([
    "customer"                    => $subscription->customer,
    "subscription"                => $subscription->id,
    "subscription_items"          => array($sample_subscription_item),
    "subscription_proration_date" => ' PRORATED_DATE ', // optional
]);

// find prorated amount
$prorated_amount = 0;
foreach($upcoming_prorated_invoice->lines->data as $invoice) {
    if ($invoice->type == "invoiceitem") {

        $prorated_amount = ($invoice->amount < 0) ? abs($invoice->amount) : 0;

        break;

    }
}

// find charge id on the active subscription's last invoice
$latest_invoice = \Stripe\Invoice::retrieve($subscription->latest_invoice);
$latest_charge_id = $latest_invoice->charge;

// refund amount from last invoice charge
if ($prorated_amount > 0) {

    $refund = \Stripe\Refund::create([
        'charge' => $latest_charge_id,
        'amount' => $prorated_amount,
    ]);
  
}

// delete subscription
$subscription->delete();

【讨论】:

  • 看起来,当您这样做时,Stripe 只会创建退款并发出“信用”。它实际上并没有发出退款。
  • 谢谢@Dobes Vandermeer。好点子。我使用适用于我的用例的流程更新了答案。
  • 我收到此错误 Stripe\Exception\InvalidRequestException 您无法预览即将取消的订阅的发票。
  • @ShankarSBavan 听起来订阅已经取消了。在我的帖子中,我假设订阅仍然有效。在完成所有计算并将费用退还给客户后,它会取消订阅。
  • @PhilipStevens 是的,我想退款,他们在月中取消了订阅。您能否验证这是正确的答案。 stackoverflow.com/questions/62403075/…
猜你喜欢
  • 2021-01-11
  • 2015-01-28
  • 2018-11-21
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-29
相关资源
最近更新 更多