This is the fourth post in a four-part series. In Part one, we set up a serverless Stripe function on Azure. Part two covered how we hosted the function on Github. The third part covered Stripe Elements in Vue. This last post shows how to configure the checkout component and make the shopping cart fully functional.
Article Series:
Setup and Testing
Stripe Function and Hosting
Application and Checkout Component
Configure the Checkout Component (This Post)
As a reminder, here’s where we are in our application at this point:
Configuring the Checkout Component
We have to do a few things to adjust the component in order for it to meet our needs:
Make sure the form is only displaying if we haven’t submitted it—we’ll deal with the logic for this in our pay method in a moment
Allow the form to take a customer’s email address in case something is wrong with the order.
Disable the submit button until the required email address is provided
Finally and most importantly, change to our testing key
Here’s our updated checkout component with the changes to the original code highlighted:
Please enter your payment details:
Test using this credit card: 4242 4242 4242 4242, and enter any 5 digits for the zip code
There are a number of things we need to store and use for this component, so let’s add them to data or bring them in as props. The props that we need from our parent component will be total and success. We’ll need the total amount of the purchase so we can send it to Stripe, and the success will be something we need to coordinate between this component and the parent, because both components need to know if the payment was successful. I write out the datatypes as well as a default for my props.
props: {
total: {
type: [Number, String],
default: 50.00
},
success: {
type: Boolean,
default: false
}
},
Next, the data we need to store will be the stripeEmail we collected from the form, stripeOptions that I left in to show you can configure some options for your form, as well as status and response that we’ll get from communicating with the server and Stripe. We also want to hold whether or not the form was submitted, and whether the form was completed for enabling and disabling the submit button, which can both be booleans.
data() {
return {
submitted: false,
complete: false,
status: ,
response: ,
stripeOptions: {
// you can configure that cc element. I liked the default, but you can
// see https://stripe.com/docs/stripe.js#element-options for details
},
stripeEmail:
};
},
Now for the magic! We have everything we need—we just need to alter our pay() method, which will do all the heavy lifting for us. I’m going to use Axios for this, which will receive and transform the data:
npm i axios –save
…or using Yarn:
yarn add axios
If you’re not familiar with Axios and what it does, check out this article for some background information.
pay() {
createToken().then(data => {
this.submitted = true; // well change the flag to let ourselves know it was submitted
console.log(data.token); // this is a token we would use for the stripeToken below
axios
.post(
https://sdras-stripe.azurewebsites.net/api/charge?code=zWwbn6LLqMxuyvwbWpTFXdRxFd7a27KCRCEseL7zEqbM9ijAgj1c1w==,
{
stripeEmail: this.stripeEmail, // send the email
stripeToken: data.token.id, // testing token
stripeAmt: this.total // send the amount
},
{
headers: {
Content-Type: application/json
}
}
)
.then(response => {
this.status = success;
this.$emit(successSubmit);
this.$store.commit(clearCartCount);
// console logs for you 🙂
this.response = JSON.stringify(response, null, 2);
console.log(this.response);
})
.catch(error => {
this.status = failure;
// console logs for you 🙂
this.response = Error: + JSON.stringify(error, null, 2);
console.log(this.response);
});
});
},
The code above does a number of things:
It allows us to track whether we’ve submitted the form or not, with this.submitted
It uses Axios to post to our function. We got this URL from going to where the function lives in the portal, and clicking “Get Function URL” on the right side of the screen.
It sends the email, token, and total to the serverless function
If it’s successful, it changes the status to success, commits to our Vuex store, uses a mutation to clear our cart, and emits to the parent cart component that the payment was successful. It also logs the response to the console, though this is for educational purposes and should be deleted in production.
If it errors, it changes the status to failure, and logs the error response for help with debugging
If the payment fails, which we’ll know from our status, we need to let the user know something went wrong, clear our cart, and allow them to try again. In our template:
Oh No!
Something went wrong!
The button executes the following clearCheckout method that clears a number of the fields and allow the customer to try again:
clearCheckout() {
this.submitted = false;
this.status = ;
this.complete = false;
this.response = ;
}
If the payment succeeds, we will show a loading component, that will play an SVG animation until we hear back from the server. Sometimes this can take a couple of seconds, so it’s important that our animation make sense if it is seen for a short or long amount of time, and can loop as necessary.
Please hold, were filling up your cart with goodies
Here’s what that looks like:
See the Pen shop loader by Sarah Drasner (@sdras) on CodePen.
Now if we revisit the first cart component we looked at in pages/cart.vue, we can fill that page based on the logic we set up before because it’s been completed:
Cart
…
Cart
Your cart is empty.
Success!
Your order has been processed, it will be delivered shortly.
If we have items in our cart, we show the cart. If the cart is empty and the success is false, we’ll let them know that their cart is empty. Otherwise, if the checkout has just been processed, we’ll let them know that everything has been executed successfully!
We are now here:
In the AppSuccess.vue component, we have a small SVG animation designed to make them feel good about the purchase:
See the Pen success by Sarah Drasner (@sdras) on CodePen.
(You may have to hit “Rerun” to replay the animation.)
We also put a small timer in the mounted() lifecycle hook:
window.setTimeout(() => this.$emit(restartCart), 3000);
This will show the success for three seconds while they read it then kick off the restartCart that was shown in the component above. This allows us to reset the cart in case they would like to continue shopping.
Conclusion
You learned how to make a serverless function, host it on Github, add required dependencies, communicate with Stripe, set up a Shopping Cart in a Vue application, establish a connection with the serverless function and Stripe, and handle the logic for all of the cart states. Whew, way to go!
It’s worth mentioning that the demo app we looked at is a sample application built for specifically for this purpose of this tutorial. There are a number of steps you’d want to go through for a production site, including testing, building the app’s dist folder, using real Stripe keys, only sending the item from the client and adding the price in the serverless function, etc. There are also so many ways to set this up, Serverless functions can be so flexible in tandem with something like Vue. Hopefully this gets you on track and saves you time as you try it out yourself.