3

我将 Laravel 5.3 与 Cashier 一起使用。如果客户更新了他们的卡详细信息,我如何检查是否有待处理的发票并要求 Stripe 重新尝试在新卡上收费?目前,我已经在 Stripe 仪表板中设置了尝试设置。但据我了解,如果客户更新了他们的卡详细信息,Stripe 不会自动尝试向他们收费,它会等待下一个尝试日期再试一次。这就是为什么我想在客户更新卡后立即手动尝试向他们收取待处理发票的费用。我阅读了 Cashier 文档和 Github 页面,但这里没有涉及到这个案例。

$user->updateCard($token);
// Next charge customer if there is a pending invoice

有人可以帮帮我吗?

4

1 回答 1

1

经过测试并与 Stripe 支持人员交谈后,我发现updateCard()Laravel Cashier 中使用的当前方法存在问题。

使用当前updateCard()方法,将卡片添加到源列表中,然后将新卡片设置为default_source. 这种方法的结果有两个结果:

  1. 尽管最近的一张被设置为,但多张卡被添加到列表中default_source

  2. 使用此方法更新卡时,如果有未付发票(即past_due状态发票),则不会自动扣款。

为了让stripe重新尝试对所有处于past_due状态的发票向客户收费,source需要传递参数。所以我创建了一个类似这样的新方法:

public function replaceCard($token)
    {
        $customer = $this->asStripeCustomer();
        $token = StripeToken::retrieve($token, ['api_key' => $this->getStripeKey()]);
        // If the given token already has the card as their default source, we can just
        // bail out of the method now. We don't need to keep adding the same card to
        // a model's account every time we go through this particular method call.
        if ($token->card->id === $customer->default_source) {
            return;
        }
        //  Just pass `source: tok_xxx` in order for the previous default source 
        // to be deleted and any unpaid invoices to be retried
        $customer->source = $token;
        $customer->save();
        // Next we will get the default source for this model so we can update the last
        // four digits and the card brand on the record in the database. This allows
        // us to display the information on the front-end when updating the cards.
        $source = $customer->default_source
                    ? $customer->sources->retrieve($customer->default_source)
                    : null;
        $this->fillCardDetails($source);
        $this->save();
    }

我为此添加创建了一个拉取请求。由于直接编辑Billable文件以进行任何更改不是一个好主意,如果这没有添加到 Cashier,那么您可以使用 Controller 文件中的以下内容直接从那里执行此操作:

$user = Auth::User();

$customer = $user->asStripeCustomer();
$token = StripeToken::retrieve($token, ['api_key' => config('services.stripe.secret')]);

if (!($token->card->id === $customer->default_source)) {
  $customer->source = $token;
  $customer->save();
  // Next synchronise user's card details and update the database
  $user->updateCardFromStripe();
}
于 2017-01-10T06:34:45.617 回答