Search code examples
reactjsstripe-paymentse-commerce

Need Guidance with processing a stripe payment due to Unhandled Rejection (TypeError): Failed to fetch error


I have been working on processing a connection to a payment gateway and have run into a fetch issue.

I have been following this guide https://www.knowledgehut.com/blog/web-development/stripe-node-js

But I have run into a fetch error and I am unsure of how to proceed.

below is my check out modal component where the items in the cart are shown, a user can see the items added to the cart and remove them and this is where the payment is supposed to be processed.

import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Modal from '@mui/material/Modal';
import products from './product'
import { useContext } from 'react';
import { Elements } from "@stripe/react-stripe-js";
import { useState, useEffect} from 'react';
import { loadStripe } from "@stripe/stripe-js"; 

import cart from '../context/cart'
import { CartContext } from '../context/cart';
const style = {
  position: 'absolute',
  top: '50%',
  left: '50%',
  transform: 'translate(-50%, -50%)',
  width: "100%",
  bgcolor: 'background.paper',
  border: '2px solid #000',
  boxShadow: 24,
  p: 4,
};
export default function BasicModal() {
  const [open, setOpen] = React.useState(false);
  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);
  const stripePromise = loadStripe("pk_test_35p114pH8oNuHX72SmrvsFqh00Azv3ZaIA");


  const { cartItems, addToCart, removeFromCart, clearCart, getCartTotal } = useContext(CartContext)
  useEffect(() => {
    // storing input name
    localStorage.getItem("cartItems", JSON.stringify(cartItems));
  }, [cartItems])



// payment is processed here


  const makePayment = async () => { 
    const stripe = await loadStripe("pk_test_35p"); 
    const body = { cartItems }; 
    const headers = { 
      "Content-Type": "application/json", 
    }; 
  
    const response = await fetch( 
      "localhost:8000/api/create-checkout-session", 
      { 
        method: "POST", 
        headers: headers, 
        body: JSON.stringify(body), 
      } 
    ); 
  
    const session = await response.json(); 
  
    const result = stripe.redirectToCheckout({ 
      sessionId: session.id, 
    }); 
    if (result.error) { 
      console.log(result.error); 
    } 
  }; 
  return (
    <div>
      <Button onClick={handleOpen}   >

        ({cartItems.length})
        Check Out</Button>
      <Modal
      disableScrollLock={true}
      fullScreen={true}
        open={open}
        onClose={handleClose}
        aria-labelledby="modal-modal-title"
        aria-describedby="modal-modal-description"
      >
        <Box sx={style}>
          <>
            <div className="flex-col flex items-center bg-white gap-8 p-10 text-black text-sm">
              <h1 className="text-2xl font-bold">Cart</h1>
              <div className="flex flex-col gap-4">
  
  
                {cartItems.map((item) => (
                  <div className="flex justify-between items-center" key={item.id}>
                    <div className="flex gap-4">
                      <img src={item.imageId} alt={item.title} className="rounded-md h-24" />
                      <div className="flex flex-col">
                        <h1 className="text-lg font-bold">{item.title}</h1>
                        <p className="text-gray-600">{item.price}</p>
                        <p className="text-gray-600">{item.description}</p>

                      </div>
                    </div>
                    <div className="flex gap-4">
                      <button
                        className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                        onClick={() => {
                          addToCart(item)
                        }}
                      >
                        +
                      </button>
                      <p>{item.quantity}</p>
                      <button
                        className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                        onClick={() => {
                          removeFromCart(item)
                        }}
                      >
                        -
                      </button>

                    </div>
                  </div>
                ))}
              </div>
              {
                cartItems.length > 0 ? (
                  <div className="flex flex-col justify-between items-center">
                    <h1 className="text-lg font-bold">Total: ${getCartTotal()}</h1>
                    <button
                      className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                      onClick={() => {
                        clearCart()
                      }}
                    >
                      Clear cart
                    </button>
                    <Button variant="primary" onClick={makePayment} >Check out
                      </Button> 
                  </div>
                ) : (
                  <>
                    <h1 className="text-lg font-bold">Your cart is empty</h1>
                  </>
                )
              }
            </div>
            <div class="col d-flex justify-content-center">      
 </div>
          </>
        </Box>
      </Modal>
    </div>
  );
} 

below is my node server where I am trying to process the back end


const cors = require("cors"); 
const express = require("express"); 
 
const stripe = require("stripe")("sMK"); 
 
const app = express(); 
 
// Middlewares here 
app.use(express.json()); 
 
// Routes here 
app.get("/", (req, res) => { 
  res.send("Hello World"); 
}); 
 
app.use(cors({origin: "*",}))
// Listen 
app.listen(8000, () => { 
  console.log("Server started at port 8000"); 
}); 

app.post("/api/create-checkout-session", async (req, res) => { 
    const { product } = req.body; 
    const session = await stripe.checkout.sessions.create({ 
      payment_method_types: ["card"], 
      line_items: [ 
        { 
          price_data: { 
            currency: "inr", 
            product_data: { 
              name: product.name, 
            }, 
            unit_amount: product.price * 100, 
          }, 
          quantity: product.quantity, 
        }, 
      ], 
      mode: "payment", 
      success_url: "http://localhost:3000/success", 
      cancel_url: "http://localhost:3000/failure", 
    }); 
    res.json({ id: session.id }); 
  }); 


Solution

  • Your fetch command needs to specify the URL scheme, which for localhost should be http:.

    Try changing this

    const response = await fetch( 
          "localhost:8000/api/create-checkout-session", 
          { 
            method: "POST", 
            headers: headers, 
            body: JSON.stringify(body), 
          } 
        ); 
    

    to this

    const response = await fetch( 
          "http://localhost:8000/api/create-checkout-session", 
          { 
            method: "POST", 
            headers: headers, 
            body: JSON.stringify(body), 
          } 
        );