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.
which extension shows the import library size?
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
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]
.
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.
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!
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.
Hi, Having the same problem as Hugo, 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.
Even though I am in Test mode in stripe. Any help please?
Hi again, it seems I was using the Stripe API key for live and not for test mode, I have put the test mode API key in .env.local and also in Vercel environment variable, I also made sure that the product price IDs where the ones from test mode and not from live mode, cause it seems they are different. Now all seems to work.
I'm getting this error when clicking on Buy Button
IntegrationError: Invalid value for stripe.redirectToCheckout: lineItems.0.price should be a string. You specified: 1
I would start by double-checking your code. Here is the start of the next lesson for the index.js file and here is the start for the payments.js file.
can you please share your vscode editor settings (font-family)?