【发布时间】:2020-09-24 19:53:53
【问题描述】:
我正在使用 Laravel 6 和 Cashier 10.7 来处理我平台上的订阅。一次性支付给 Stripe 的工作正常,从一个订阅切换到另一个订阅也是如此,但是当我尝试为没有存储卡的客户启动新订阅时,我收到一个错误
无法确定请求哪个 URL:Stripe\PaymentMethod 实例的 ID 无效:
我的付款表格如下所示;
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-6 mt-5 mb-2">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> There was a problem.
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="h2 text-center">
{{ __('Please enter your card details') }}
</div>
<div class="card">
<div class="card-body">
<form method="post" action="{{ route('startSubscription') }}" id="payment-form">
@csrf
<div class="group">
<label class="stripe-label">
<span class="mr-1 p-2">{{ __('Cardholder Name') }}</span>
<input id="card-holder-name" class="field" placeholder="Jordan Jones" />
</label>
</div>
<!-- Stripe Elements Placeholder -->
<div class="group">
<label class="stripe-label">
<span class="mr-1 p-2">{{ __('Card') }}</span>
<div id="card-element" class="field p-3"></div>
</label>
</div>
<!-- Used to display form errors. -->
<div id="card-errors" role="alert"></div>
<button id="card-button" class="btn btn-lg btn-block btn-success" data-secret="{{ $intent->client_secret }}">
<i class="fas fa-credit-card mr-1"></i>{{ __('Add Payment Method') }}
</button>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('javascript')
<script>
const stripe = Stripe('{{ env("STRIPE_KEY") }}');
const elements = stripe.elements();
const cardElement = elements.create('card', {hidePostalCode: true});
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardElement,
billing_details: { name: cardHolderName.value }
}
}
);
if (error) {
var errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
// Submit the form with the token ID.
function stripePaymentHandler(setupIntent) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'payment_method');
hiddenInput.setAttribute('value', setupIntent.payment_method);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
}
});
</script>
@endsection
我的控制器是这样的;
public function subscriptionPayment(Request $request) {
$user = Auth::user();
$paymentMethod = $request->payment_method;
try {
if ($user->hasPaymentMethod()) {
$user->updateDefaultPaymentMethod($paymentMethod);
} else {
$user->addPaymentMethod($paymentMethod);
}
$newSubscription = $user->newSubscription('User', 'plan_HGvJkewD0eaY6G')->trialDays(60)->create($paymentMethod, ['email' => $user->email]);
} catch ( IncompletePayment $exception ){
return redirect()->route('payment',
[$exception->payment->id, 'redirect' => route('home')]
);
}
return redirect()->route('home')
->with('status', 'Your payment has been processed and your subscription is now active.');
}
Stripe 事件日志显示了这一点;
{ “对象”:{ "id": "seti_*******", “对象”:“设置意图”, “应用程序”:空,
"cancellation_reason": null, "client_secret": "seti_*********", “创建”:1591367952, “客户”:空, “描述”:空, “last_setup_error”:空, “现场模式”:假, “授权”:空, “元数据”:{ }, “下一个动作”:空, “on_behalf_of”:空, “付款方式”:空, “付款方式选项”:{ “卡片”: { “request_three_d_secure”:“自动” } }, “payment_method_types”:[ “卡片” ], “single_use_mandate”:空, “状态”:“requires_payment_method”, “用法”:“off_session”}}
任何人都可以帮助解决我做错的事情,我就是无法解决。
【问题讨论】:
-
听起来您将无效的
id字符串传递给 $user->updateDefaultPaymentMethod($paymentMethod)。它应该采用pm_****(或有时card_****)的形式。可能是您传递整个PaymentMethod对象而不仅仅是id。 -
只是 var_dumped $paymentMethod 为空。
-
看起来表单可能在使用 paymentMethod 的 Stripe 响应之前提交,但不应该等待命令这样做吗?
-
尝试硬编码 hiddenInput.setAttribute('value', '1234');进入 js 代码,但 PaymentMethod 上的 var_dump 仍然返回 null。看起来js表单追加不起作用,但我不明白为什么。向表单本身添加一个简单的隐藏字段就可以了。
标签: laravel stripe-payments subscription laravel-cashier