Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Activating Payments Using Stripe #160

Merged
merged 2 commits into from
May 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
node_modules
node_modules
36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"@emotion/styled": "^11.11.5",
"@mui/icons-material": "^5.15.17",
"@mui/material": "^5.15.17",
"@stripe/react-stripe-js": "^2.7.1",
"@stripe/stripe-js": "^3.4.0",
"axios": "^1.6.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
7 changes: 6 additions & 1 deletion server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MensRouter } from './routes/mens-route.js';
import connectDB from './config/DBconnect.js';
import { WomensRouter } from './routes/womens-route.js';
import { KidsRouter } from './routes/kids-route.js';
import StripeRouter from './routes/Stripe-route.js';

const app=express();

Expand All @@ -23,10 +24,14 @@ app.use(cors({
credentials:true,
}))



app.use('/api/v1/mens',MensRouter);
app.use('/api/v1/womens',WomensRouter);
app.use('/api/v1/kids',KidsRouter);

app.use('/api',StripeRouter);


const port=process.env.PORT||7000;

app.listen(port,()=>{
Expand Down
5 changes: 3 additions & 2 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
"dotenv": "^16.4.5",
"express": "^4.19.2",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.3.4",
"mongoose": "^8.3.5",
"morgan": "^1.10.0",
"nodemon": "^3.1.0"
"nodemon": "^3.1.0",
"stripe": "^15.6.0"
}
}
55 changes: 55 additions & 0 deletions server/routes/Stripe-route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import express from "express";
const StripeRouter = express.Router();
import dotenv from "dotenv";
dotenv.config({ path: "./config.env" });
import Stripe from "stripe";
const stripe = Stripe(process.env.STRIPE_PRIVATE_KEY);


StripeRouter.post("/create-checkout-session", async (req, res) => {
//ErrorHandling if product is not an Array
if (!Array.isArray(req.body.products)) {
return res.status(400).send({ error: "Products must be an array." });
}

const { products,cartItem } = req.body;
console.log(products);


//LineItems
const lineItems = products.map((product) => ({
price_data: {
currency: "usd",
product_data: {
name: product.name,
},
unit_amount: Math.round(product.new_price * 100),
},
quantity: cartItem[product.id],
}));


//checkoutSession
const session = await stripe.checkout.sessions.create({
line_items: lineItems,
mode: "payment",
success_url:
"https://shopy-mohitparmar1s-projects.vercel.app/user/paymentsuccess",
cancel_url:
"https://shopy-mohitparmar1s-projects.vercel.app/user/paymentfail",
shipping_address_collection: {
allowed_countries: ["IN", "US"],
},
phone_number_collection: {
enabled: true,
},
});

res.json({
id: session.id,
url: session.url,
})

});

export default StripeRouter;
5 changes: 4 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import men_banner from "./assets/banner_mens.png";
import women_banner from "./assets/banner_women.png";
import Footer from "./Components/Footer";
import Navbar from "./Components/Navbar";
import PaymentFail from "./Pages/paymentfail";
import PaymentSuccess from "./Pages/Success";
import Cart from "./Pages/Cart";
import Login from "./Pages/Login";
import Product from "./Pages/Product";
Expand Down Expand Up @@ -33,7 +35,8 @@ const App = () => {
<Route path="/wishlist" element={<WishlistWithFooter />} />
<Route path="/about" element={<About/>} />
<Route path="*" element={<NotFound/>} />

<Route path="/user/paymentsuccess" element={<PaymentSuccess/>} />
<Route path="/user/paymentfail" element={<PaymentFail/>} />
</Routes>
</Router>
);
Expand Down
42 changes: 40 additions & 2 deletions src/Components/CartItems.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ShopContext } from "../Context/ShopContext";
import removeIcon from "../assets/cart_cross_icon.png";
import AddIcon from "@mui/icons-material/Add";
import RemoveIcon from "@mui/icons-material/Remove";
import {loadStripe} from '@stripe/stripe-js';

const CartItems = () => {
const {
Expand All @@ -13,6 +14,44 @@ const CartItems = () => {
RemoveFromCart,
AddToCart,
} = useContext(ShopContext);

//payment gateway
const makePayment = async()=>{
const stripe = await loadStripe("Enter Your Stripe Public Key Here");

const filteredProducts = all_products.filter(product => cartItem[product.id] >0);
console.log(filteredProducts)
const body = {
products:filteredProducts,
cartItem:cartItem
}

const headers = {
"Content-Type":"application/json"
}
const response = await fetch("http://localhost:7000/api/create-checkout-session",{
method:"POST",
headers:headers,
body:JSON.stringify(body)
});
if (!response.ok) {
const errorText = await response.text(); // or response.json() if the server returns JSON
console.error('Error response:', errorText);
throw new Error(`Network response was not ok: ${response.status}`);
}

const session = await response.json();

const result = await stripe.redirectToCheckout({
sessionId:session.id
});

if(result.error){
console.log(result.error);
}
}
console.log(all_products);
console.log(cartItem)
return (
<div className="w-full h-screen my-5">
<div className="grid grid-cols-7 gap-5 items-center ml-14">
Expand All @@ -25,7 +64,6 @@ const CartItems = () => {
<p className="font-bold">Remove</p>
</div>
<hr />

{all_products &&
all_products.map((item) => {
if (cartItem[item.id] > 0) {
Expand Down Expand Up @@ -79,7 +117,7 @@ const CartItems = () => {
<h3 className="text-lg font-bold">Total</h3>
<h3 className="text-lg font-bold">${getCartTotalAmount()}</h3>
</div>
<button className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 focus:outline-none">
<button className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 focus:outline-none" onClick={makePayment}>
Proceed to Checkout
</button>
</div>
Expand Down
34 changes: 34 additions & 0 deletions src/Pages/Success.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';

const PaymentSuccess = () => {
const successPageStyle = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
textAlign: 'center',
color: '#4BB543',
};

const buttonStyle = {
marginTop: '20px',
padding: '10px 20px',
fontSize: '16px',
color: '#fff',
backgroundColor: '#007bff',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
};

return (
<div style={successPageStyle}>
<h1>Payment Successful!</h1>
<p>Your order has been placed and is on its way to being processed.</p>
<button style={buttonStyle} onClick={() => window.location.href = '/'}>Continue Shopping</button>
</div>
);
}

export default PaymentSuccess;
18 changes: 18 additions & 0 deletions src/Pages/paymentfail.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { FaSadTear } from 'react-icons/fa';

const PaymentFail = () => {

return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<FaSadTear size="5em" color="#ff6347" />
<h1>Payment Failed</h1>
<p>We encountered an issue processing your payment. Please try again.</p>
<button onClick={() => window.location.href = '/'} style={{ padding: '10px 20px', fontSize: '16px', backgroundColor: '#ff6347', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}>
Retry Payment
</button>
</div>
);
};

export default PaymentFail;