Using Stripe Elements in a VueJS Component

Part 4 of 7 in Using Laravel Cashier with VueJS SPA and Laravel Passport API
Dan Pastori avatar
Dan Pastori December 17th, 2019

At this point, we have Laravel Cashier installed, Stripe configured and API keys in our Laravel instance, and we’ve added a product with 3 plans (Basic, Professional, Enterprise) in our Stripe platform. Now it’s time to jump back to Laravel & VueJS and start connecting the two platforms. The first place to start is with Stripe Elements.

For those who aren’t familiar with Stripe Elements (https://stripe.com/payments/elements), I’d recommend checking out the documentation. Essentially they are a programatic way to set up a Stripe form and accept a payment. They are also beautifully designed, capable of handling all of the validation necessary, and able to be adapted to fit the flow of your application.

1. Create Your Subscription Management Component

For this course, we will be making a single component to manage your subscriptions within your single page application.

Before we get too far, I’d like to say this will end up being a fairly large component. Feel free to divide it up into smaller sub-components if you want. Also, feel free to style this at will. I won’t be going through many UI/UX features besides installing Stripe Elements.

The first thing we will do is make a SubscriptionManagement.vue component wherever you are storing your components. In our Single Page Application, we have a directory called components.

The initial component should be a basic structure of the VueJS component like this:


<div>
    <h3>Manage Your Subscription</h3>
</div>

export default {
    data(){
        return {
            
        }
    }
}

2. Add the Stripe Public Key

Remember the public Stripe Key? We will need to add this in our component. This is the PUBLIC key the one that starts with pk_test in a testing scenario or pk_live in a live scenario. However you want to include this in your build process is up to you. An environment variable of some sort would be preferable, but configuring that for an SPA is an entirely different tutorial.

For now, take the public key and add it as a piece of data to the local component data like so:


<template>
    <div>
        <h3>Manage Your Subscription</h3>
    </div>
</template>

export default {
    data(){
        return {
            stripeAPIToken: 'pk_test_YOUR_RANDOM_KEY'
        }
    }
}

Now we have the key readily available for when we make front end Javascript requests.

3. Include Stripe Elements Javascript

In a normal application, you’d include this in your header. In a Single Page Application, you could do this in your index file, or you could load it dynamically from the component. There are multiple times where your component will not need to be rendered so loading a third party JS script every single time may not be the best approach.

You will also need to ensure it’s loaded before you configure your form. Outside of your SPA, this could be difficult since it’s a trick to fire a callback inside of a component within an SPA. I prefer to load it dynamically within the component only when we need it. To do this, we need to add 2 methods to our component. The first is includeStripe . This method will create a script tag and load our Stripe javascript file and add it to the head of our application. The second is configureStripe which will set up our Stripe elements.

Add the following method:


methods: {
    /*
        Includes Stripe.js dynamically
    */
    includeStripe( URL, callback ){
        let documentTag = document, tag = 'script',
            object = documentTag.createElement(tag),
            scriptTag = documentTag.getElementsByTagName(tag)[0];
        object.src = '//' + URL;
        if (callback) { object.addEventListener('load', function (e) { callback(null, e); }, false); }
        scriptTag.parentNode.insertBefore(object, scriptTag);
    },
    }

This method accepts 2 parameters, the URL of the file we are loading dynamically which will be the Stripe JS file and a callback function that will run when the file is loaded.

Now, when we have the file properly loaded, we will callback and Stripe will be configured.

In the mounted lifecycle hook on your component, call this method with the URL of the StripeJS file. This is important not to house this file on your server for security reasons. ALWAYS load it from their CDN:


mounted(){
    this.includeStripe('js.stripe.com/v3/', function(){
        this.configureStripe();
    }.bind(this) );
},

2 things to note, we are binding this so we have access to the local component’s methods inside the callback and 2, we are calling configureStripe once everything has been loaded. We have not implemented that yet, but that’s next! That’s our callback method that will set up Stripe locally within the component.

4. Configure Stripe Elements

Before we get started, there are A LOT of different options you can do to style your Stripe Elements, add new fields, etc. For more information on what you can do with Stripe elements, visit: https://stripe.com/docs/stripe-js. For this course, we are going to be using the very basic design and style. Styling is outside the scope of this course.

So let’s first implement the configureStripe() method we brushed on in step 3. This is where we will be adding our configuration of Stripe elements.

First, let’s add a few variables to our local component’s data():


data(){
    return {
        stripeAPIToken: 'pk_test_',

        stripe: '',
        elements: '',
        card: ''
    }
},

We’ve added 3 variables stripe, elements and card. The stripe variable will house a local instance of the Stripe object that is in the Stripe JS API that we loaded. The elements will house an instance of the Stripe Elements and card will be the object representation of the Card for Stripe Elements. Let’s set this up!

Let’s add the following method to our methods object:


/*
    Configures Stripe by setting up the elements and 
    creating the card element.
*/
configureStripe(){
    this.stripe = Stripe( this.stripeAPIToken );

    this.elements = this.stripe.elements();
    this.card = this.elements.create('card');

    this.card.mount('#card-element');
},

This line this.stripe = Stripe( this.stripeAPIToken ); initializes the local Stripe variable to an instance of the Stripe object with our public API token available to make calls.

Next we have this.elements = this.stripe.elements(); and this.card = this.elements.create('card'); . The first line initializes our local elements variable with a Stripe elements instance. The second line creates a special card element and assigns it to our local card variable. You can optionally pass custom styles as the second parameter to the create method to style the card explained here: https://stripe.com/docs/stripe-js#elements.

The third line this.card.mount('#card-element'); mounts an element in our component with the id of card-element. We haven’t created that yet, but guess what? That’s what’s next! Right now, we’ve included our Stripe API and have elements configured. We assigned all of these to local variables within the component and not with in the method because we will be using the card variable in a variety of other places in later tutorials. We will need that to be cleared, listen to actions, and create intents. All of which we will go through in this course.

5. Add Card Element

This is pretty simple, but it’s the first time we are adding to the template. We simply just need to add the following in the Vue component’s template:


<label>Card</label>
<div id="card-element">

</div>

One thing I want to point out. This is the only form element WITHOUT a v-model attached to it. That’s very important. We do NOT want the credit card number within our component and accidentally hitting our server. With Stripe Elements, this is all housed with in the Stripe Elements card object and gets submitted to their server. In our case, we will take the setup intent (discussed later) and save the submitted payment method token in the database so we can charge it later.

Right now, we have Stripe Elements set up and configured in our VueJS component! At this state, our component should be this:


<template>
    <div>
        <h3>Manage Your Subscription</h3>

        <label>Card</label>
        <div id="card-element">

        </div>
    </div>
</template>

    export default {
        data(){
            return {
                stripeAPIToken: 'pk_test_',
    
                stripe: '',
                elements: '',
                card: ''
            }
        },
    
        mounted(){
            this.includeStripe('js.stripe.com/v3/', function(){
                this.configureStripe();
            }.bind(this) );
        },
    
        methods: {
            /*
                Includes Stripe.js dynamically
            */
            includeStripe( URL, callback ){
                let documentTag = document, tag = 'script',
                    object = documentTag.createElement(tag),
                    scriptTag = documentTag.getElementsByTagName(tag)[0];
                object.src = '//' + URL;
                if (callback) { object.addEventListener('load', function (e) { callback(null, e); }, false); }
                scriptTag.parentNode.insertBefore(object, scriptTag);
            },
    
            /*
                Configures Stripe by setting up the elements and 
                creating the card element.
            */
            configureStripe(){
                this.stripe = Stripe( this.stripeAPIToken );
    
                this.elements = this.stripe.elements();
                this.card = this.elements.create('card');
    
                this.card.mount('#card-element');
            },
        }
    }
    

At the end of the course I will provide all source code. Let me know if you have any questions so far in the comment section below! In the next tutorial, we will be talking about Payment Intents which are the user’s intent to pay for something with a payment method.

Keep Reading
View the course View the Course Using Laravel Cashier with VueJS SPA and Laravel Passport API
Up Next → Creating Stripe Setup Intents With Laravel API and VueJS SPA

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.