import { Elysia, t } from 'elysia' import { cors } from '@elysiajs/cors' import Stripe from 'stripe' const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', { apiVersion: '2025-01-27.acacia', }) 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 = new Elysia() .use(cors({ origin: '*', methods: ['GET', 'POST'] })) // ── SEO : robots + sitemap (nginx ne les génère pas dynamiquement) ────────── .get('/robots.txt', () => new Response(`User-agent: *\nAllow: /\nSitemap: ${DOMAIN}/sitemap.xml\n`, { headers: { 'Content-Type': 'text/plain', 'Cache-Control': 'public, max-age=86400' }, }) ) .get('/sitemap.xml', () => { const today = new Date().toISOString().split('T')[0] return new Response( `\n\n ${DOMAIN}/${today}weekly1.0\n`, { headers: { 'Content-Type': 'application/xml', 'Cache-Control': 'public, max-age=86400' } } ) }) // ── API Stripe : créer session checkout ─────────────────────────────────── .post( '/api/checkout', async ({ body }) => { const product = PRODUCTS[body.product as keyof typeof PRODUCTS] if (!product) return new Response('Produit inconnu', { status: 404 }) const session = await stripe.checkout.sessions.create({ mode: 'payment', payment_method_types: ['card'], line_items: [{ price_data: { currency: product.currency, unit_amount: product.amount, product_data: { name: product.name, description: product.description }, }, quantity: 1, }], success_url: `${DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${DOMAIN}/#collection`, locale: 'fr', customer_email: body.email ?? undefined, custom_text: { submit: { message: 'Pièce unique — fabriquée à Paris. Délai : 6 à 8 semaines.' }, }, }) return { url: session.url } }, { body: t.Object({ product: t.String(), email: t.Optional(t.String()), }), } ) // ── API : vérifier session après paiement ───────────────────────────────── .get( '/api/session/:id', async ({ params }) => { const session = await stripe.checkout.sessions.retrieve(params.id) return { status: session.payment_status, amount: session.amount_total, currency: session.currency, customer_email: session.customer_details?.email ?? null, } }, { params: t.Object({ id: t.String() }) } ) // ── Webhook Stripe ───────────────────────────────────────────────────────── .post('/api/webhook', async ({ request, headers }) => { const sig = headers['stripe-signature'] const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET if (!sig || !webhookSecret) return new Response('Missing signature', { status: 400 }) let event: Stripe.Event try { event = stripe.webhooks.constructEvent( Buffer.from(await request.arrayBuffer()), sig, webhookSecret ) } catch { return new Response('Webhook Error', { status: 400 }) } if (event.type === 'checkout.session.completed') { const session = event.data.object as Stripe.Checkout.Session if (session.payment_status === 'paid') { console.log(`✓ Paiement — ${session.id} — ${session.customer_details?.email}`) } } return { received: true } }) .listen(3000) console.log(` ┌──────────────────────────────────────┐ │ REBOUR API — http://localhost:3000 │ │ NODE_ENV: ${process.env.NODE_ENV ?? 'development'} └──────────────────────────────────────┘ `)