首页 > 解决方案 > Laravel Cashier 新订阅 Stripe 抛出“无法确定请求哪个 URL:”错误

问题描述

我正在使用 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_*******”,“对象”:“setup_intent”,“应用程序”:null,

“cancellation_reason”:null,“client_secret”:“seti_*********”,“created”:1591367952,“customer”:null,“description”:null,“last_setup_error”:null,“livemode” :假,“授权”:空,“元数据”:{},“next_action”:空,“on_behalf_of”:空,“payment_method”:空,“payment_method_options”:{“卡”:{“request_three_d_secure”:“自动" } }, "payment_method_types": [ "card" ], "single_use_mandate": null, "status": "requires_payment_method", "usage": "off_session" } }

任何人都可以帮助解决我做错的事情,我只是无法解决。

标签: laravelstripe-paymentssubscriptionlaravel-cashier

解决方案


我将此追踪到标题中的 js 脚本标记中存在“延迟”,这意味着事件侦听器无法正常工作,并且表单正在提交而无需等待来自 Stripe 的调用和响应。用一个简单的固定

<script src="{{ asset('js/app.js') }}"></script>

2天后‍♂️</p>


推荐阅读