Hi,
I watched your YouTube video on Next, Tailwind, and MongoDB Amazona project and was able to successfully deploy it on Vercel.I was wondering about implementing the strip payment option. I noticed that whichever payment choice I choose it goes directly to PayPal only. Can you please tell me how I can approach this task.
Thank you for your videos. They are really helpful.
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} /> )}
In the meantime please follow this guide: https://vercel.com/guides/getting-started-with-nextjs-typescript-stripe