Using Stripe Elements in a VueJS Component
Part 4 of 7 in Using Laravel Cashier with VueJS SPA and Laravel Passport APIAt 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.