Laravel Cashier 新订阅 Stripe 抛出“无法确定请求哪个 URL:”错误
Posted
技术标签:
【中文标题】Laravel Cashier 新订阅 Stripe 抛出“无法确定请求哪个 URL:”错误【英文标题】:Laravel Cashier new subscription with Stripe throws "Could not determine which URL to request:" error 【发布时间】: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表单追加不起作用,但我不明白为什么。向表单本身添加一个简单的隐藏字段就可以了。
【参考方案1】:
我将此追踪到标题中的 js 脚本标记中存在“延迟”,这意味着事件侦听器无法正常工作,并且表单正在提交而无需等待来自 Stripe 的调用和响应。 用一个简单的
修复<script src=" asset('js/app.js') "></script>
2天后?♂️
【讨论】:
以上是关于Laravel Cashier 新订阅 Stripe 抛出“无法确定请求哪个 URL:”错误的主要内容,如果未能解决你的问题,请参考以下文章
Laravel Cashier SCA 订阅返回不完整的订阅
无需订阅即可使用 Laravel Cashier 一次性付款