From d15a6d22db2f30aa5ce82e402c93658d95de9e4f Mon Sep 17 00:00:00 2001 From: Horror26 <1032210438@tcetmumbai.in> Date: Thu, 29 May 2025 14:45:16 +0530 Subject: [PATCH 1/3] updated the payment according to razerpy update --- package-lock.json | 45 +++++++--- package.json | 1 + server/config/razorpay.js | 6 ++ server/controllers/Payments.js | 88 +++++++++++-------- server/index.js | 10 ++- src/App.css | 3 +- src/services/operations/studentFeaturesAPI.js | 10 +-- 7 files changed, 101 insertions(+), 62 deletions(-) diff --git a/package-lock.json b/package-lock.json index a16becf..3e0137e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "chart.js": "^4.3.0", "concurrently": "^8.0.1", "copy-to-clipboard": "^3.3.3", + "razorpay": "^2.9.6", "react": "^18.2.0", "react-chartjs-2": "^5.2.0", "react-countup": "^6.5.3", @@ -4634,11 +4635,11 @@ } }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -7952,9 +7953,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -14554,6 +14555,14 @@ "node": ">=0.10.0" } }, + "node_modules/razorpay": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/razorpay/-/razorpay-2.9.6.tgz", + "integrity": "sha512-zsHAQzd6e1Cc6BNoCNZQaf65ElL6O6yw0wulxmoG5VQDr363fZC90Mp1V5EktVzG45yPyNomNXWlf4cQ3622gQ==", + "dependencies": { + "axios": "^1.6.8" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -21328,11 +21337,11 @@ "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==" }, "axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "requires": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" }, @@ -23777,9 +23786,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, "for-each": { "version": "0.3.3", @@ -28230,6 +28239,14 @@ } } }, + "razorpay": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/razorpay/-/razorpay-2.9.6.tgz", + "integrity": "sha512-zsHAQzd6e1Cc6BNoCNZQaf65ElL6O6yw0wulxmoG5VQDr363fZC90Mp1V5EktVzG45yPyNomNXWlf4cQ3622gQ==", + "requires": { + "axios": "^1.6.8" + } + }, "react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", diff --git a/package.json b/package.json index a9931b9..b2fdc62 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "chart.js": "^4.3.0", "concurrently": "^8.0.1", "copy-to-clipboard": "^3.3.3", + "razorpay": "^2.9.6", "react": "^18.2.0", "react-chartjs-2": "^5.2.0", "react-countup": "^6.5.3", diff --git a/server/config/razorpay.js b/server/config/razorpay.js index 1813874..b93235f 100644 --- a/server/config/razorpay.js +++ b/server/config/razorpay.js @@ -1,8 +1,14 @@ const Razorpay = require("razorpay"); +if (!process.env.RAZORPAY_KEY || !process.env.RAZORPAY_SECRET) { + throw new Error("Razorpay credentials are not properly configured"); +} exports.instance = new Razorpay({ key_id: process.env.RAZORPAY_KEY, key_secret: process.env.RAZORPAY_SECRET, + headers: { + 'Content-Type': 'application/json' + } }); diff --git a/server/controllers/Payments.js b/server/controllers/Payments.js index 48488bc..9bda586 100644 --- a/server/controllers/Payments.js +++ b/server/controllers/Payments.js @@ -10,56 +10,68 @@ const CourseProgress = require("../models/CourseProgress"); //initiate the razorpay order exports.capturePayment = async(req, res) => { + try { + const {courses} = req.body; + const userId = req.user.id; - const {courses} = req.body; - const userId = req.user.id; + if(!courses || courses.length === 0) { + return res.status(400).json({success:false, message:"Please provide Course Id"}); + } - if(courses.length === 0) { - return res.json({success:false, message:"Please provide Course Id"}); - } + let totalAmount = 0; - let totalAmount = 0; + for(const course_id of courses) { + let course; + try { + course = await Course.findById(course_id); + if(!course) { + return res.status(404).json({success:false, message:"Could not find the course"}); + } - for(const course_id of courses) { - let course; - try{ - - course = await Course.findById(course_id); - if(!course) { - return res.status(200).json({success:false, message:"Could not find the course"}); - } + const uid = new mongoose.Types.ObjectId(userId); + if(course.studentsEnrolled.includes(uid)) { + return res.status(400).json({success:false, message:"Student is already Enrolled"}); + } - const uid = new mongoose.Types.ObjectId(userId); - if(course.studentsEnrolled.includes(uid)) { - return res.status(200).json({success:false, message:"Student is already Enrolled"}); + totalAmount += course.price; + } + catch(error) { + console.error("Error finding course:", error); + return res.status(500).json({success:false, message:"Error processing course details"}); } - - totalAmount += course.price; - } - catch(error) { - console.log(error); - return res.status(500).json({success:false, message:error.message}); } - } - const currency = "INR"; - const options = { - amount: totalAmount * 100, - currency, - receipt: Math.random(Date.now()).toString(), - } - try{ + const currency = "INR"; + const options = { + amount: Math.round(totalAmount * 100), // Ensure amount is a whole number + currency, + receipt: `receipt_${Date.now()}`, + notes: { + userId: userId, + courses: courses + } + }; + const paymentResponse = await instance.orders.create(options); - res.json({ - success:true, - message:paymentResponse, - }) + + // Return the response in the expected format + return res.status(200).json({ + success: true, + data: { + orderId: paymentResponse.id, + amount: paymentResponse.amount, + currency: paymentResponse.currency, + key: process.env.RAZORPAY_KEY + } + }); } catch(error) { - console.log(error); - return res.status(500).json({success:false, mesage:"Could not Initiate Order"}); + console.error("Payment initiation error:", error); + return res.status(500).json({ + success: false, + message: error.message || "Could not initiate payment" + }); } - } diff --git a/server/index.js b/server/index.js index 0cf85c1..3ce5b50 100644 --- a/server/index.js +++ b/server/index.js @@ -21,7 +21,12 @@ database.connect(); //middlewares app.use(express.json()); app.use(cookieParser()); -app.use(cors()); +app.use( + cors({ + origin: process.env.CORS_ORIGIN || "http://localhost:3000", + credentials: true, + }) +); app.use( fileUpload({ @@ -50,5 +55,4 @@ app.get("/", (req, res) => { app.listen(PORT, () => { console.log(`App is running at ${PORT}`) -}) - +}) \ No newline at end of file diff --git a/src/App.css b/src/App.css index 7bf521b..c5d9451 100644 --- a/src/App.css +++ b/src/App.css @@ -7,8 +7,7 @@ body { overflow-x: hidden; } -/* ===== Scrollbar CSS ===== */ -/* Firefox */ + * { scrollbar-width: auto; scrollbar-color: #afb2bf; diff --git a/src/services/operations/studentFeaturesAPI.js b/src/services/operations/studentFeaturesAPI.js index 6ba9992..d07eed9 100644 --- a/src/services/operations/studentFeaturesAPI.js +++ b/src/services/operations/studentFeaturesAPI.js @@ -48,10 +48,10 @@ export async function buyCourse(token, courses, userDetails, navigate, dispatch) console.log("PRINTING orderResponse", orderResponse); //options const options = { - key: process.env.RAZORPAY_KEY, - currency: orderResponse.data.message.currency, - amount: `${orderResponse.data.message.amount}`, - order_id:orderResponse.data.message.id, + key: orderResponse.data.data.key, + currency: orderResponse.data.data.currency, + amount: orderResponse.data.data.amount, + order_id: orderResponse.data.data.orderId, name:"StudyNotion", description: "Thank You for Purchasing the Course", image:rzpLogo, @@ -61,7 +61,7 @@ export async function buyCourse(token, courses, userDetails, navigate, dispatch) }, handler: function(response) { //send successful wala mail - sendPaymentSuccessEmail(response, orderResponse.data.message.amount,token ); + sendPaymentSuccessEmail(response, orderResponse.data.data.amount, token); //verifyPayment verifyPayment({...response, courses}, token, navigate, dispatch); } From 86f5cbeb1b7559a3124a61f30d12dbd24c48f188 Mon Sep 17 00:00:00 2001 From: Horror26 <1032210438@tcetmumbai.in> Date: Thu, 29 May 2025 15:02:49 +0530 Subject: [PATCH 2/3] updated aaxios error --- server/controllers/Payments.js | 355 +++------------------------------ 1 file changed, 27 insertions(+), 328 deletions(-) diff --git a/server/controllers/Payments.js b/server/controllers/Payments.js index 9bda586..4a6e8eb 100644 --- a/server/controllers/Payments.js +++ b/server/controllers/Payments.js @@ -1,339 +1,38 @@ -const {instance} = require("../config/razorpay"); -const Course = require("../models/Course"); -const User = require("../models/User"); -const mailSender = require("../utils/mailSender"); -const {courseEnrollmentEmail} = require("../mail/templates/courseEnrollmentEmail"); -const { default: mongoose } = require("mongoose"); -const { paymentSuccessEmail } = require("../mail/templates/paymentSuccessEmail"); -const crypto = require("crypto"); -const CourseProgress = require("../models/CourseProgress"); - -//initiate the razorpay order -exports.capturePayment = async(req, res) => { - try { - const {courses} = req.body; - const userId = req.user.id; - - if(!courses || courses.length === 0) { - return res.status(400).json({success:false, message:"Please provide Course Id"}); - } - - let totalAmount = 0; - - for(const course_id of courses) { - let course; - try { - course = await Course.findById(course_id); - if(!course) { - return res.status(404).json({success:false, message:"Could not find the course"}); - } - - const uid = new mongoose.Types.ObjectId(userId); - if(course.studentsEnrolled.includes(uid)) { - return res.status(400).json({success:false, message:"Student is already Enrolled"}); - } - - totalAmount += course.price; - } - catch(error) { - console.error("Error finding course:", error); - return res.status(500).json({success:false, message:"Error processing course details"}); - } - } - - const currency = "INR"; - const options = { - amount: Math.round(totalAmount * 100), // Ensure amount is a whole number - currency, - receipt: `receipt_${Date.now()}`, - notes: { - userId: userId, - courses: courses - } - }; - - const paymentResponse = await instance.orders.create(options); - - // Return the response in the expected format - return res.status(200).json({ - success: true, - data: { - orderId: paymentResponse.id, - amount: paymentResponse.amount, - currency: paymentResponse.currency, - key: process.env.RAZORPAY_KEY - } - }); - } - catch(error) { - console.error("Payment initiation error:", error); - return res.status(500).json({ - success: false, - message: error.message || "Could not initiate payment" - }); - } -} - - -//verify the payment -exports.verifyPayment = async(req, res) => { - const razorpay_order_id = req.body?.razorpay_order_id; - const razorpay_payment_id = req.body?.razorpay_payment_id; - const razorpay_signature = req.body?.razorpay_signature; - const courses = req.body?.courses; - const userId = req.user.id; - - if(!razorpay_order_id || - !razorpay_payment_id || - !razorpay_signature || !courses || !userId) { - return res.status(200).json({success:false, message:"Payment Failed"}); - } - - let body = razorpay_order_id + "|" + razorpay_payment_id; - const expectedSignature = crypto - .createHmac("sha256", process.env.RAZORPAY_SECRET) - .update(body.toString()) - .digest("hex"); - - if(expectedSignature === razorpay_signature) { - //enroll karwao student ko - await enrollStudents(courses, userId, res); - //return res - return res.status(200).json({success:true, message:"Payment Verified"}); - } - return res.status(200).json({success:"false", message:"Payment Failed"}); +const Razorpay = require("razorpay"); +// Validate environment variables +if (!process.env.RAZORPAY_KEY || !process.env.RAZORPAY_SECRET) { + console.error("Razorpay credentials missing!"); + throw new Error("Razorpay credentials are not properly configured"); } +// Log the first few characters of the key to verify it's being loaded +console.log("Razorpay Key ID:", process.env.RAZORPAY_KEY.substring(0, 4) + "..." + process.env.RAZORPAY_KEY.substring(process.env.RAZORPAY_KEY.length - 4)); -const enrollStudents = async(courses, userId, res) => { - - if(!courses || !userId) { - return res.status(400).json({success:false,message:"Please Provide data for Courses or UserId"}); +const razorpayInstance = new Razorpay({ + key_id: process.env.RAZORPAY_KEY.trim(), + key_secret: process.env.RAZORPAY_SECRET.trim(), + headers: { + 'Content-Type': 'application/json' } +}); - for(const courseId of courses) { - try{ - //find the course and enroll the student in it - const enrolledCourse = await Course.findOneAndUpdate( - {_id:courseId}, - {$push:{studentsEnrolled:userId}}, - {new:true}, - ) - - if(!enrolledCourse) { - return res.status(500).json({success:false,message:"Course not Found"}); - } - - const courseProgress = await CourseProgress.create({ - courseID:courseId, - userId:userId, - completedVideos: [], - }) - - //find the student and add the course to their list of enrolledCOurses - const enrolledStudent = await User.findByIdAndUpdate(userId, - {$push:{ - courses: courseId, - courseProgress: courseProgress._id, - }},{new:true}) - - ///bachhe ko mail send kardo - const emailResponse = await mailSender( - enrollStudents.email, - `Successfully Enrolled into ${enrolledCourse.courseName}`, - courseEnrollmentEmail(enrolledCourse.courseName, `${enrolledStudent.firstName}`) - ) - //console.log("Email Sent Successfully", emailResponse.response); - } - catch(error) { - console.log(error); - return res.status(500).json({success:false, message:error.message}); +// Test function to verify credentials +async function testRazorpayConnection() { + try { + const accountDetails = await razorpayInstance.account.fetch(); + console.log("Razorpay connection successful!"); + return true; + } catch (error) { + console.error("Razorpay connection test failed:", error.message); + if (error.statusCode === 401) { + console.error("Authentication failed. Please check your API keys."); } + return false; } - } -exports.sendPaymentSuccessEmail = async(req, res) => { - const {orderId, paymentId, amount} = req.body; - - const userId = req.user.id; - - if(!orderId || !paymentId || !amount || !userId) { - return res.status(400).json({success:false, message:"Please provide all the fields"}); - } - - try{ - //student ko dhundo - const enrolledStudent = await User.findById(userId); - await mailSender( - enrolledStudent.email, - `Payment Recieved`, - paymentSuccessEmail(`${enrolledStudent.firstName}`, - amount/100,orderId, paymentId) - ) - } - catch(error) { - console.log("error in sending mail", error) - return res.status(500).json({success:false, message:"Could not send email"}) - } -} - - -// //capture the payment and initiate the Razorpay order -// exports.capturePayment = async (req, res) => { -// //get courseId and UserID -// const {course_id} = req.body; -// const userId = req.user.id; -// //validation -// //valid courseID -// if(!course_id) { -// return res.json({ -// success:false, -// message:'Please provide valid course ID', -// }) -// }; -// //valid courseDetail -// let course; -// try{ -// course = await Course.findById(course_id); -// if(!course) { -// return res.json({ -// success:false, -// message:'Could not find the course', -// }); -// } - -// //user already pay for the same course -// const uid = new mongoose.Types.ObjectId(userId); -// if(course.studentsEnrolled.includes(uid)) { -// return res.status(200).json({ -// success:false, -// message:'Student is already enrolled', -// }); -// } -// } -// catch(error) { -// console.error(error); -// return res.status(500).json({ -// success:false, -// message:error.message, -// }); -// } - -// //order create -// const amount = course.price; -// const currency = "INR"; - -// const options = { -// amount: amount * 100, -// currency, -// receipt: Math.random(Date.now()).toString(), -// notes:{ -// courseId: course_id, -// userId, -// } -// }; - -// try{ -// //initiate the payment using razorpay -// const paymentResponse = await instance.orders.create(options); -// console.log(paymentResponse); -// //return response -// return res.status(200).json({ -// success:true, -// courseName:course.courseName, -// courseDescription:course.courseDescription, -// thumbnail: course.thumbnail, -// orderId: paymentResponse.id, -// currency:paymentResponse.currency, -// amount:paymentResponse.amount, -// }); -// } -// catch(error) { -// console.log(error); -// res.json({ -// success:false, -// message:"Could not initiate order", -// }); -// } - - -// }; - -// //verify Signature of Razorpay and Server - -// exports.verifySignature = async (req, res) => { -// const webhookSecret = "12345678"; - -// const signature = req.headers["x-razorpay-signature"]; - -// const shasum = crypto.createHmac("sha256", webhookSecret); -// shasum.update(JSON.stringify(req.body)); -// const digest = shasum.digest("hex"); - -// if(signature === digest) {3 -// console.log("Payment is Authorised"); - -// const {courseId, userId} = req.body.payload.payment.entity.notes; - -// try{ -// //fulfil the action - -// //find the course and enroll the student in it -// const enrolledCourse = await Course.findOneAndUpdate( -// {_id: courseId}, -// {$push:{studentsEnrolled: userId}}, -// {new:true}, -// ); - -// if(!enrolledCourse) { -// return res.status(500).json({ -// success:false, -// message:'Course not Found', -// }); -// } - -// console.log(enrolledCourse); - -// //find the student andadd the course to their list enrolled courses me -// const enrolledStudent = await User.findOneAndUpdate( -// {_id:userId}, -// {$push:{courses:courseId}}, -// {new:true}, -// ); - -// console.log(enrolledStudent); - -// //mail send krdo confirmation wala -// const emailResponse = await mailSender( -// enrolledStudent.email, -// "Congratulations from CodeHelp", -// "Congratulations, you are onboarded into new CodeHelp Course", -// ); - -// console.log(emailResponse); -// return res.status(200).json({ -// success:true, -// message:"Signature Verified and COurse Added", -// }); - - -// } -// catch(error) { -// console.log(error); -// return res.status(500).json({ -// success:false, -// message:error.message, -// }); -// } -// } -// else { -// return res.status(400).json({ -// success:false, -// message:'Invalid request', -// }); -// } - +// Test the connection when the module loads +testRazorpayConnection(); -// }; \ No newline at end of file +exports.instance = razorpayInstance; \ No newline at end of file From a535c077d2b6a07eebee3d2f121218394a60cad8 Mon Sep 17 00:00:00 2001 From: Horror26 <1032210438@tcetmumbai.in> Date: Thu, 29 May 2025 15:07:32 +0530 Subject: [PATCH 3/3] updated aaxios error --- server/controllers/Payments.js | 355 ++++++++++++++++++++++++++++++--- 1 file changed, 328 insertions(+), 27 deletions(-) diff --git a/server/controllers/Payments.js b/server/controllers/Payments.js index 4a6e8eb..9bda586 100644 --- a/server/controllers/Payments.js +++ b/server/controllers/Payments.js @@ -1,38 +1,339 @@ -const Razorpay = require("razorpay"); +const {instance} = require("../config/razorpay"); +const Course = require("../models/Course"); +const User = require("../models/User"); +const mailSender = require("../utils/mailSender"); +const {courseEnrollmentEmail} = require("../mail/templates/courseEnrollmentEmail"); +const { default: mongoose } = require("mongoose"); +const { paymentSuccessEmail } = require("../mail/templates/paymentSuccessEmail"); +const crypto = require("crypto"); +const CourseProgress = require("../models/CourseProgress"); -// Validate environment variables -if (!process.env.RAZORPAY_KEY || !process.env.RAZORPAY_SECRET) { - console.error("Razorpay credentials missing!"); - throw new Error("Razorpay credentials are not properly configured"); +//initiate the razorpay order +exports.capturePayment = async(req, res) => { + try { + const {courses} = req.body; + const userId = req.user.id; + + if(!courses || courses.length === 0) { + return res.status(400).json({success:false, message:"Please provide Course Id"}); + } + + let totalAmount = 0; + + for(const course_id of courses) { + let course; + try { + course = await Course.findById(course_id); + if(!course) { + return res.status(404).json({success:false, message:"Could not find the course"}); + } + + const uid = new mongoose.Types.ObjectId(userId); + if(course.studentsEnrolled.includes(uid)) { + return res.status(400).json({success:false, message:"Student is already Enrolled"}); + } + + totalAmount += course.price; + } + catch(error) { + console.error("Error finding course:", error); + return res.status(500).json({success:false, message:"Error processing course details"}); + } + } + + const currency = "INR"; + const options = { + amount: Math.round(totalAmount * 100), // Ensure amount is a whole number + currency, + receipt: `receipt_${Date.now()}`, + notes: { + userId: userId, + courses: courses + } + }; + + const paymentResponse = await instance.orders.create(options); + + // Return the response in the expected format + return res.status(200).json({ + success: true, + data: { + orderId: paymentResponse.id, + amount: paymentResponse.amount, + currency: paymentResponse.currency, + key: process.env.RAZORPAY_KEY + } + }); + } + catch(error) { + console.error("Payment initiation error:", error); + return res.status(500).json({ + success: false, + message: error.message || "Could not initiate payment" + }); + } } -// Log the first few characters of the key to verify it's being loaded -console.log("Razorpay Key ID:", process.env.RAZORPAY_KEY.substring(0, 4) + "..." + process.env.RAZORPAY_KEY.substring(process.env.RAZORPAY_KEY.length - 4)); -const razorpayInstance = new Razorpay({ - key_id: process.env.RAZORPAY_KEY.trim(), - key_secret: process.env.RAZORPAY_SECRET.trim(), - headers: { - 'Content-Type': 'application/json' +//verify the payment +exports.verifyPayment = async(req, res) => { + const razorpay_order_id = req.body?.razorpay_order_id; + const razorpay_payment_id = req.body?.razorpay_payment_id; + const razorpay_signature = req.body?.razorpay_signature; + const courses = req.body?.courses; + const userId = req.user.id; + + if(!razorpay_order_id || + !razorpay_payment_id || + !razorpay_signature || !courses || !userId) { + return res.status(200).json({success:false, message:"Payment Failed"}); } -}); -// Test function to verify credentials -async function testRazorpayConnection() { - try { - const accountDetails = await razorpayInstance.account.fetch(); - console.log("Razorpay connection successful!"); - return true; - } catch (error) { - console.error("Razorpay connection test failed:", error.message); - if (error.statusCode === 401) { - console.error("Authentication failed. Please check your API keys."); + let body = razorpay_order_id + "|" + razorpay_payment_id; + const expectedSignature = crypto + .createHmac("sha256", process.env.RAZORPAY_SECRET) + .update(body.toString()) + .digest("hex"); + + if(expectedSignature === razorpay_signature) { + //enroll karwao student ko + await enrollStudents(courses, userId, res); + //return res + return res.status(200).json({success:true, message:"Payment Verified"}); } - return false; + return res.status(200).json({success:"false", message:"Payment Failed"}); + +} + + +const enrollStudents = async(courses, userId, res) => { + + if(!courses || !userId) { + return res.status(400).json({success:false,message:"Please Provide data for Courses or UserId"}); } + + for(const courseId of courses) { + try{ + //find the course and enroll the student in it + const enrolledCourse = await Course.findOneAndUpdate( + {_id:courseId}, + {$push:{studentsEnrolled:userId}}, + {new:true}, + ) + + if(!enrolledCourse) { + return res.status(500).json({success:false,message:"Course not Found"}); + } + + const courseProgress = await CourseProgress.create({ + courseID:courseId, + userId:userId, + completedVideos: [], + }) + + //find the student and add the course to their list of enrolledCOurses + const enrolledStudent = await User.findByIdAndUpdate(userId, + {$push:{ + courses: courseId, + courseProgress: courseProgress._id, + }},{new:true}) + + ///bachhe ko mail send kardo + const emailResponse = await mailSender( + enrollStudents.email, + `Successfully Enrolled into ${enrolledCourse.courseName}`, + courseEnrollmentEmail(enrolledCourse.courseName, `${enrolledStudent.firstName}`) + ) + //console.log("Email Sent Successfully", emailResponse.response); + } + catch(error) { + console.log(error); + return res.status(500).json({success:false, message:error.message}); + } + } + } -// Test the connection when the module loads -testRazorpayConnection(); +exports.sendPaymentSuccessEmail = async(req, res) => { + const {orderId, paymentId, amount} = req.body; + + const userId = req.user.id; + + if(!orderId || !paymentId || !amount || !userId) { + return res.status(400).json({success:false, message:"Please provide all the fields"}); + } + + try{ + //student ko dhundo + const enrolledStudent = await User.findById(userId); + await mailSender( + enrolledStudent.email, + `Payment Recieved`, + paymentSuccessEmail(`${enrolledStudent.firstName}`, + amount/100,orderId, paymentId) + ) + } + catch(error) { + console.log("error in sending mail", error) + return res.status(500).json({success:false, message:"Could not send email"}) + } +} + + +// //capture the payment and initiate the Razorpay order +// exports.capturePayment = async (req, res) => { +// //get courseId and UserID +// const {course_id} = req.body; +// const userId = req.user.id; +// //validation +// //valid courseID +// if(!course_id) { +// return res.json({ +// success:false, +// message:'Please provide valid course ID', +// }) +// }; +// //valid courseDetail +// let course; +// try{ +// course = await Course.findById(course_id); +// if(!course) { +// return res.json({ +// success:false, +// message:'Could not find the course', +// }); +// } + +// //user already pay for the same course +// const uid = new mongoose.Types.ObjectId(userId); +// if(course.studentsEnrolled.includes(uid)) { +// return res.status(200).json({ +// success:false, +// message:'Student is already enrolled', +// }); +// } +// } +// catch(error) { +// console.error(error); +// return res.status(500).json({ +// success:false, +// message:error.message, +// }); +// } + +// //order create +// const amount = course.price; +// const currency = "INR"; + +// const options = { +// amount: amount * 100, +// currency, +// receipt: Math.random(Date.now()).toString(), +// notes:{ +// courseId: course_id, +// userId, +// } +// }; + +// try{ +// //initiate the payment using razorpay +// const paymentResponse = await instance.orders.create(options); +// console.log(paymentResponse); +// //return response +// return res.status(200).json({ +// success:true, +// courseName:course.courseName, +// courseDescription:course.courseDescription, +// thumbnail: course.thumbnail, +// orderId: paymentResponse.id, +// currency:paymentResponse.currency, +// amount:paymentResponse.amount, +// }); +// } +// catch(error) { +// console.log(error); +// res.json({ +// success:false, +// message:"Could not initiate order", +// }); +// } + + +// }; + +// //verify Signature of Razorpay and Server + +// exports.verifySignature = async (req, res) => { +// const webhookSecret = "12345678"; + +// const signature = req.headers["x-razorpay-signature"]; + +// const shasum = crypto.createHmac("sha256", webhookSecret); +// shasum.update(JSON.stringify(req.body)); +// const digest = shasum.digest("hex"); + +// if(signature === digest) {3 +// console.log("Payment is Authorised"); + +// const {courseId, userId} = req.body.payload.payment.entity.notes; + +// try{ +// //fulfil the action + +// //find the course and enroll the student in it +// const enrolledCourse = await Course.findOneAndUpdate( +// {_id: courseId}, +// {$push:{studentsEnrolled: userId}}, +// {new:true}, +// ); + +// if(!enrolledCourse) { +// return res.status(500).json({ +// success:false, +// message:'Course not Found', +// }); +// } + +// console.log(enrolledCourse); + +// //find the student andadd the course to their list enrolled courses me +// const enrolledStudent = await User.findOneAndUpdate( +// {_id:userId}, +// {$push:{courses:courseId}}, +// {new:true}, +// ); + +// console.log(enrolledStudent); + +// //mail send krdo confirmation wala +// const emailResponse = await mailSender( +// enrolledStudent.email, +// "Congratulations from CodeHelp", +// "Congratulations, you are onboarded into new CodeHelp Course", +// ); + +// console.log(emailResponse); +// return res.status(200).json({ +// success:true, +// message:"Signature Verified and COurse Added", +// }); + + +// } +// catch(error) { +// console.log(error); +// return res.status(500).json({ +// success:false, +// message:error.message, +// }); +// } +// } +// else { +// return res.status(400).json({ +// success:false, +// message:'Invalid request', +// }); +// } + -exports.instance = razorpayInstance; \ No newline at end of file +// }; \ No newline at end of file