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

adamjhn's avatar

Stripe integration- console shows not defined error

Do you know why is appearing the error below using the default stripe code in the documentation?

jquery.min.js:2 Uncaught ReferenceError: pk_test_.... is not defined
    at HTMLDocument.<anonymous> (registration:607)

Laravel RegistrationController charge():

 public function charge(Request $request)
    {
        Stripe::setApiKey(config('services.stripe.secret'));
        $source = $request->stripeToken;

            Charge::create([
                'currency' => 'eur',
                'description' => 'Example charge',
                'amount' => 2500,
                'source' => $source,
            ]);
    }

Html:


<script src="https://js.stripe.com/v3/"></script>

<form action="{{ route('registration.charge') }}" method="post" id="payment-form">
    {{csrf_field()}}

    <div class="form-row">
        <label for="card-element">
            Credit or debit card
        </label>
        <div id="card-element">
            <!-- A Stripe Element will be inserted here. -->
        </div>

        <!-- Used to display form errors. -->
        <div id="card-errors" role="alert"></div>
    </div>

    <button>Submit Payment</button>
</form>

Stripe js:

var stripe = Stripe({{config('services.stripe.key')}});

// Create an instance of Elements.
var elements = stripe.elements();

// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
    base: {
        color: '#32325d',
        lineHeight: '18px',
        fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
        fontSmoothing: 'antialiased',
        fontSize: '16px',
        '::placeholder': {
            color: '#aab7c4'
        }
    },
    invalid: {
        color: '#fa755a',
        iconColor: '#fa755a'
    }
};

// Create an instance of the card Element.
var card = elements.create('card', {style: style});

// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');

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

// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
    event.preventDefault();

    stripe.createToken(card).then(function(result) {
        if (result.error) {
            // Inform the user if there was an error.
            var errorElement = document.getElementById('card-errors');
            errorElement.textContent = result.error.message;
        } else {
            // Send the token to your server.
            stripeTokenHandler(result.token);
        }
    });
});

0 likes
12 replies
ejdelmonico's avatar

Looks like the stripe secret is not being found because pk_test is part of the test api key.

1 like
adamjhn's avatar

Thanks, but to test is not better to use the test key? I have the keys in the .env file. And then in services.php


 'stripe' => [
        'model' => App\User::class,
        'key' => env('STRIPE_KEY'),
        'secret' => env('STRIPE_SECRET'),
    ],
adamjhn's avatar

If I pass the key directly like:

 var stripe = Stripe({{config('pk_....')}});

It shows:


jquery.min.js:2 Uncaught Error: Invalid value for Stripe(): apiKey should be a string. You specified: undefined.
Cronix's avatar

apiKey should be a string

put quotes around it so it's a string.

Right now you're just dumping the content of the config file into the Stripe() object, but without quotes around it JS doesn't know it's a string.

1 like
adamjhn's avatar

Thanks but shows the same error using "" like:

var stripe = Stripe({{config("pk_test_...")}});

Cronix's avatar
Cronix
Best Answer
Level 67

notice where I put the single quotes....surrounding {{ }} so the output of config gets put INTO a string.

var stripe = Stripe('{{ config("pk_test") }}');

It's no different than putting things in quotes like on forms...

<input type="text" value="{{ $someObject->id }}">
1 like
adamjhn's avatar

Thanks! Now it appears "Uncaught SyntaxError: Unexpected token &". Do you know why? In the error apepars this:

var stripe = Stripe(config(&quot;services.stripe.key&quot;));

Cronix's avatar

is this a .js file, or in a blade view? If it's a .js file, you can't use blade helpers (which is php) in them.

You'll have to output the php as js and attach it to the window object or something. Here's a good package for doing that: https://github.com/laracasts/PHP-Vars-To-Js-Transformer

And it's really best to not have js in blade views. You lose all of the benefit of caching the js files so the browser has to download it every single time the page loads, which slows things down.

1 like
adamjhn's avatar

The code is in a blade view. But above the form there is the

 <script src="https://js.stripe.com/v3/"></script>
adamjhn's avatar

Thanks, can you explain better that part of dont have js in blade views? Your are saying that instead of have the necessary js for a specific blade view like for example, on the bottom of the view have something like:

@section('scripts')

        $(function () {
            // js code for this specific view
                
        });
@endsection

Instead, have just imports of js files that are necessary for that specific view like:

@section('scripts')

    <script type="text/javascript" src="{{url('js/getConferencesAjax.js')}}"></script>
     <script type="text/javascript" src="{{url('js/searchConferencesAjax.js')}}"></script>
@endsection

?

Cronix's avatar

Yes, all of my js scripts are in separate js files like that.

<script type="text/javascript" src="{{url('js/getConferencesAjax.js')}}"></script>
<script type="text/javascript" src="{{url('js/searchConferencesAjax.js')}}"></script>

That way the browser can cache them and not have to download them every time you load a page. That and using the version() function of laravel mix to add a query string to the files so if I change a file, that "technically" changes the filename and forces the browser to download the newest version if something has changed.

However I usually only have 1 or 2 js files for the whole site with everything contained in them. The first visit to the site caches them so every other page the user visits they already have all of the js needed and is a lot faster.

1 like

Please or to participate in this conversation.