freedge/backend/.env.example
ordinarthur 339de4c44c feat(stripe): full subscription flow (checkout, portal, webhooks)
Backend:
- Prisma: add stripeSubscriptionId, subscriptionStatus, priceId,
  currentPeriodEnd to User + migration SQL
- plugins/stripe.ts: getPlans catalog with env-based price IDs
- server.ts: raw body JSON parser for webhook signature verification,
  skip rate limit on /stripe/webhook
- types/fastify.d.ts: declare rawBody on FastifyRequest
- routes/stripe.ts (new):
  - GET  /stripe/plans        public
  - GET  /stripe/subscription user status
  - POST /stripe/checkout     hosted Checkout Session, lazy-creates
    customer, dynamic payment methods, promo codes enabled
  - POST /stripe/portal       Billing Portal session
  - POST /stripe/webhook      signature verified, handles
    checkout.session.completed, customer.subscription.*,
    invoice.payment_failed. Resolves user by clientReferenceId,
    metadata.userId, or stripeId fallback
- .env.example + README: Stripe setup, stripe CLI, test cards

Frontend:
- api/stripe.ts typed client (getPlans, getSubscription,
  startCheckout, openPortal)
- pages/Pricing.tsx: 3-card grid (free/essentiel/premium) with
  popular badge, current plan indicator, gradient popular card
- pages/CheckoutSuccess.tsx: animated confirmation with polling on
  /stripe/subscription until webhook activates plan
- pages/Profile.tsx: SubscriptionCard above tabs — free users see an
  upgrade banner, paid users see plan + status + next billing date
  + 'Gérer l'abonnement' button opening Customer Portal
- components/header.tsx: 'Tarifs' link in nav
- App.tsx: /pricing (public) and /checkout/success (protected) routes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:54:27 +02:00

65 lines
2.2 KiB
Plaintext

# ---- Requis ----
DATABASE_URL="file:./prisma/dev.db"
JWT_SECRET="change-me-please-use-at-least-32-characters"
OPENAI_API_KEY="sk-..."
# ---- Serveur ----
PORT=3000
LOG_LEVEL=info
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
FRONTEND_URL=http://localhost:5173
# Base URL publique du backend (utilisée pour les URLs de fichiers servis localement)
PUBLIC_BASE_URL=http://localhost:3000
# ---- IA ----
# Modèle texte (recette). Recommandé : gpt-4o-mini (rapide & cheap),
# ou gpt-4o pour un cran de qualité supplémentaire.
OPENAI_TEXT_MODEL=gpt-4o-mini
# Modèle de transcription audio.
# - gpt-4o-mini-transcribe : -50% par rapport à whisper-1, meilleur en français
# - whisper-1 : ancien, à éviter sauf compat
OPENAI_TRANSCRIBE_MODEL=gpt-4o-mini-transcribe
# Génération d'image
ENABLE_IMAGE_GENERATION=true
# Modèle principal : gpt-image-1 (meilleure qualité photographique)
# NOTE : gpt-image-1 requiert une vérification d'organisation sur OpenAI.
# Si ton org n'est pas vérifiée, mets dall-e-3 en principal.
OPENAI_IMAGE_MODEL=gpt-image-1
# Modèle de fallback automatique si le principal échoue (ex: org non vérifiée)
OPENAI_IMAGE_FALLBACK_MODEL=dall-e-3
# Pour gpt-image-1: low | medium | high
# Pour dall-e-3: standard | hd (mappé automatiquement)
OPENAI_IMAGE_QUALITY=medium
OPENAI_IMAGE_SIZE=1024x1024
# Robustesse OpenAI
OPENAI_MAX_RETRIES=3
OPENAI_TIMEOUT_MS=60000
# ---- Stripe ----
# Clé secrète (commence par sk_test_ en dev, sk_live_ en prod)
STRIPE_SECRET_KEY=
# Secret webhook (affiché par `stripe listen --forward-to localhost:3000/stripe/webhook`)
STRIPE_WEBHOOK_SECRET=
# IDs des prix récurrents créés dans le dashboard Stripe
STRIPE_PRICE_ID_ESSENTIAL=price_...
STRIPE_PRICE_ID_PREMIUM=price_...
# Version d'API (facultatif, défaut = 2023-10-16)
# STRIPE_API_VERSION=2023-10-16
# ---- MinIO (démarré avec `docker-compose up -d` depuis la racine du projet) ----
# Laisse vide pour désactiver et utiliser uniquement le stockage local ./uploads
MINIO_ENDPOINT=localhost
MINIO_PORT=9000
MINIO_USE_SSL=false
MINIO_ACCESS_KEY=freedge
MINIO_SECRET_KEY=freedge123
MINIO_BUCKET=freedge
MINIO_ALLOW_SELF_SIGNED=false
# ---- Email (optionnel) ----
RESEND_API_KEY=