I built a checkout button with vue-stripe
Tags: javascript, vue, stripe, debug
Published: 2023-07-24 18:47:00

---
title: I built a checkout button with vue-stripe
published: true
description: 
tags: #javascript #vue #stripe #debug
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/exnrnxas9w1hmugn2w1i.png
series: Code debugging with dashcam
# Use a ratio of 100:42 for best results.
---

## TL;DR

In this blogpost, I explain how I built a very simple product page using [vue-stripe](https://vuestripe.com/). If you decide to follow along, you can too  start selling your product or your services today!

I am also going to share about how to resolve the most common problems while building this, using a tool called [Dashcam](https://dashcam.io).

### Why?
Selling online is fun! If you have a project you want to monetize, this is the fastest way to get started!

![lets do this](https://media.giphy.com/media/BpGWitbFZflfSUYuZ9/giphy.gif)



## Let's get started! 🔥

Let's assume you already have node.js and npm installed. If not, [you can learn how to do it here](https://www.digitalocean.com/community/tutorial-collections/how-to-install-node-js)

The first thing we want to do is set up the environment. We're going to be super vanilla and make a folder called:

```
stripe-vue
```
This will be the root directory, within which we're gonna initiate our Vue project!

Go ahead and type the following command in your terminal of choice:
```bash
mkdir stripe-vue && cd stripe-vue
```


Next, we want to initiate a Vue project, so let's create a Vue app

```bash
npm init vue@latest
```

What this does is, it initializes a new project with **Vue.js** as a dependency using npm. 

I use `vue@latest` - because `@latest` indicates that the latest version of Vue.js should be installed.

> 🤫
> (I use npm but if you're more advanced, or picky, you can choose your package manager of choice)

## Configure your vue project

When you run this command, `npm` will prompt you to provide information about the project (e.g., project name, options, etc).
`npm` will generate a package.json file and install the latest version of Vue.js as a project dependency.
Personally, I selected  **No** on each option, because I am just building a simple checkout button, but your mileage may vary


After this step, the CLI tells me to run some commands

```bash
cd vue-stripe-checkout
npm install
npm run dev
```

I am going to run the top 2 of them, **but not the last one**, because I don't wanna run the project just yet...!

The first two commands place me inside the actual project folder, where our code will go and install the dependencies.

When that's finished I need one more dependency: `vue-stripe`

```bash
npm install @vue-stripe/vue-stripe
```

**Wait! 👋 Before you continue!**
![wait](https://media.giphy.com/media/eeL8EcBBTwSMLACw6F/giphy.gif)
### Create products and prices on Stripe and enable Checkout

If you want to sell something you need to tell Stripe what you're selling.

In this demo we're selling Jars of spicy condiment/ $15 a jar. It's delicious, I promise

### Creating a product & set price


![stripe product](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p0tpt5bmruhynnb65mq.png)



Before we continue, we have to do something on Stripe's side. We have to create the product, and attach a price to it.  [There's a beautiful step by step tutorial on the Stripe Doc portal](https://support.stripe.com/questions/how-to-create-products-and-prices)

Once you have created your product with a price, you need to note down the **SKU id**, you can find this on the Product settings page you just created and it looks like this `sku_OHSgXJ1rXvtqrt`

Using the SKU id value will tell Stripe's Checkout to find the default price of the product.

### Creating a product price 

If you have multiple prices for the same product (perhaps you're offering different geo location/currencies) instead of noting down the **SKU id** (red arrow), find the **price id** (green arrow)

![screenshot of prices](https://slabstatic.com/prod/uploads/vww16xdi/posts/images/0_7SXCB5O-l-H9ba3cnBMmxZ.png)

### Ensuring checkout is enabled

We also need to make sure that the checkout functionality is enabled, that's just a switch and it can be done quickly, [the docs on Stripe's website clearly show the steps](https://stripe.com/docs/payments/checkout/client#enable-checkout)



After creating the product, having attached a price to it (_and additionally another price_), making sure checkout is enabled… now let's move on to creating the actual checkout page in Vue.



## Creating a vue component

Back to our Vue project, let's make a new file in the components folder, if you followed this article step by step that should be:

```bash
stripe-vue/vue-stripe-checkout/src/components/CheckoutButton.vue
```

## Now let's write some code.


![write some code in vscode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m32p0r2vso7d0zi5m9fc.png)



Open the Checkout component and let's build a button that will lead to a Stripe checkout, first by importing `StripeCheckout` from the `vue-stripe` library

Then we're going to export an object with the default export.

We make `StripeCheckout` as an exportable component. This way it can be rendered and used within our app!

```vue
<template>
  <!-- We're going to put our Stripe Checkout code here in a moment -->
</template>

<script>
import { StripeCheckout } from '@vue-stripe/vue-stripe';
export default {
  components: {
    StripeCheckout,
  },
};
</script>
```

Next we're going to write some code to customize our Stripe Checkout button.

We're gonna write some code in this component within the `<template></template>` section.

```vue
<template>
    <div>
      <stripe-checkout
        ref="checkoutRef"
        mode="payment"
        :pk="publishableKey"
        :line-items="lineItems"
        :success-url="successURL"
        :cancel-url="cancelURL"
        @loading="v => loading = v"
      />
      <button @click="submit">Pay now!</button>
    </div>
  </template>
```

The interesting things here are to be noted:

- **mode**: This is the type of Checkout we're asking Stripe to create, either `payment` or `subscription`. We're making a one-time payment form, so let's set it to `payment`.
- **line-items:** The items that should be purchased by the customer, they're shown on the  Checkout interface and make up the total amount to be collected by Checkout.
- **success-url:** The success URL to redirect the customer after purchase
- **cancel-url:** The cancellation URL that we should redirect customers when payment is canceled (i.e. you click the back arrow on the Stripe checkout UI)

Also, let's add a button with a label saying "Pay now!" so we can purchase the Spicy jar condiment we're going to sell when clicking the button.
Let's write some JavaScript to specify the config for our Stripe checkout that will appear once the button is clicked!

### vue-stripe component setup

Let's now hook up the component we have added with the ability to be purchased.

We're going to set it up like this between the `<script></script>` tags

Notice that we have to set up a couple of variables:

- **publishableKey:** your PK from Stripe's developer dashboard
- **lineItems:** an array of objects; each object has a _price_ for a product you're trying to sell and a _quantity_. You can have multiple objects in this array to create more "complex" checkouts, for example, if you sell multiple products at once
- **succesURL**: The value of the URL after the user purchases
- **cancelURL**: The value of the URL if the user cancels

```vue
<script>
  import { StripeCheckout } from '@vue-stripe/vue-stripe';
  export default {
    components: {
      StripeCheckout,
    },
    data () {
      return {
        publishableKey: "<YOUR-STRIPE-PUBLIC-KEY>",
        loading: false,
        lineItems: [
          {
            price: '<YOUR-SKU-ID>', // The SKU id of the product created in the Stripe dashboard
            //price: '<YOUR-PRICE-ID>', // the Price id of the product I want to sell, if you have multiple prices, pick one

            quantity: 1,
          }
        ],
        successURL: '<URL_SUCCESS>',
        cancelURL: '<URL_CANCEL>',
      };
    },
    methods: {
      submit () {
        this.$refs.checkoutRef.redirectToCheckout();
      },
    },
  };
  </script>
```

Now that we're done with the code, our final component should look like this:

```vue
<template>
    <div>
      <stripe-checkout
        ref="checkoutRef"
        mode="payment"
        :pk="publishableKey"
        :line-items="lineItems"
        :success-url="successURL"
        :cancel-url="cancelURL"
        @loading="v => loading = v"
      />
      <button @click="submit">Pay now!</button>
    </div>
  </template>
<script>
  import { StripeCheckout } from '@vue-stripe/vue-stripe';
  export default {
    components: {
      StripeCheckout,
    },
    data () {
      return {
        publishableKey: "<YOUR-STRIPE-PUBLIC-KEY>",
        loading: false,
        lineItems: [
          {
            price: '<YOUR-SKU-ID>', // The SKU id of the product created in the Stripe dashboard
            //price: '<YOUR-PRICE-ID>', // the Price id of the product I want to sell, if you have multiple prices, pick one

            quantity: 1,
          }
        ],
        successURL: '<URL_SUCCESS>',
        cancelURL: '<URL_CANCEL>',
      };
    },
    methods: {
      submit () {
        this.$refs.checkoutRef.redirectToCheckout();
      },
    },
  };
  </script>
```

## Display the Checkout component

We're going to load our component into the `App.vue` file so that it can be shown to our

So create an `App.vue` file (if one exists, delete the original one) and let's write some code

```vue
<script setup>
import CheckoutButton from './components/CheckoutButton.vue'
</script>

<template>
  <div>
    <h1>Purchase a Spicy Jar</h1>
    <p>A Spicy Jar of condiment, delicious and adds a touch of fire to blander dishes</p>
    <div id="image"></div>
    <Checkout></Checkout>
</div>
</template>

<style>
  #app {display: inline-block;}
  #image {
    width: 108px; 
    height: 108px; 
    border-radius: 4px;
    background-size: cover;
    background-image: url("https://stripe-camo.global.ssl.fastly.net/1da6f350ad1131277e51712ee1b3a992efb07a9333055c2926e8db1ceb633ab6/68747470733a2f2f66696c65732e7374726970652e636f6d2f6c696e6b732f4d44423859574e6a6446387851335673596e564762484e50633367355a58565366475a735833526c6333526663564a3463577075617a4a51654746784e57786857585a61656c4261633063793030657347736d436d4f");
  }
</style>

```

First let's import our `Checkout` element from the `CheckoutButton.vue` file we created a moment ago, on line 2.

Then within this file, let's add some context (line 7-9) so users know what they're buying and the `<Checkout></Checkout>` component  (line 10). When this component renders, a button will be rendered.

## Launching the Vue app
![preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/twozhg6z59bz7nit0cj5.png)

Save all your files and head to your terminal:

Make sure you're in the right directory `stripe-vue/vue-stripe-checkout` and run `npm run dev`

Navigate to the URL and see your checkout button in action!

## Debugging the Vue app
What do you do when the code doesn't work?
![debug](https://media.giphy.com/media/1BXa2alBjrCXC/giphy.gif)
To debug the Vue app we're going to use [Dashcam](https://dashcam.io) (disclaimer: I am working on Dashcam, a video-first code debugging tool for debs).

Dashcam allows you to debug your work, it's a screen recorder app for debugging that gives you the error logs alongside a video of what caused them, all locally on your computer.

Here's an example of me using Dashcam to debug the above code while I was writing this tutorial.

<a href="https://app.dashcam.io/replay/64bab70f87ca2f005fd66f3d?share=QlZolztfFGyJQxDE5lUgXA">![Debug code](https://replayable-api-production.herokuapp.com/replay/64bab70f87ca2f005fd66f3d/gif?shareKey=QlZolztfFGyJQxDE5lUgXA)</a>
{% cta https://app.dashcam.io/replay/64bab70f87ca2f005fd66f3d?share=QlZolztfFGyJQxDE5lUgXA %} Watch it now {% endcta %}

👀 Looking at the video I can see that I made a typo when pasting the API key (publishable one) that caused to Stripe checkout to not be able to be launched when I clicked the button.
🫠 Easy fix!

### Conclusion: Writing code and understanding errors
In this article we learned how to:
- 👀 Set up a simple Vue project from scratch
- 🙏 Create a checkout button (some would call it a product page or a one-item cart page) that leads to a checkout page hosted by Stripe using Vue.
- 🔥 Debug your web apps using video and error logs through Dashcam. 

Just looking at error logs sometimes is just not enough, especially when you're working with friends or team-mates asynchronously. 

Sharing a video is worth a million words. IMHO adding video evidence to error logs truly makes a difference: I truly believe debugging with Dashcam is pretty useful because it gives you the video context alongside the Dev Tools and Network errors.

We'll see how to debug the backend in the next article!

Thank you for reading this far and let me know if you have any comments or questions below this article!

---

{% cta https://www.dashcam.io/ %} Download Dashcam (Free - Open Beta) {% endcta %}

{% cta https://vuestripe.com/ %} Explore vue-stripe further {% endcta %}