import { Elysia, t } from 'elysia' import { cors } from '@elysiajs/cors' import { staticPlugin } from '@elysiajs/static' 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' // Produit LUMIÈRE_ORBITALE — prix en centimes (EUR) 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, // 1800 EUR currency: 'eur', }, } const app = new Elysia() .use(cors({ origin: DOMAIN, methods: ['GET', 'POST'], })) // Sert les fichiers statiques (html, css, js, assets) .use(staticPlugin({ assets: '.', prefix: '/', indexHTML: true, })) // ── Créer une session de checkout Stripe ────────────────────────────────── .post( '/api/checkout', async ({ body }) => { const product = PRODUCTS[body.product as keyof typeof PRODUCTS] if (!product) { throw new Error('Produit inconnu') } 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.html?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${DOMAIN}/#collection`, locale: 'fr', custom_text: { submit: { message: 'Pièce unique — fabriquée à Paris. Délai de fabrication : 6 à 8 semaines.' }, }, }) return { url: session.url } }, { body: t.Object({ product: t.String(), email: t.Optional(t.String({ format: 'email' })), }), } ) // ── Vérification de session (page success) ──────────────────────────────── .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 const rawBody = await request.arrayBuffer() try { event = stripe.webhooks.constructEvent( Buffer.from(rawBody), sig, webhookSecret ) } catch (err) { console.error('⚠ Webhook signature invalide:', err) 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 reçu — session: ${session.id}`) console.log(` Client: ${session.customer_details?.email}`) console.log(` Montant: ${(session.amount_total ?? 0) / 100} EUR`) // → ici : envoyer email confirmation, mettre à jour BDD, etc. } } return { received: true } }) .listen(3000) console.log(` ┌──────────────────────────────────────┐ │ REBOUR — SERVEUR DÉMARRÉ │ │ http://localhost:3000 │ │ │ │ POST /api/checkout │ │ GET /api/session/:id │ │ POST /api/webhook │ └──────────────────────────────────────┘ `)