147 lines
4.5 KiB
JavaScript
147 lines
4.5 KiB
JavaScript
import express from 'express';
|
|
import cors from 'cors';
|
|
import Stripe from 'stripe';
|
|
import dotenv from 'dotenv';
|
|
|
|
dotenv.config();
|
|
|
|
const app = express();
|
|
const port = process.env.PORT || 3001;
|
|
|
|
// Initialize Stripe
|
|
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
|
|
// Middleware
|
|
app.use(cors({
|
|
origin: process.env.FRONTEND_URL || 'http://localhost:5173',
|
|
}));
|
|
app.use(express.json());
|
|
|
|
// Health check
|
|
app.get('/api/health', (req, res) => {
|
|
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
});
|
|
|
|
// Create Stripe Checkout Session
|
|
app.post('/api/checkout', async (req, res) => {
|
|
try {
|
|
const { orderData } = req.body;
|
|
|
|
// Validate required fields
|
|
if (!orderData?.contact?.email || !orderData?.contact?.name) {
|
|
return res.status(400).json({ error: 'Name and email are required' });
|
|
}
|
|
|
|
// Create Stripe Checkout Session
|
|
const session = await stripe.checkout.sessions.create({
|
|
payment_method_types: ['card'],
|
|
mode: 'payment',
|
|
customer_email: orderData.contact.email,
|
|
line_items: [
|
|
{
|
|
price_data: {
|
|
currency: 'eur',
|
|
product_data: {
|
|
name: 'Website in 48h',
|
|
description: `${orderData.websiteType} | ${orderData.style} | ${orderData.theme === 'dark' ? 'Dunkel' : 'Hell'}`,
|
|
images: ['https://webklar.de/og-image.png'], // Optional
|
|
},
|
|
unit_amount: 19900, // 199€ in cents
|
|
},
|
|
quantity: 1,
|
|
},
|
|
],
|
|
metadata: {
|
|
customerName: orderData.contact.name,
|
|
customerCompany: orderData.contact.company || '',
|
|
customerPhone: orderData.contact.phone || '',
|
|
websiteType: orderData.websiteType,
|
|
style: orderData.style,
|
|
theme: orderData.theme,
|
|
colorPrimary: orderData.colors?.primary || '#0A400C',
|
|
colorSecondary: orderData.colors?.secondary || '#819067',
|
|
colorAccent: orderData.colors?.accent || '#B1AB86',
|
|
customReferenceUrl: orderData.customInput?.referenceUrl || '',
|
|
customDescription: orderData.customInput?.description || '',
|
|
},
|
|
success_url: `${process.env.FRONTEND_URL || 'http://localhost:5173'}/success?session_id={CHECKOUT_SESSION_ID}`,
|
|
cancel_url: `${process.env.FRONTEND_URL || 'http://localhost:5173'}/konfigurator`,
|
|
});
|
|
|
|
res.json({
|
|
sessionId: session.id,
|
|
url: session.url
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Stripe error:', error);
|
|
res.status(500).json({
|
|
error: 'Failed to create checkout session',
|
|
details: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// Verify session (for success page)
|
|
app.get('/api/session/:sessionId', async (req, res) => {
|
|
try {
|
|
const session = await stripe.checkout.sessions.retrieve(req.params.sessionId);
|
|
|
|
res.json({
|
|
id: session.id,
|
|
status: session.payment_status,
|
|
customerEmail: session.customer_email,
|
|
amountTotal: session.amount_total,
|
|
metadata: session.metadata,
|
|
});
|
|
} catch (error) {
|
|
console.error('Session verification error:', error);
|
|
res.status(404).json({ error: 'Session not found' });
|
|
}
|
|
});
|
|
|
|
// Stripe Webhook (for production)
|
|
app.post('/api/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
|
|
const sig = req.headers['stripe-signature'];
|
|
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
|
|
|
|
if (!webhookSecret) {
|
|
console.warn('Webhook secret not configured');
|
|
return res.status(400).send('Webhook secret not configured');
|
|
}
|
|
|
|
try {
|
|
const event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
|
|
|
|
switch (event.type) {
|
|
case 'checkout.session.completed':
|
|
const session = event.data.object;
|
|
console.log('✅ Payment successful:', session.id);
|
|
// TODO: Save order to database, send confirmation email, etc.
|
|
break;
|
|
|
|
case 'payment_intent.payment_failed':
|
|
console.log('❌ Payment failed:', event.data.object.id);
|
|
break;
|
|
|
|
default:
|
|
console.log(`Unhandled event type: ${event.type}`);
|
|
}
|
|
|
|
res.json({ received: true });
|
|
} catch (error) {
|
|
console.error('Webhook error:', error.message);
|
|
res.status(400).send(`Webhook Error: ${error.message}`);
|
|
}
|
|
});
|
|
|
|
app.listen(port, () => {
|
|
console.log(`\n🚀 Server running on http://localhost:${port}`);
|
|
console.log(`\n📋 Endpoints:`);
|
|
console.log(` GET /api/health`);
|
|
console.log(` POST /api/checkout`);
|
|
console.log(` GET /api/session/:sessionId`);
|
|
console.log(` POST /api/webhook\n`);
|
|
});
|
|
|