我正在尝试使用Stripe和Laravel Cashier(V10)设置付款方式,但出现以下错误:

We could not retrieve data from the specified Element. Please make sure the Element you are attempting to use is still mounted.


我只能假定出于某种原因将元素从DOM中删除,但是我不知道为什么。

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name') }}</title>
    <link rel="shortcut icon" href="/assets/img/favicon.png">


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

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
    <main>

        <div class="h-screen flex flex-col">
            <div class="bg-white text-text text-xs border-b border-trim h-16 font-light flex items-center
            px-5 justify-between">
                <div class="w-1/3 flex text-primary">
                    <button class="focus:outline-none">
                        <a href="/home">
                            <i class="fas fa-home fa-2x"></i>
                        </a>
                    </button>
                </div>
                <div class="w-1/3 flex justify-center py-2">
                    <img style="height: 40px" src="{{ asset('assets/img/Logo.svg') }}" alt="">
                </div>
                <div class="w-1/3 flex text-primary justify-end">
                    <shar-nav-dropdown></shar-nav-dropdown>
                </div>
            </div>
            <div class="flex flex-col flex-grow w-full bg-background p-2 md:p-12 md:px-48 items-center">
                <div class="flex flex-col items-center mt-6 md:mt-0 justify-start md:justify-center w-full px-6 md:px-0 md:w-1/2 h-full">
                    <div class="text-xl md:text-4xl font-thin text-primary mb-6">
                        Enter your payment details to activate your <span class="capitalize font-bold">{{$plan}}</span> plan.
                    </div>

                    <form onsubmit="submitForm(this)" id="payment-form" class="w-full">
                    @csrf

                    <!-- Stripe Elements Placeholder -->
                        <div id="card-element" class="border border-trim w-full rounded border-backgroundAccent bg-white focus:border-primary mb-3 outline-none
                                       px-4 py-2 text-black placeholder-text text-sm">
                        </div>

                        <!-- Used to display form errors. -->
                        <div id="card-errors" role="alert" class="-mt-2 text-sm text-error mb-3"></div>
                        <input type="hidden" name="plan" value="{{ $plan }}"/>

                        <!-- Pay button. -->
                        <button id="card-button" type="submit" class="w-full py-2 bg-primary rounded text-white hover:bg-primaryAlt focus:outline-none text-sm"
                                data-secret="{{
                            $intent->client_secret }}">
                            Securely Pay
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </main>
</div>
</body>
<script src="https://js.stripe.com/v3/"></script>

<script>
    const stripe = Stripe('{{ env("STRIPE_KEY") }}'); // Create a Stripe client.
    const elements = stripe.elements(); // Create an instance of Elements.
    const cardElement = elements.create('card'); // Create an instance of the card Element.
    const cardButton = document.getElementById('card-button');
    const clientSecret = cardButton.dataset.secret;
    cardElement.mount('#card-element'); // Add an instance of the card Element into the `card-element` <div>.

    // Handle real-time validation errors from the card Element.
    cardElement.addEventListener('change', function (event) {
        var displayError = document.getElementById('card-errors');
        if (event.error) {
            displayError.textContent = event.error.message;
        } else {
            displayError.textContent = '';
        }
    });

    // Handle form submission
    const form = document.getElementById('payment-form');

    function submitForm() {
        stripe.confirmCardSetup(
            clientSecret,
            {
                payment_method: {
                    card: cardElement,
                    // billing_details: {name: cardholderName.value}
                }
            }
        ).then(function (result) {
            console.log(result);
            if (result.error) {
                // Inform the user if there was an error.
                var errorElement = document.getElementById('card-errors');
                errorElement.textContent = result.error.message;
            } else {
                console.log(result);
                // Send the token to your server.
                stripeTokenHandler(result.setupIntent.payment_method);
            }
        });
    }

    // Submit the form with the token ID.
    function stripeTokenHandler(paymentMethod) {
        console.log('Handling...');
        // 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', 'paymentMethod');
        hiddenInput.setAttribute('value', paymentMethod);
        form.appendChild(hiddenInput);

        // Submit the form
        form.submit();
    }
</script>
</html>


cardElement中似乎找不到submitForm()。如果打开Chrome Dev Tools并键入cardElement,我可以看到该对象,但是如果在函数顶部添加console.log(cardElement),则似乎会打印一个空对象。可能与我正在使用<form onsubmit="submitForm()">的事实有关吗?也许在分配之前正在评估中?

任何帮助将不胜感激!

最佳答案

这是由于Vue组件将自身附加到根div。删除解决了它。

10-04 16:25