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

shinigaimi's avatar

Cashier 11 unable to store Payment Methods

I have been searching high and low and was unable to find anything that could help so I came here to see if I could get some sage wisdom passed down so I can learn a little more.

I am setting up "laravel/cashier": "^11.0", and when I am trying to do a dd($paymentMethods); it shows blank specifically

Illuminate\Support\Collection {#384 ▼
  #items: []
}

below will show my code

Subscription Controller: This will correctly display the intent on the form as the data secret

    public function ViewSubscriptions()
    {
        return view('Subscriptions.new_sub', [
            'intent' => $user->createSetupIntent()
        ]);
}

new_sub.blade.php: Shows the form

@extends('layouts.master')

@section('head')
    <script src="https://js.stripe.com/v3/"></script>

    <style>
        .StripeElement {
            box-sizing: border-box;
            height: 40px;
            padding: 10px 12px;
            border: 1px solid transparent;
            border-radius: 4px;
            background-color: white;
            box-shadow: 0 1px 3px 0 #e6ebf1;
            -webkit-transition: box-shadow 150ms ease;
            transition: box-shadow 150ms ease;
        }

        .StripeElement--focus {
            box-shadow: 0 1px 3px 0 #cfd7df;
        }

        .StripeElement--invalid {
            border-color: #fa755a;
        }

        .StripeElement--webkit-autofill {
            background-color: #fefde5 !important;
        }
    </style>
@endsection

@section('content')
    <div class="container">

        <form action="{{ route('subscription.create') }}" method="post" id="payment-form">
            @csrf

            <input id="card-holder-name" type="text">

            <!-- Stripe Elements Placeholder -->
            <div id="card-element"></div>

            <button id="card-button" data-secret="{{ $intent->client_secret }}">
                Update Payment Method
            </button>

        </form>
    </div>

@endsection

@section('js')

    <script>
        const stripe = Stripe('{{ env('STRIPE_KEY')}} ');

        const elements = stripe.elements();
        const cardElement = elements.create('card');

        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) {
                // Display "error.message" to the user...
            } else {
                // The card has been verified successfully...
            }
        });
    </script>
@endsection

Create Function inside Subscription controller: This is where I am receiving the empty payment method, also the test customer is already in the stripe system.

public function create(Request $request)
    {
        $user           = User::findorFail($request->user()->id); 
        $paymentMethods = $user->paymentMethods();
        $stripeCustomer = $user->createOrGetStripeCustomer();

        dd($paymentMethods);
}

would appreciate any guidance as to where this is failing me! :( or might be missing!

0 likes
1 reply

Please or to participate in this conversation.