import Fastify from 'fastify' import cors from '@fastify/cors' import Stripe from 'stripe' import { readFileSync } from 'node:fs' const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '') const DOMAIN = process.env.DOMAIN ?? 'http://localhost:3000' const PRODUCTS = { lumiere_orbitale: { name: 'LUMIÈRE_ORBITALE — REBOUR', description: 'Lampe de table unique. Béton texturé coulé à la main + dôme céramique laqué. Collection 001.', amount: 180000, currency: 'eur', }, } const app = Fastify({ logger: true }) await app.register(cors, { origin: '*', methods: ['GET', 'POST'] }) // ── SEO ─────────────────────────────────────────────────────────────────────── app.get('/robots.txt', (_, reply) => { reply .type('text/plain') .header('Cache-Control', 'public, max-age=86400') .send(`User-agent: *\nAllow: /\nSitemap: ${DOMAIN}/sitemap.xml\n`) }) app.get('/sitemap.xml', (_, reply) => { const today = new Date().toISOString().split('T')[0] reply .type('application/xml') .header('Cache-Control', 'public, max-age=86400') .send( `\n\n ${DOMAIN}/${today}weekly1.0\n` ) }) // ── Checkout Stripe ─────────────────────────────────────────────────────────── app.post('/api/checkout', async (request, reply) => { const { product, email } = request.body ?? {} const p = PRODUCTS[product] if (!p) return reply.code(404).send({ error: 'Produit inconnu' }) const session = await stripe.checkout.sessions.create({ mode: 'payment', payment_method_types: ['card'], line_items: [{ price_data: { currency: p.currency, unit_amount: p.amount, product_data: { name: p.name, description: p.description }, }, quantity: 1, }], success_url: `${DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${DOMAIN}/#collection`, locale: 'fr', customer_email: email ?? undefined, custom_text: { submit: { message: 'Pièce unique — fabriquée à Paris. Délai : 6 à 8 semaines.' }, }, }) return { url: session.url } }) // ── Vérification session ────────────────────────────────────────────────────── app.get('/api/session/:id', async (request) => { const session = await stripe.checkout.sessions.retrieve(request.params.id) return { status: session.payment_status, amount: session.amount_total, currency: session.currency, customer_email: session.customer_details?.email ?? null, } }) // ── Webhook Stripe ──────────────────────────────────────────────────────────── app.post('/api/webhook', { config: { rawBody: true }, onRequest: (request, reply, done) => { request.rawBody = '' request.req.on('data', chunk => { request.rawBody += chunk }) request.req.on('end', done) }, }, async (request, reply) => { const sig = request.headers['stripe-signature'] const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET if (!sig || !webhookSecret) return reply.code(400).send('Missing signature') let event try { event = stripe.webhooks.constructEvent(request.rawBody, sig, webhookSecret) } catch { return reply.code(400).send('Webhook Error') } if (event.type === 'checkout.session.completed') { const session = event.data.object if (session.payment_status === 'paid') { app.log.info(`✓ Paiement — ${session.id} — ${session.customer_details?.email}`) } } return { received: true } }) // ── Start ───────────────────────────────────────────────────────────────────── try { await app.listen({ port: 3000, host: '127.0.0.1' }) } catch (err) { app.log.error(err) process.exit(1) }