This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/billing-service
Benjamin Admin bfdaf63ba9 fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00
..

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

# 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

# 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

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

-- 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

# 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

# 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

{
  "error": "TASK_LIMIT_REACHED",
  "message": "Dein Aufgaben-Kontingent ist aufgebraucht.",
  "current_balance": 0,
  "plan": "basic"
}

HTTP Status: 402 Payment Required

No Subscription

{
  "error": "NO_SUBSCRIPTION",
  "message": "Kein aktives Abonnement gefunden."
}

HTTP Status: 403 Forbidden

Frontend Integration

Task Usage anzeigen

// 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

// 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' })
});