Integrate Stripe Checkout to Purchase Products in Next.js with Stripe @stripe/stripe-js Cl

Colby Fayock
InstructorColby Fayock

Share this video with your friends

Send Tweet
Published 11 months ago
Updated 10 months ago

Now that we have an app and our products configure in Stripe, it's time to connect the two and give people a way to purchase our products.

Using Stripe's API, we can initiate a new instance of the Stripe Checkout flow with a simple click of a button.

We'll create an initiateCheckout function that handles this flow for us. After loading stripe through @stripe/stripe-js we'll await a stripePromise that will allow us to redirect to stripes checkout flow. You'll notice that we will need to pass in line items with the price id and quantity.

Lecturer: [0:00] We're going to start off with our Space Jelly Shop Next.js App running on our local development server. Here, we have our three products, but we don't currently have a way to purchase them. Inside our code, we're mapping through the products variable to create each one of those product cards.

[0:12] We also have a .env.local file where we're storing our Stripe API key to make it available for us in the app. In order to make our products available to purchase, the first thing we need is a button. We're going to add a new paragraph tag. Inside that, we're going to add a new button, and we're going to say Buy Now.

[0:27] If we look in our browser, we can see our new button, but it's not anything that's special. To add some styles, we can open up our home.module.css file, where if we scroll to the bottom, we can create a new class called Button. I'm going to paste in a few styles including making the color of the text white. I'm going to make the font size a little smaller. I'm going to set the background color to blue-violet.

[0:46] In order to use our new button class, we're going to add the prop className. We're going to set that = styles.button. Now if we look in our browser, we can see our big, beautiful buttons. Currently, when we click these buttons, they don't do anything. What we want to happen is when we click one of those buttons, we want to initiate the checkout process with Stripe.

[1:03] The first thing I'm going to do, I'm going to add a new prop called onClick where I'm going create a new function that when somebody clicks that, I'm going to console log out Buy. If we open up our browser and open up our developer tools, we can test that out by clicking the Buy Now button and see that it logs out Buy.

[1:18] Instead of a console log, when we click that button, we want to initiate the checkout process. In order to keep my logic organized, I'm going to create that function in a new file. Inside of my app, I'm going to create a new folder. I'm going to call that lib. Inside of that folder, I'm going to create a new file called payments.js.

[1:33] Here, I'm going to export a new async function called initiateCheckout. Inside that function, I'm going to console log out Checkout. Back inside of my home page, I'm going to import that initiateCheckout function from one level up in lib/payments.js. Now when someone clicks that button, instead of that console log, I'm going to fire the function initiateCheckout.

[1:57] If we reload the page and click the button, we can see that it fires checkout. When this function is fired, we don't want to just console log out. We want to initiate a new session with Stripe. To do this, we first need to install the Stripe JavaScript library to our app.

[2:08] Inside the terminal, I'm going to run yarn add and the package name, which is @stripe/stripe-js. Once that's done installing, I can spin back up my development server. Back inside of my payments file, I'm going to import loadStripe from our package name.

[2:24] Then I'm going to create a new constant called stripePromise. I'm going to set that equal to loadStripe, where inside that function, we're going to pass in process.env and then our environment variable for our API key.

[2:35] If we open up our app, we shouldn't notice anything different, but if we open up our developer tools, we'll first see this warning about HTTPS. If we go over to the Network tab and filter for Stripe and reload the page, we can see that it's now making the requests out to Stripe.

[2:49] Inside of our initiateCheckout function, we're going to create a new constant called Stripe. We're going to set it to await stripe.promise. What this is going to do is it's going to take our stripe.promise up here and make sure it finishes before continuing on in the function.

[3:03] Then, we're going to add a new line for await stripe.redirectToCheckout, where inside, we're going to create a new object, and we're going to set the mode to payment. We'll also add a successUrl, where I'm going to paste in this value and what we're doing is we're grabbing the origin from our window.

[3:20] We're passing along a sessionId with a variable that Stripe will update, so that when somebody returns back to our application, they'll land on our home page with that new sessionId. We'll also add a cancelUrl. We're here. We're just going to pass in the home page.

[3:34] We're not yet finished setting it up, but to test that it's working so far, we can go to our application and click Buy Now, and we can see an error where it's setting up the redirectToCheckout function, but we still need to pass in our lineItems. To do this, we're going to need to dynamically pass in those lineItems depending on which product gets clicked.

[3:51] I'm going to create a new destructured argument called lineItems, where I'm also going to set that by default to an empty object in case someone doesn't pass it in. I'm going to pass that lineItems directly into that redirectToCheckout function.

[4:02] Back inside of our home page, when someone clicks that Buy Now button, we want to pass in a new object, where we add the lineItems property with an empty array, where we can add a new object, where we're first going to pass in our priceId, which for our case is the id.

[4:15] We're also going to add the quantity, where for our case, since we're only giving the option to buy one, we're going to just pass in the number 1.

[4:22] If we go back to our application and click one of the Buy Now buttons, we get redirected to Stripe. One thing to note, because we're still in test mode, that's why we were able to redirect from localhost. Once we're live, we're only able to redirect from those domains that we made valid inside of our Checkout settings.

[4:38] To test this out, I'll push these changes out to git which automatically trigger the Vercel Deploy, and now, I can see my new buttons. If I click Buy Now, I get redirected to Stripe just like before.

[4:48] In review, we have our Space Jelly Shop, but we wanted people to be able to buy our products. First, we added our Buy Now buttons so that somebody had something to click in order to initiate that process.

[4:57] When someone clicks that button, we're going to fire a new function called initiateCheckout where we're going to pass in the lineItems for those products. As soon as that initiateCheckout function fires, we're going to load Stripe and then redirect our customers to Checkout. When someone clicks Buy Now, inside of our app, they're redirected to Stripe, where they can now check out.

Navneet Kumar Sharma
Navneet Kumar Sharma
~ 6 months ago

can you please share your vscode editor settings (font-family)?

Navneet Kumar Sharma
Navneet Kumar Sharma
~ 6 months ago

which extension shows the import library size?

Colby Fayock
Colby Fayockinstructor
~ 6 months ago

can you please share your vscode editor settings (font-family)?

Font family is VS Code default Menlo, Monaco, 'Courier New', monospace Theme is Night Owl https://marketplace.visualstudio.com/items?itemName=sdras.night-owl

which extension shows the import library size?

Extension is https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost

~ 5 months ago

Could you explain the following error message I return when I click the 'Buy Now!' button? :

Client-only Checkout does not support prices with usage_type=metered in items[0].

Colby Fayock
Colby Fayockinstructor
~ 5 months ago

Could you explain the following error message I return when I click the 'Buy Now!' button? :

Client-only Checkout does not support prices with usage_type=metered in items[0].

That looks like a Stripe error, I'm not sure about that. It seems that you may be trying to use "metered" billing that's not supported with the client-only checkout.

Aryan Raj Sinha
Aryan Raj Sinha
~ 3 months ago

Hi! I did all the things you are doing, and added lineItems too. There's still an error that's coming both after deployment and on localhost.

It says this - "v3:1 Uncaught (in promise) IntegrationError: stripe.redirectToCheckout: successUrl must start with either http:// or https://."

I went over to network and searched stripe, then reloaded it too. I'm not sure what's happening.

Kindly help!

HUgo
HUgo
~ 2 months ago

Hello, I'm around 4:20 and when I click on the button the error i have is this

v3:1 Uncaught (in promise) IntegrationError: The domain (http://localhost:3000/) that redirected to Checkout is not enabled in the dashboard. Add this domain at https://dashboard.stripe.com/account/checkout/settings. at rn (v3:1) at e._handleMessage (v3:1) at e._handleMessage (v3:1) at v3:1

I did try to enable it in the dashboard, but the problem is that I can't enable localhost3000, it doesn't let me do so.