puffin-app/server/index.js
Matt 06733cb2cb
All checks were successful
Build and Push Docker Image / docker (push) Successful in 42s
Integrate Stripe Checkout and add comprehensive UI enhancements
## Stripe Payment Integration
- Add Express.js backend server with Stripe Checkout Sessions
- Create SQLite database for order tracking
- Implement Stripe webhook handlers for payment events
- Integrate with Wren Climate API for carbon offset fulfillment
- Add CheckoutSuccess and CheckoutCancel pages
- Create checkout API client for frontend
- Update OffsetOrder component to redirect to Stripe Checkout
- Add processing fee calculation (3% of base amount)
- Implement order status tracking (pending → paid → fulfilled)

Backend (server/):
- Express server with CORS and middleware
- SQLite database with Order schema
- Stripe configuration and client
- Order CRUD operations model
- Checkout session creation endpoint
- Webhook handler for payment confirmation
- Wren API client for offset fulfillment

Frontend:
- CheckoutSuccess page with order details display
- CheckoutCancel page with retry encouragement
- Updated OffsetOrder to use Stripe checkout flow
- Added checkout routes to App.tsx
- TypeScript interfaces for checkout flow

## Visual & UX Enhancements
- Add CertificationBadge component for project verification status
- Create PortfolioDonutChart for visual portfolio allocation
- Implement RadialProgress for percentage displays
- Add reusable form components (FormInput, FormTextarea, FormSelect, FormFieldWrapper)
- Refactor OffsetOrder with improved layout and animations
- Add offset percentage slider with visual feedback
- Enhance MobileOffsetOrder with better responsive design
- Improve TripCalculator with cleaner UI structure
- Update CurrencySelect with better styling
- Add portfolio distribution visualization
- Enhance project cards with hover effects and animations
- Improve color palette and gradient usage throughout

## Configuration
- Add VITE_API_BASE_URL environment variable
- Create backend .env.example template
- Update frontend .env.example with API URL
- Add Stripe documentation references

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 21:45:14 +01:00

81 lines
2.6 KiB
JavaScript

import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import { initializeDatabase } from './config/database.js';
import checkoutRoutes from './routes/checkout.js';
import webhookRoutes from './routes/webhooks.js';
const app = express();
const PORT = process.env.PORT || 3001;
// Initialize database
console.log('🗄️ Initializing database...');
initializeDatabase();
// CORS configuration
const corsOptions = {
origin: process.env.FRONTEND_URL || 'http://localhost:5173',
credentials: true,
};
app.use(cors(corsOptions));
// IMPORTANT: Webhook routes must come BEFORE express.json() middleware
// because Stripe webhooks require raw body for signature verification
app.use('/api/webhooks', webhookRoutes);
// JSON body parser for all other routes
app.use(express.json());
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// API Routes
app.use('/api/checkout', checkoutRoutes);
// Error handling middleware
app.use((err, req, res, next) => {
console.error('❌ Unhandled error:', err);
res.status(500).json({
error: 'Internal server error',
message: process.env.NODE_ENV === 'development' ? err.message : undefined,
});
});
// 404 handler
app.use((req, res) => {
res.status(404).json({ error: 'Not found' });
});
// Start server
app.listen(PORT, () => {
console.log('');
console.log('🚀 Puffin App Server');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(`📡 Server running on port ${PORT}`);
console.log(`🌐 Frontend URL: ${process.env.FRONTEND_URL}`);
console.log(`🔑 Stripe configured: ${!!process.env.STRIPE_SECRET_KEY}`);
console.log(`🌱 Wren API configured: ${!!process.env.WREN_API_TOKEN}`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('');
console.log('📝 Available endpoints:');
console.log(` GET http://localhost:${PORT}/health`);
console.log(` POST http://localhost:${PORT}/api/checkout/create-session`);
console.log(` GET http://localhost:${PORT}/api/checkout/session/:sessionId`);
console.log(` POST http://localhost:${PORT}/api/webhooks/stripe`);
console.log('');
});
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('👋 SIGTERM received, shutting down gracefully...');
process.exit(0);
});
process.on('SIGINT', () => {
console.log('👋 SIGINT received, shutting down gracefully...');
process.exit(0);
});