Metatron_Admin_Backend/controllers/payment.controller.js
2025-10-09 10:10:50 +05:30

133 lines
3.7 KiB
JavaScript

// controllers/payment.controller.js
import Stripe from "stripe";
import { Payment } from "../models/payment.model.js";
// ✅ Load Stripe Secret Key from .env
const stripe = new Stripe("sk_test_51SB8SnIFk8fh986GkYaNPVSfZzh6gcuXhq3tOa5hyE4U4vYIqrHwyGRu2OE1N5TNW39tJmfFOyYfsh4HcZOjlsj100xIeM46zU", {
apiVersion: "2022-11-15",
});
/**
* 🔹 Option 1: PaymentIntent API (client uses clientSecret)
*/
export async function createPaymentIntent(req, res) {
try {
const { amount } = req.body;
if (!amount) return res.status(400).json({ error: "amount is required" });
const paymentIntent = await stripe.paymentIntents.create({
amount: Math.round(amount * 100), // dollars → cents
currency: "usd",
automatic_payment_methods: { enabled: true },
});
await Payment.create({
amount: Math.round(amount * 100),
stripePaymentIntentId: paymentIntent.id,
status: "pending",
});
res.json({ clientSecret: paymentIntent.client_secret });
} catch (err) {
console.error("❌ Error creating PaymentIntent:", err);
res.status(500).json({ error: "Internal Server Error" });
}
}
/**
* 🔹 Option 2: Stripe Checkout Session (redirect flow)
*/
export async function createCheckoutSession(req, res) {
try {
const { email, amount, planId } = req.body;
if (!email || !amount) {
return res.status(400).json({ error: "email and amount are required" });
}
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
customer_email: email,
line_items: [
{
price_data: {
currency: "usd",
product_data: { name: planId || "SEO Plan" },
unit_amount: Math.round(amount * 100),
},
quantity: 1,
},
],
success_url: "https://app.crawlerx.co/success",
cancel_url: "https://app.crawlerx.co/cancel",
});
// Save to DB using stripeSessionId instead of stripePaymentIntentId
await Payment.create({
email,
amount: Math.round(amount * 100),
stripeSessionId: session.id, // ✅ use session id
status: "pending",
});
res.json({ sessionId: session.id });
} catch (err) {
console.error("❌ Error creating checkout session:", err);
res.status(500).json({ error: "Internal Server Error" });
}
}
/**
* 🔹 Stripe Webhook
* Stripe requires `express.raw({ type: "application/json" })` in route
*/
export async function handleWebhook(req, res) {
const sig = req.headers["stripe-signature"];
let event;
try {
event = stripe.webhooks.constructEvent(
req.rawBody, // Must be raw body
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
console.error("❌ Webhook signature verification failed:", err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case "payment_intent.succeeded": {
const paymentIntent = event.data.object;
console.log("✅ PaymentIntent succeeded:", paymentIntent.id);
await Payment.findOneAndUpdate(
{ stripePaymentIntentId: paymentIntent.id },
{ status: "succeeded" }
);
break;
}
case "checkout.session.completed": {
const session = event.data.object;
console.log("✅ Checkout session completed:", session.id);
// Update DB record created earlier
await Payment.findOneAndUpdate(
{ email: session.customer_email, status: "pending" },
{
stripePaymentIntentId: session.payment_intent,
status: "succeeded",
}
);
break;
}
default:
console.log(`Unhandled event type ${event.type}`);
}
res.json({ received: true });
}