# Billing Service Go-Microservice fuer Stripe-basiertes Subscription Management mit Task-basierter Abrechnung. ## Uebersicht Der Billing Service verwaltet: - Subscription Lifecycle (Trial, Active, Canceled) - Task-basierte Kontingentierung (1 Task = 1 Einheit) - Carryover-Logik (Tasks sammeln sich bis zu 5 Monate an) - Stripe Integration (Checkout, Webhooks, Portal) - Feature Gating und Entitlements ## Quick Start ### Voraussetzungen - Go 1.21+ - PostgreSQL 14+ - Docker (optional) ### Lokale Entwicklung ```bash # 1. Dependencies installieren go mod download # 2. Umgebungsvariablen setzen export DATABASE_URL="postgres://user:pass@localhost:5432/breakpilot?sslmode=disable" export JWT_SECRET="your-jwt-secret" export STRIPE_SECRET_KEY="sk_test_..." export STRIPE_WEBHOOK_SECRET="whsec_..." export BILLING_SUCCESS_URL="http://localhost:3000/billing/success" export BILLING_CANCEL_URL="http://localhost:3000/billing/cancel" export INTERNAL_API_KEY="internal-api-key" export TRIAL_PERIOD_DAYS="7" export PORT="8083" # 3. Service starten go run cmd/server/main.go # 4. Tests ausfuehren go test -v ./... ``` ### Mit Docker ```bash # Service bauen und starten docker compose up billing-service # Nur bauen docker build -t billing-service . ``` ## Architektur ``` billing-service/ ├── cmd/server/main.go # Entry Point ├── internal/ │ ├── config/config.go # Konfiguration │ ├── database/database.go # DB Connection + Migrations │ ├── models/models.go # Datenmodelle │ ├── middleware/middleware.go # JWT Auth, CORS, Rate Limiting │ ├── services/ │ │ ├── subscription_service.go # Subscription Management │ │ ├── task_service.go # Task Consumption │ │ ├── entitlement_service.go # Feature Gating │ │ ├── usage_service.go # Usage Tracking (Legacy) │ │ └── stripe_service.go # Stripe API │ └── handlers/ │ ├── billing_handlers.go # API Endpoints │ └── webhook_handlers.go # Stripe Webhooks ├── Dockerfile └── go.mod ``` ## Task-basiertes Billing ### Konzept - **1 Task = 1 Kontingentverbrauch** (unabhaengig von Seitenanzahl, Tokens, etc.) - **Monatliches Kontingent**: Plan-abhaengig (Basic: 30, Standard: 100, Premium: Fair Use) - **Carryover**: Ungenutzte Tasks sammeln sich bis zu 5 Monate an - **Max Balance**: `monthly_allowance * 5` (z.B. Basic: max 150 Tasks) ### Task Types ```go TaskTypeCorrection = "correction" // Korrekturaufgabe TaskTypeLetter = "letter" // Brief erstellen TaskTypeMeeting = "meeting" // Meeting-Protokoll TaskTypeBatch = "batch" // Batch-Verarbeitung TaskTypeOther = "other" // Sonstige ``` ### Monatswechsel-Logik Bei jedem API-Aufruf wird geprueft, ob ein Monat vergangen ist: 1. `last_renewal_at` pruefen 2. Falls >= 1 Monat: `task_balance += monthly_allowance` 3. Cap bei `max_task_balance` 4. `last_renewal_at` aktualisieren ## API Endpoints ### User Endpoints (JWT Auth) | Methode | Endpoint | Beschreibung | |---------|----------|--------------| | GET | `/api/v1/billing/status` | Aktueller Billing Status | | GET | `/api/v1/billing/plans` | Verfuegbare Plaene | | POST | `/api/v1/billing/trial/start` | Trial starten | | POST | `/api/v1/billing/change-plan` | Plan wechseln | | POST | `/api/v1/billing/cancel` | Abo kuendigen | | GET | `/api/v1/billing/portal` | Stripe Portal URL | ### Internal Endpoints (API Key) | Methode | Endpoint | Beschreibung | |---------|----------|--------------| | GET | `/api/v1/billing/entitlements/:userId` | Entitlements abrufen | | GET | `/api/v1/billing/entitlements/check/:userId/:feature` | Feature pruefen | | GET | `/api/v1/billing/tasks/check/:userId` | Task erlaubt? | | POST | `/api/v1/billing/tasks/consume` | Task konsumieren | | GET | `/api/v1/billing/tasks/usage/:userId` | Task Usage Info | ### Webhook | Methode | Endpoint | Beschreibung | |---------|----------|--------------| | POST | `/api/v1/billing/webhook` | Stripe Webhooks | ## Plaene und Preise | Plan | Preis | Tasks/Monat | Max Balance | Features | |------|-------|-------------|-------------|----------| | Basic | 9.90 EUR | 30 | 150 | Basis-Features | | Standard | 19.90 EUR | 100 | 500 | + Templates, Batch | | Premium | 39.90 EUR | Fair Use | 5000 | + Team, Admin, API | ### Fair Use Mode (Premium) Im Premium-Plan: - Keine praktische Begrenzung - Tasks werden trotzdem getrackt (fuer Monitoring) - Balance wird nicht dekrementiert - `CheckTaskAllowed` gibt immer `true` zurueck ## Datenbank ### Wichtige Tabellen ```sql -- Task-basierte Nutzung pro Account CREATE TABLE account_usage ( account_id UUID UNIQUE, plan VARCHAR(50), monthly_task_allowance INT, max_task_balance INT, task_balance INT, last_renewal_at TIMESTAMPTZ ); -- Einzelne Task-Records CREATE TABLE tasks ( id UUID PRIMARY KEY, account_id UUID, task_type VARCHAR(50), consumed BOOLEAN, created_at TIMESTAMPTZ ); ``` ## Tests ```bash # Alle Tests go test -v ./... # Mit Coverage go test -cover ./... # Nur Models go test -v ./internal/models/... # Nur Services go test -v ./internal/services/... # Nur Handlers go test -v ./internal/handlers/... ``` ## Stripe Integration ### Webhooks Konfiguriere im Stripe Dashboard: ``` URL: https://your-domain.com/api/v1/billing/webhook Events: - checkout.session.completed - customer.subscription.created - customer.subscription.updated - customer.subscription.deleted - invoice.paid - invoice.payment_failed ``` ### Lokales Testing ```bash # Stripe CLI installieren brew install stripe/stripe-cli/stripe # Webhook forwarding stripe listen --forward-to localhost:8083/api/v1/billing/webhook # Test Events triggern stripe trigger checkout.session.completed stripe trigger invoice.paid ``` ## Umgebungsvariablen | Variable | Beschreibung | Beispiel | |----------|--------------|----------| | `DATABASE_URL` | PostgreSQL Connection String | `postgres://...` | | `JWT_SECRET` | JWT Signing Secret | `your-secret` | | `STRIPE_SECRET_KEY` | Stripe Secret Key | `sk_test_...` | | `STRIPE_WEBHOOK_SECRET` | Webhook Signing Secret | `whsec_...` | | `BILLING_SUCCESS_URL` | Checkout Success Redirect | `http://...` | | `BILLING_CANCEL_URL` | Checkout Cancel Redirect | `http://...` | | `INTERNAL_API_KEY` | Service-to-Service Auth | `internal-key` | | `TRIAL_PERIOD_DAYS` | Trial Dauer in Tagen | `7` | | `PORT` | Server Port | `8083` | ## Error Handling ### Task Limit Reached ```json { "error": "TASK_LIMIT_REACHED", "message": "Dein Aufgaben-Kontingent ist aufgebraucht.", "current_balance": 0, "plan": "basic" } ``` HTTP Status: `402 Payment Required` ### No Subscription ```json { "error": "NO_SUBSCRIPTION", "message": "Kein aktives Abonnement gefunden." } ``` HTTP Status: `403 Forbidden` ## Frontend Integration ### Task Usage anzeigen ```typescript // Response von GET /api/v1/billing/status interface TaskUsageInfo { tasks_available: number; // z.B. 45 max_tasks: number; // z.B. 150 info_text: string; // "Aufgaben verfuegbar: 45 von max. 150" tooltip_text: string; // "Aufgaben koennen sich bis zu 5 Monate ansammeln." } ``` ### Task konsumieren ```typescript // Vor jeder KI-Aktion const response = await fetch('/api/v1/billing/tasks/check/' + userId); const { allowed, message } = await response.json(); if (!allowed) { showUpgradeDialog(message); return; } // Nach erfolgreicher KI-Aktion await fetch('/api/v1/billing/tasks/consume', { method: 'POST', body: JSON.stringify({ user_id: userId, task_type: 'correction' }) }); ```