Amazon-clone using React, Stripe and Firebase (Part 3)
In part 1 of creating an Amazon clone, I went over how to set up the app, create the header, home page and how to add a product to the basket.
In part 2, I showed how to build the subtotal, remove items to the basket and create the login page.
In this final part, I’m going to describe how to build the checkout page, use Stripe functionality to handle the payments and use the cloud function to process the payments.
The checkout page
In Subtotal.js, we need to tell React to use the history once the button is clicked to remember who is the user. Once the user clicks on the ‘Proceed to checkout’ button, he will be redirected to the payment page. I added a functionality where the button shows ‘Sign in or create an account to proceed to checkout’ when the user is not signed in, which will redirect them on the login page.
The payment component will have 3 main div, the user informations, the review items section, and the payment method. Next we need to pull in Stripe into our app by running:
npm i @stripe/stripe.js
npm i @stripe/react-stripe.js
Visit Stripe and on the home page once you created your profile, you will find your API key (see screenshot)
In App.js, we need to import loadStripe from @stripe/stripe-js and Elements from @stripe/react-stripe-js and create a const promise that will be equal to loadStripe containing the key that we got from Stripe. In the payment route, we need to pass this Element that will wrap our payment component, with a prop stripe containing that promise.
In Payment.js, we need to pull in useStripe, useElements and CardElement from @stripe/react-stripe-js. We need to create a form which will call a handleSubmit function itself containing the CardElement which will call an onChange function. This handleChange function will have 2 options. If the event is empty, it will disable the button otherwise if there is an error, show the error or show nothing.
Inside this CardElement, there is a div containing the CurrencyFormat that we used before.
Next, there is button showing either ‘Buy Now’ or ‘processing’ which will update depending of the state.
Lastly, the handleSubmit function will first prevent the page from refreshing, then set the processing to ‘true’, which will stop the user to click the Buy button multiple times, and then we will have a payload constant. For this step, we need to create a constant called ‘clientSecret, setClientSecret’ using the useState hook, and then with the useEffect function, so that whenever the basket changes, it will run an async function that will handle the response. We need to create an axios.js component which will contain our base URL.
The payload constant will confirm the card Payment with clientSecret informations, define the payment method, and then once we get the promise, we destructure the response which will have the paymentIntent (payment confirmation). If everything is correct, we setSucceeded to true, setError to null and setProcessing to false and finally replace the history so that the user is redirected to the orders page.
Now in order for this to work, we need to build out the backend to support this. In the terminal, we need to run:
This will create a functions folder which will be our backend. Now we need to make sure we are in the right folder before we install any dependencies. In the functions folder, we need to run
npm i express
npm i cors
npm i stripe
and declare it in functions > index.js and set up the API like shown below:
The stripe secret key on line 4 is from Stripe.com underneath the publishable key. Next in functions, we need to run the command:
This will spin up an express server:
If everything works well, you should now be able to submit a payment in your app using the fake card (4242 4242 4242 4242 04/24 24242) and will be submitted to your Stripe account where you can check how much sales you have made