Files
ANDJJJJJJ/server/index.mjs

210 lines
6.5 KiB
JavaScript

import 'dotenv/config';
import express from 'express';
import { Client, Databases, Query } from 'node-appwrite';
import Stripe from 'stripe';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const requiredEnvVars = [
'APPWRITE_ENDPOINT',
'APPWRITE_PROJECT_ID',
'APPWRITE_API_KEY',
'APPWRITE_DATABASE_ID',
'STRIPE_SECRET_KEY',
'STRIPE_WEBHOOK_SECRET'
];
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
console.error(`Error: Missing required environment variable: ${envVar}`);
process.exit(1);
}
}
const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const client = new Client()
.setEndpoint(process.env.APPWRITE_ENDPOINT)
.setProject(process.env.APPWRITE_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);
const databases = new Databases(client);
app.use(express.static(join(__dirname, '..', 'public')));
app.use('/api', express.json());
app.post('/stripe/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const sig = req.headers['stripe-signature'];
try {
const event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
const submissionId = session.metadata.submissionId;
if (submissionId) {
await databases.updateDocument(
process.env.APPWRITE_DATABASE_ID,
'submissions',
submissionId,
{ status: 'paid' }
);
await databases.createDocument(
process.env.APPWRITE_DATABASE_ID,
'orders',
'unique()',
{
submissionId: submissionId,
orderDataJson: JSON.stringify(session)
}
);
}
}
res.json({ received: true });
} catch (err) {
console.error('Webhook error:', err.message);
res.status(400).send(`Webhook Error: ${err.message}`);
}
});
app.get('/api/questions', async (req, res) => {
try {
const { productSlug } = req.query;
const productsResponse = await databases.listDocuments(
process.env.APPWRITE_DATABASE_ID,
'products',
[Query.equal('slug', productSlug), Query.equal('isActive', true)]
);
if (productsResponse.documents.length === 0) {
return res.status(404).json({ error: 'Product not found' });
}
const product = productsResponse.documents[0];
const questionsResponse = await databases.listDocuments(
process.env.APPWRITE_DATABASE_ID,
'questions',
[
Query.equal('productId', product.$id),
Query.equal('isActive', true),
Query.orderAsc('step'),
Query.orderAsc('order')
]
);
res.json(questionsResponse.documents);
} catch (error) {
console.error('Error fetching questions:', error);
res.status(500).json({ error: 'Failed to fetch questions' });
}
});
app.post('/api/submissions', async (req, res) => {
try {
const { productSlug, answers } = req.body;
const productsResponse = await databases.listDocuments(
process.env.APPWRITE_DATABASE_ID,
'products',
[Query.equal('slug', productSlug)]
);
if (productsResponse.documents.length === 0) {
return res.status(404).json({ error: 'Product not found' });
}
const product = productsResponse.documents[0];
const submission = await databases.createDocument(
process.env.APPWRITE_DATABASE_ID,
'submissions',
'unique()',
{
productId: product.$id,
status: 'draft',
customerEmail: answers.email || null,
customerName: answers.name || null,
finalSummaryJson: JSON.stringify(answers),
priceCents: product.priceCents,
currency: product.currency
}
);
await databases.createDocument(
process.env.APPWRITE_DATABASE_ID,
'answers',
'unique()',
{
submissionId: submission.$id,
answersJson: JSON.stringify(answers)
}
);
res.json({ submissionId: submission.$id });
} catch (error) {
console.error('Error creating submission:', error);
res.status(500).json({ error: 'Failed to create submission' });
}
});
app.post('/api/checkout', async (req, res) => {
try {
const { submissionId } = req.body;
if (!submissionId) {
return res.status(400).json({ error: 'Missing submissionId' });
}
const submission = await databases.getDocument(
process.env.APPWRITE_DATABASE_ID,
'submissions',
submissionId
);
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: submission.currency,
product_data: {
name: 'Email Sortierer Service',
},
unit_amount: submission.priceCents,
},
quantity: 1,
},
],
mode: 'payment',
success_url: `${process.env.BASE_URL || 'http://localhost:3000'}/success.html`,
cancel_url: `${process.env.BASE_URL || 'http://localhost:3000'}/cancel.html`,
metadata: {
submissionId: submissionId
}
});
res.json({ url: session.url });
} catch (error) {
console.error('Error creating checkout session:', error);
res.status(500).json({ error: 'Failed to create checkout session' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});