Zum Inhalt

Stripe Import & Export Commands

Diese Dokumentation listet alle verfügbaren PHP Artisan Commands für den Import und Export von Daten zwischen HostAdmin und Stripe.

Inhaltsverzeichnis


Import Commands (Stripe → HostAdmin)

Diese Commands importieren Daten von Stripe in HostAdmin.

stripe:import-customers

Importiert Kunden von Stripe in HostAdmin.

Verwendung

# Docker
docker-compose exec app php artisan stripe:import-customers [OPTIONS]

# Lokal
php artisan stripe:import-customers [OPTIONS]

Optionen

Option Beschreibung
--dry-run Simulation ohne tatsächlichen Import
--update-existing Verknüpft bestehende HostAdmin-Kunden (gleiche E-Mail) mit Stripe

Beispiele

# Dry-Run (empfohlen für ersten Test)
docker-compose exec app php artisan stripe:import-customers --dry-run

# Echter Import
docker-compose exec app php artisan stripe:import-customers

# Mit Verknüpfung bestehender Kunden
docker-compose exec app php artisan stripe:import-customers --update-existing

Was wird importiert?

  • Kundendaten (Name, E-Mail, Adresse, Telefon)
  • Stripe Customer ID
  • Standard-Zahlungsmethode
  • Tax Rate (19% für DE, sonst 0%)
  • Source = stripe

Duplikat-Behandlung

  • E-Mail-Duplikate: Ohne --update-existing werden übersprungen
  • Metadata customer_id: Kunde gilt als bereits synchronisiert

Automatisierung

Läuft automatisch täglich um 3:00 Uhr (siehe routes/console.php).


stripe:import-subscriptions

Importiert Subscriptions von Stripe in HostAdmin.

Verwendung

docker-compose exec app php artisan stripe:import-subscriptions [OPTIONS]

Optionen

Option Beschreibung
--dry-run Simulation ohne tatsächlichen Import
--update-existing Aktualisiert bestehende Subscriptions wenn Stripe ID übereinstimmt

Beispiele

# Dry-Run
docker-compose exec app php artisan stripe:import-subscriptions --dry-run

# Echter Import
docker-compose exec app php artisan stripe:import-subscriptions

# Mit Update bestehender
docker-compose exec app php artisan stripe:import-subscriptions --update-existing

Was wird importiert?

  • Subscription Details (Status, Billing Cycle, Next Billing Date)
  • Subscription Items mit Prices
  • Verknüpfung mit Kunden
  • Metadata-Mapping zu ServiceDefinitions
  • Source = stripe

Voraussetzungen

  • Kunden müssen bereits importiert sein (stripe:import-customers)
  • ServiceDefinitions sollten synchronisiert sein (stripe:sync-products)

Status-Mapping

Stripe Status HostAdmin Status
active Active
canceled, cancelled Cancelled
incomplete, incomplete_expired Draft
past_due Active (mit Flag)
trialing Active
unpaid Active

stripe:import-invoices

NEU! Importiert Rechnungen von Stripe in HostAdmin.

Verwendung

docker-compose exec app php artisan stripe:import-invoices [OPTIONS]

Optionen

Option Wert Beschreibung
--from Y-m-d Start-Datum für Import (z.B. 2024-01-01)
--to Y-m-d End-Datum für Import (z.B. 2024-12-31)
--status paid, open, draft, void, uncollectible Filter nach Status (mehrfach möglich)
--dry-run - Simulation ohne tatsächlichen Import
--download-pdfs - PDFs automatisch herunterladen

Beispiele

# Alle unbezahlten Rechnungen ab 2024
docker-compose exec app php artisan stripe:import-invoices --from=2024-01-01 --status=open

# Alle bezahlten Rechnungen mit PDFs
docker-compose exec app php artisan stripe:import-invoices --status=paid --download-pdfs

# Dry Run für letzten Monat
docker-compose exec app php artisan stripe:import-invoices --from=2024-12-01 --to=2024-12-31 --dry-run

# Alle Rechnungen mit PDF-Download (empfohlen)
docker-compose exec app php artisan stripe:import-invoices --download-pdfs

Was wird importiert?

  • Invoice-Daten: Nummer, Datum, Fälligkeitsdatum, Beträge
  • Invoice Items: Alle Positionen mit Beschreibung, Menge, Preisen
  • Status: Draft, Sent, Paid, Overdue, Cancelled
  • PDFs: Werden zu S3 heruntergeladen (wenn --download-pdfs aktiviert)
  • Payment Records: Für bezahlte Rechnungen automatisch erstellt
  • Source: stripe

PDF-Ablage

PDFs werden nach folgendem Schema gespeichert:

customer/{customer_id}/invoices/{year}/{customer_number}-{invoice_number}.pdf

Beispiel: customer/123/invoices/2025/10001-RE-2025-001.pdf

Status-Mapping

Stripe Status HostAdmin Status
draft draft
open sent
paid paid
void cancelled
uncollectible overdue

Voraussetzungen

  • Kunden müssen bereits importiert sein (stripe:import-customers)

Performance-Hinweis

Mit --download-pdfs kann der Import mehrere Minuten dauern, da jedes PDF einzeln von Stripe heruntergeladen wird.


stripe:import-subscription-items

Importiert fehlende Subscription Items und erstellt automatisch CustomerServices.

Verwendung

docker-compose exec app php artisan stripe:import-subscription-items [OPTIONS]

Optionen

Option Beschreibung
--create-services Erstellt automatisch CustomerServices für Items

Beispiel

docker-compose exec app php artisan stripe:import-subscription-items --create-services

Voraussetzungen

  • Kunden importiert
  • Subscriptions importiert
  • ServiceDefinitions synchronisiert

Export/Sync Commands (HostAdmin → Stripe)

Diese Commands übertragen Daten von HostAdmin zu Stripe.

stripe:sync-customers

Synchronisiert lokale Kunden zu Stripe (erstellt oder aktualisiert).

NEU: Sucht standardmäßig nach existierenden Stripe-Kunden anhand der E-Mail-Adresse, um Duplikate zu vermeiden.

Verwendung

docker-compose exec app php artisan stripe:sync-customers [OPTIONS]

Optionen

Option Wert Beschreibung
--force - Synchronisiert alle Kunden neu (auch bereits synchronisierte)
--id customer_id Nur bestimmte Kunden synchronisieren (mehrfach möglich)
--no-search - NEU: Erstellt immer neue Stripe-Kunden ohne nach existierenden zu suchen

Beispiele

# Alle unsyncten Kunden (mit Suche nach existierenden - EMPFOHLEN)
docker-compose exec app php artisan stripe:sync-customers

# Alle Kunden neu synchronisieren (mit Suche nach existierenden)
docker-compose exec app php artisan stripe:sync-customers --force

# Nur Kunde mit ID 123 (mit Suche nach existierenden)
docker-compose exec app php artisan stripe:sync-customers --id=123

# Mehrere Kunden (mit Suche nach existierenden)
docker-compose exec app php artisan stripe:sync-customers --id=123 --id=456

# OHNE Suche - erstellt immer neue Kunden (Legacy-Verhalten)
docker-compose exec app php artisan stripe:sync-customers --no-search

Was wird synchronisiert?

  • Name (company_name oder first_name/last_name)
  • E-Mail
  • Adresse (inkl. Country)
  • Telefon
  • Tax ID (mit automatischem Type-Mapping nach Land)
  • Metadata: customer_id, customer_number

Suche nach existierenden Kunden (NEU)

Standard-Verhalten (empfohlen):

Wenn ein Kunde keine stripe_customer_id hat: 1. Suche auf Stripe nach Kunden mit gleicher E-Mail-Adresse 2. Falls gefunden: Verknüpft den existierenden Stripe-Kunden und updated dessen Daten 3. Falls nicht gefunden: Erstellt einen neuen Stripe-Kunden

Vorteile: - ✅ Vermeidet Duplikate auf Stripe - ✅ Verknüpft automatisch bereits existierende Stripe-Kunden - ✅ Nützlich bei Migrationen oder Re-Importen - ✅ Bessere Datenintegrität

Logging: - Bei gefundenem Kunden: Found existing Stripe customer by email - Bei neuem Kunden: Created new Stripe customer

Auto-Sync Logik

Ohne --force werden nur Kunden synchronisiert: - Die noch keine stripe_customer_id haben - Oder deren stripe_synced_at älter als 24h ist


stripe:sync-products

Synchronisiert ServiceDefinitions als Stripe Products und Prices.

Verwendung

docker-compose exec app php artisan stripe:sync-products [OPTIONS]

Optionen

Option Wert Beschreibung
--force - Synchronisiert alle Products neu
--id service_definition_id Nur bestimmte ServiceDefinitions (mehrfach möglich)

Beispiele

# Alle unsyncten ServiceDefinitions
docker-compose exec app php artisan stripe:sync-products

# Alle neu synchronisieren
docker-compose exec app php artisan stripe:sync-products --force

# Nur ServiceDefinition mit ID 5
docker-compose exec app php artisan stripe:sync-products --id=5

Was wird synchronisiert?

Product: - Name - Beschreibung - Active-Status - Tax Code: txcd_10000000 (Software/Digital Services) - Metadata: service_definition_id, article_number, service_type, billing_cycle

Price: - Amount (in Cents) - Currency: EUR - Tax Behavior: exclusive - Recurring Interval (monthly, quarterly, yearly) - Metadata: service_definition_id, billing_cycle

Billing Cycle Mapping

HostAdmin Stripe Interval
monatlich, 1 month / 1
vierteljaehrlich, 3 month / 3
halbjaehrlich, 6 month / 6
jaehrlich, 12 year / 1
zweijaehrlich, 24 year / 2
einmalig, 0 One-time (kein recurring)

Price Immutability

Wichtig: Stripe Prices sind immutable! Bei Änderungen: 1. Alte Price wird archiviert (active = false) 2. Neue Price wird erstellt 3. stripe_price_id wird aktualisiert

Rate Limiting

Der Command enthält 0.5s Delay zwischen Produkten, um Stripe Rate Limits zu vermeiden.


subscriptions:update-descriptions

Aktualisiert die Beschreibungen (Namen) aller Subscriptions in Stripe.

Verwendung

docker-compose exec app php artisan subscriptions:update-descriptions

Was passiert?

  • Für jede Subscription in HostAdmin:
  • Name wird aus Subscription + Items generiert
  • Name wird zu Stripe hochgeladen
  • Macht Subscriptions in Stripe lesbarer

Beispiel-Output

Vorher: sub_1ABC123 Nachher: Hosting Pro (10001) - 3 Services


Utility Commands

Manuelles Verknüpfen eines HostAdmin-Kunden mit einem Stripe Customer.

Verwendung

docker-compose exec app php artisan customer:link-stripe {customer_id} {stripe_customer_id}

Beispiel

# Verknüpfe HostAdmin Kunde 123 mit Stripe Customer cus_ABC123
docker-compose exec app php artisan customer:link-stripe 123 cus_ABC123

Wann nutzen?

  • Nach manueller Erstellung in Stripe
  • Bei Migrationen
  • Zur Fehlerkorrektur

Automatisierung

Scheduled Commands

In routes/console.php konfiguriert:

Schedule::command('stripe:import-customers')->dailyAt('03:00');

Scheduler aktivieren

Der Scheduler-Container muss laufen:

docker-compose up -d scheduler

Scheduler-Status prüfen

# Liste aller scheduled Tasks
docker-compose exec app php artisan schedule:list

# Scheduler-Logs
docker-compose logs -f scheduler

Custom Schedule

Beispiele für eigene Schedules:

// Wöchentlich statt täglich
Schedule::command('stripe:import-customers')->weekly();

// Nur montags um 3 Uhr
Schedule::command('stripe:import-customers')->mondays()->at('03:00');

// Alle 6 Stunden
Schedule::command('stripe:import-customers')->everySixHours();

// Invoice-Import täglich um 4 Uhr
Schedule::command('stripe:import-invoices --download-pdfs')->dailyAt('04:00');

Best Practices

1. Import-Reihenfolge

Für einen vollständigen Import von Stripe:

# 1. Kunden importieren
docker-compose exec app php artisan stripe:import-customers

# 2. Produkte synchronisieren (falls nötig)
docker-compose exec app php artisan stripe:sync-products

# 3. Subscriptions importieren
docker-compose exec app php artisan stripe:import-subscriptions

# 4. Subscription Items importieren
docker-compose exec app php artisan stripe:import-subscription-items --create-services

# 5. Rechnungen importieren
docker-compose exec app php artisan stripe:import-invoices --download-pdfs

2. Immer erst Dry-Run

Bei jedem Command mit --dry-run Option:

docker-compose exec app php artisan stripe:import-customers --dry-run

3. Monitoring

Logs überwachen während laufender Imports:

# Application Logs
docker-compose exec app tail -f storage/logs/laravel.log

# Scheduler Logs
docker-compose logs -f scheduler

# Queue Logs (falls Queue genutzt wird)
docker-compose logs -f queue

4. Settings prüfen

Vor Stripe-Operations:

docker-compose exec app php artisan tinker

# Stripe-Konfiguration prüfen
>>> config('services.stripe.secret')
>>> config('services.stripe.webhook_secret')

# Settings prüfen
>>> setting('stripe_download_invoice_pdf')
>>> setting('billing_use_stripe_invoices')

5. Fehlerbehandlung

Bei Fehlern:

  1. Logs prüfen: storage/logs/laravel.log
  2. Stripe Dashboard: Überprüfen ob Daten in Stripe korrekt sind
  3. Metadata prüfen: In Stripe Dashboard → Customer/Subscription → Metadata
  4. Command wiederholen: Meistens idempotent

6. Performance

Bei großen Datenmengen:

  • Invoices: --from und --to nutzen für zeitliche Begrenzung
  • Customers: In Batches via --id importieren
  • PDF-Download: Separat nach Import durchführen wenn zeitkritisch

7. Backup

Vor großen Operationen:

# Database Backup
docker-compose exec hostadmin-db mysqldump -u laravel -p hostadmin > backup.sql

# Oder via phpMyAdmin
# http://localhost:8088

Troubleshooting

Problem: "Stripe API key not configured"

Lösung:

# .env prüfen
grep STRIPE .env

# Sollte enthalten:
# STRIPE_KEY=pk_...
# STRIPE_SECRET=sk_...
# STRIPE_WEBHOOK_SECRET=whsec_...

Problem: "Customer not found"

Ursache: Rechnungs-Import findet Kunden nicht

Lösung:

# Erst Kunden importieren
docker-compose exec app php artisan stripe:import-customers

Problem: "Price already exists"

Ursache: ServiceDefinition wurde mehrfach synchronisiert

Lösung: Ist normal! Alte Price wird archiviert, neue erstellt.

Problem: "Rate limit exceeded"

Ursache: Zu viele API-Requests zu Stripe

Lösung: - Warten und wiederholen - --id Option nutzen für kleinere Batches - Rate Limiting in Code ist bereits aktiv (0.5s delay)

Problem: "Invoice PDF download failed"

Ursache: PDF nicht verfügbar oder S3-Problem

Lösung:

# S3-Konfiguration prüfen
docker-compose exec app php artisan tinker
>>> \Storage::disk('s3')->exists('test.txt')

# MinIO Console prüfen
# http://localhost:9091

Problem: Scheduler läuft nicht

Lösung:

# Scheduler-Container starten
docker-compose up -d scheduler

# Status prüfen
docker-compose ps scheduler

# Logs prüfen
docker-compose logs scheduler


Webhook-Integration

Für automatische Synchronisation via Webhooks siehe: - Webhook-Handler: app/Http/Controllers/Api/StripeWebhookController.php - Webhook-Route: /api/webhooks/stripe

Events: - invoice.finalized → Invoice wird importiert - invoice.paid → Status wird aktualisiert, Payment erstellt - invoice.payment_succeeded → Payment erstellt - invoice.payment_failed → Status auf overdue - customer.subscription.created/updated/deleted → Subscription-Status aktualisiert

Konfiguration in Stripe Dashboard: 1. Developers → Webhooks → Add endpoint 2. URL: https://your-domain.com/api/webhooks/stripe 3. Events auswählen 4. Webhook Secret in .env: STRIPE_WEBHOOK_SECRET=whsec_...


  • Stripe API Docs: https://stripe.com/docs/api
  • Laravel Scheduling: https://laravel.com/docs/scheduling
  • Filament Admin Panel: https://filamentphp.com

Command-Übersicht (Quick Reference)

# === IMPORTS (Stripe → HostAdmin) ===
php artisan stripe:import-customers [--dry-run] [--update-existing]
php artisan stripe:import-subscriptions [--dry-run] [--update-existing]
php artisan stripe:import-invoices [--from=] [--to=] [--status=] [--dry-run] [--download-pdfs]
php artisan stripe:import-subscription-items [--create-services]

# === EXPORTS/SYNC (HostAdmin → Stripe) ===
php artisan stripe:sync-customers [--force] [--id=*] [--no-search]
php artisan stripe:sync-products [--force] [--id=*]
php artisan subscriptions:update-descriptions

# === UTILITIES ===
php artisan customer:link-stripe {customer_id} {stripe_customer_id}

# === SCHEDULER ===
php artisan schedule:list
php artisan schedule:run