【问题标题】:Laravel Cashier new subscription with Stripe throws "Could not determine which URL to request:" errorLaravel Cashier 新订阅 Stripe 抛出“无法确定请求哪个 URL:”错误
【发布时间】: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


【解决方案1】:

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

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

2天后?‍♂️

【讨论】:

    猜你喜欢
    • 2019-06-23
    • 2021-08-04
    • 2015-10-15
    • 2016-08-04
    • 2020-05-07
    • 2021-03-31
    • 1970-01-01
    • 2020-07-25
    • 2016-03-04
    相关资源
    最近更新 更多