Is there any way to implement Stripe Checkout into the shopping cart we built in your “React Shopping Cart for Absolute Beginners” video? Excellent video, by the way!T.
Bassir Changed status to publish November 26, 2023
hello there,
in backend:
npm i stripe
then create stripeRouter.js like this:
/* eslint-disable camelcase */ import Stripe from 'stripe'; import express from 'express'; import config from '../config.js'; import Order from '../models/orderModel.js'; const stripe = Stripe(config.STRIPE_SECRET_KEY); const stripeRouter = express.Router(); stripeRouter.get('/secret/:id', async (req, res) => { const order = await Order.findById(req.params.id).populate( 'user', '_id name email' ); const paymentIntent = await stripe.paymentIntents.create({ amount: order.totalPrice * 100, currency: 'usd', // Verify your integration in this guide by including this parameter metadata: { integration_check: 'accept_a_payment' }, }); res.send({ order, client_secret: paymentIntent.client_secret }); }); stripeRouter.get('/key', (req, res) => { res.send(config.STRIPE_PUBLISHABLE_KEY); }); export default stripeRouter;
and add to the routes in server.js
import stripeRouter from './routers/stripeRouters.js'; ... app.use('/api/stripe', stripeRouter);
and set env variable in .env:
STRIPE_SECRET_KEY=sk_xxx STRIPE_PUBLISHABLE_KEY=pk_xxx
get them from stripe.com
in frontend install
npm i @stripe/react-stripe-js @stripe/stripe-js
and create this component:
import React, { useState } from 'react'; import { useStripe, useElements, CardElement, Elements, } from '@stripe/react-stripe-js'; import { Button } from 'react-bootstrap'; import Axios from 'axios'; function CheckoutForm(props) { const [processing, setProcessing] = useState(false); const stripe = useStripe(); const elements = useElements(); const handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); if (!stripe || !elements) { // Stripe.js has not yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } setProcessing(true); const { data } = await Axios(`/api/stripe/secret/${props.orderId}`); const clientSecret = data.client_secret; // Call stripe.confirmCardPayment() with the client secret. const result = await stripe.confirmCardPayment(clientSecret, { payment_method: { card: elements.getElement(CardElement), billing_details: { name: data.order.user.name, email: data.order.user.email, }, }, }); if (result.error) { // Show error to your customer (e.g., insufficient funds) console.log(result.error.message); alert(result.error.message); } else { // The payment has been processed! if (result.paymentIntent.status === 'succeeded') { props.handleSuccessPayment(result.paymentIntent); console.log(result.paymentIntent); // alert(result.paymentIntent.status); } } setProcessing(false); }; return ( <form onSubmit={handleSubmit}> <CardElement /> <Button type="submit" className="btn-block" disabled={!stripe || processing} > Pay With Stripe </Button> </form> ); } const StripeCheckout = (props) => ( <Elements stripe={props.stripe}> <CheckoutForm orderId={props.orderId} handleSuccessPayment={props.handleSuccessPayment} /> </Elements> ); export default StripeCheckout;
then use it in OrderScreen.js
import { loadStripe } from '@stripe/stripe-js/pure'; import StripeCheckout from '../components/StripeCheckout';
in useEffect:
const [stripe, setStripe] = useState(null); useEffect(() => { const addStripeScript = async () => { const { data: clientId } = await axios.get('/api/stripe/key'); const stripeObj = await loadStripe(clientId); setStripe(stripeObj); }; if (order.paymentMethod === 'stripe') { if (!stripe) { addStripeScript(); }
in the return part:
{!order.isPaid && !stripe && <LoadingBox />} {!order.isPaid && stripe && ( <StripeCheckout stripe={stripe} orderId={order._id} handleSuccessPayment={handleSuccessPayment} /> )}
Bassir Answered question October 25, 2022