Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

bwoogie's avatar

Laravel app.js stops Stripe payment form from showing

I'm trying to accept payments with Stripe. I got the code from the Stripe documentation and added it to a view. When I click the button it doesn't show the form, but instead goes to the form action page (payments).

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <!-- CSRF Token -->
        <meta name="csrf-token" content="9HgWQfTsUXQ0RmIPQPLbhNoujOobjHn5PL9en8jx">
    
        <title>Staff</title>
    
        <!-- Styles -->
        <link href="https://localhost/staff/public/css/app.css" rel="stylesheet">
        <link href="https://localhost/staff/public/css/style.css" rel="stylesheet">
    </head>
    <body>
        <div id="app">
    
    
    
            <form action="payments/" method="POST">
      <script
        src="https://checkout.stripe.com/checkout.js" class="stripe-button"
        data-key="pk_test_xxx"
        data-amount="999"
        data-name="Demo Site"
        data-description="Widget"
        data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
        data-locale="auto">
      </script>
    </form>
        </div>
    
        <!-- Scripts -->
        <script src="https://localhost/staff/public/js/app.js"></script>
    </body>
    </html>

I Stripped everything way down to eliminate everything a left only the button, still didn't work. One last thing to remove.....

    <script src="https://localhost/staff/public/js/app.js"></script>

And that's what kept the form from showing....

So my question: Why would that be causing Stripe to not be able to show the form and what can I do to fix it? Did I just forget to set something up correctly? I'm new to Laravel, this is my first project with the framework, and my installation is pretty close to vanilla as I'm just getting started...

I ran composer require "laravel/cashier":"~7.0" and then added the service provider to config/app.php:

    'providers' => [
        ...
        Laravel\Cashier\CashierServiceProvider::class,
    ],

And then migrated the database.

Here are some of my files...

web.php:

    ...
    Route::post('/payments', 'PaymentsController@subscribe')->name('payments');
    Route::get('/payments', 'PaymentsController@index')->name('payments');

PaymentsController.php:

    <?php
    
    namespace Staff\Http\Controllers;
    
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\DB;
    
    class PaymentsController extends Controller
    {
    
        //private $states;
    
        /**
         * Create a new controller instance.
         *
         * @return void
         */
        public function __construct()
        {
            $this->middleware('auth');
        }
    
        public function index() {
            return view('payments/payment');
        }
    
        public function subscribe() {
            echo "huhh";
            
        }
    }

payment.blade.php:

    @extends('layouts.app')
    
    @section('content')
    <form action="" method="POST">
      <script
        src="https://checkout.stripe.com/checkout.js" class="stripe-button"
        data-key="pk_test_fCM9Fr1e33JYW6t17ZoSyXRf"
        data-amount="999"
        data-name="Demo Site"
        data-description="Widget"
        data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
        data-locale="auto">
      </script>
    </form>
    @endsection

services.php:

    <?php
    
    return [
    
        ...
    
        'stripe' => [
            'model' => Staff\User::class,
            'key' => env('pk_test_xxx'),
            'secret' => env('sk_test_zzz'),
        ],
    
    ];

Edit

Even if I try to create a custom form it doesn't work. However, if I create a html file outside of Laravel, it works...

<html>
   <head>
      <style>
         form {
         width: 480px;
         margin: 20px auto;
         }
         .group {
         background: white;
         box-shadow: 0 7px 14px 0 rgba(49,49,93,0.10),
         0 3px 6px 0 rgba(0,0,0,0.08);
         border-radius: 4px;
         margin-bottom: 20px;
         }
         label {
         position: relative;
         color: #8898AA;
         font-weight: 300;
         height: 40px;
         line-height: 40px;
         margin-left: 20px;
         display: block;
         }
         .group label:not(:last-child) {
         border-bottom: 1px solid #F0F5FA;
         }
         label > span {
         width: 20%;
         text-align: right;
         float: left;
         }
         .field {
         background: transparent;
         font-weight: 300;
         border: 0;
         color: #31325F;
         outline: none;
         padding-right: 10px;
         padding-left: 10px;
         cursor: text;
         width: 70%;
         height: 40px;
         float: right;
         }
         .field::-webkit-input-placeholder { color: #CFD7E0; }
         .field::-moz-placeholder { color: #CFD7E0; }
         .field:-ms-input-placeholder { color: #CFD7E0; }
         button {
         float: left;
         display: block;
         background: #666EE8;
         color: white;
         box-shadow: 0 7px 14px 0 rgba(49,49,93,0.10),
         0 3px 6px 0 rgba(0,0,0,0.08);
         border-radius: 4px;
         border: 0;
         margin-top: 20px;
         font-size: 15px;
         font-weight: 400;
         width: 100%;
         height: 40px;
         line-height: 38px;
         outline: none;
         }
         button:focus {
         background: #555ABF;
         }
         button:active {
         background: #43458B;
         }
         .outcome {
         float: left;
         width: 100%;
         padding-top: 8px;
         min-height: 24px;
         text-align: center;
         }
         .success, .error {
         display: none;
         font-size: 13px;
         }
         .success.visible, .error.visible {
         display: inline;
         }
         .error {
         color: #E4584C;
         }
         .success {
         color: #666EE8;
         }
         .success .token {
         font-weight: 500;
         font-size: 13px;
         }
      </style>
   </head>
   <body>
      <script src="https://js.stripe.com/v3/"></script>
      <form >
         <div class="group">
            <label>
            <span>Name</span>
            <input name="cardholder-name" class="field" placeholder="Jane Doe" />
            </label>
            <label>
            <span>Phone</span>
            <input class="field" placeholder="(123) 456-7890" type="tel" />
            </label>
         </div>
         <div class="group">
            <label>
               <span>Card</span>
               <div id="card-element" class="field"></div>
            </label>
         </div>
         <button type="submit">Pay $25</button>
         <div class="outcome">
            <div class="error" role="alert"></div>
            <div class="success">
               Success! Your Stripe token is <span class="token"></span>
            </div>
         </div>
      </form>
      <script>
         var stripe = Stripe('pk_test_xxx');
         var elements = stripe.elements();
         
         var card = elements.create('card', {
           style: {
             base: {
               iconColor: '#666EE8',
               color: '#31325F',
               lineHeight: '40px',
               fontWeight: 300,
               fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
               fontSize: '15px',
         
               '::placeholder': {
                 color: '#CFD7E0',
               },
             },
           }
         });
         card.mount('#card-element');
         
         function setOutcome(result) {
           var successElement = document.querySelector('.success');
           var errorElement = document.querySelector('.error');
           successElement.classList.remove('visible');
           errorElement.classList.remove('visible');
         
           if (result.token) {
             // Use the token to create a charge or a customer
             // https://stripe.com/docs/charges
             successElement.querySelector('.token').textContent = result.token.id;
             successElement.classList.add('visible');
           } else if (result.error) {
             errorElement.textContent = result.error.message;
             errorElement.classList.add('visible');
           }
         }
         
         card.on('change', function(event) {
           setOutcome(event);
         });
         
         document.querySelector('form').addEventListener('submit', function(e) {
           e.preventDefault();
           var form = document.querySelector('form');
           var extraDetails = {
             name: form.querySelector('input[name=cardholder-name]').value,
           };
           stripe.createToken(card, extraDetails).then(setOutcome);
         });
      </script>
   </body>
</html>
0 likes
1 reply
bwoogie's avatar
bwoogie
OP
Best Answer
Level 1

Found the issue. It's the logout form. If I remove that, the stripe form works.

<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">{{ csrf_field() }}</form>

So, that means the two forms are conflicting. I added a name to the Stripe form, stripe-form and updated the javascript

document.querySelector("form[name='stripe-form']").addEventListener('submit', function(e) {
   e.preventDefault();
   var form = document.querySelector("form[name='stripe-form']");
   var extraDetails = {
     name: form.querySelector('input[name=cardholder-name]').value,
   };
   stripe.createToken(card, extraDetails).then(setOutcome);
 });

Please or to participate in this conversation.