经过测试并与 Stripe 支持人员交谈后,我发现updateCard()
Laravel Cashier 中使用的当前方法存在问题。
使用当前updateCard()
方法,将卡片添加到源列表中,然后将新卡片设置为default_source
. 这种方法的结果有两个结果:
尽管最近的一张被设置为,但多张卡被添加到列表中default_source
使用此方法更新卡时,如果有未付发票(即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();
}