/** * Stripe Checkout Session API * Deploy as standalone Node.js server. * * Environment: STRIPE_SECRET_KEY, FRONTEND_URL */ const http = require('http') const https = require('https') const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY const FRONTEND_URL = process.env.FRONTEND_URL || 'https://git.fdsa.agency' const PORT = process.env.PORT || 8787 function createCheckoutSession(priceId, mode, email) { return new Promise((resolve, reject) => { const data = new URLSearchParams({ mode: mode || 'payment', success_url: `${FRONTEND_URL}/checkout/success`, cancel_url: `${FRONTEND_URL}/checkout/cancel`, allow_promotion_codes: 'true', 'line_items[0][price]': priceId, 'line_items[0][quantity]': '1', }) if (email) data.set('customer_email', email) const options = { hostname: 'api.stripe.com', path: '/v1/checkout/sessions', method: 'POST', headers: { 'Authorization': `Bearer ${STRIPE_SECRET_KEY}`, 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': data.toString().length, }, } const req = https.request(options, (res) => { let body = '' res.on('data', chunk => body += chunk) res.on('end', () => { try { resolve({ status: res.statusCode, body: JSON.parse(body) }) } catch { resolve({ status: res.statusCode, body: { error: { message: body } } }) } }) }) req.on('error', reject) req.write(data.toString()) req.end() }) } const server = http.createServer(async (req, res) => { res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS') res.setHeader('Access-Control-Allow-Headers', 'Content-Type') // Healthcheck endpoint if (req.url === '/health' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ status: 'ok', uptime: process.uptime() })) return } if (req.method === 'OPTIONS') { res.writeHead(204) res.end() return } if (req.method !== 'POST') { res.writeHead(405, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: 'Method not allowed' })) return } if (!STRIPE_SECRET_KEY) { res.writeHead(500, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: 'Stripe not configured' })) return } let body = '' req.on('data', chunk => body += chunk) req.on('end', async () => { try { const { price_id, mode, customer_email } = JSON.parse(body) const result = await createCheckoutSession(price_id, mode, customer_email) if (result.status === 200) { res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ url: result.body.url, session_id: result.body.id })) } else { res.writeHead(result.status, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: result.body.error?.message || 'Stripe error' })) } } catch (e) { res.writeHead(400, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: e.message })) } }) }) server.listen(PORT, () => { console.log(`Checkout API running on :${PORT}`) })