Files
fotospiel-app/docs/prp/08-billing.md
Codex Agent d04e234ca0 - Tenant-Admin-PWA: Neues /event-admin/welcome Onboarding mit WelcomeHero, Packages-, Order-Summary- und Event-Setup-Pages, Zustandsspeicher, Routing-Guard und Dashboard-CTA für Erstnutzer; Filament-/admin-Login via Custom-View behoben.
- Brand/Theming: Marketing-Farb- und Typographievariablen in `resources/css/app.css` eingeführt, AdminLayout, Dashboardkarten und Onboarding-Komponenten entsprechend angepasst; Dokumentation (`docs/todo/tenant-admin-onboarding-fusion.md`, `docs/changes/...`) aktualisiert.
- Checkout & Payments: Checkout-, PayPal-Controller und Tests für integrierte Stripe/PayPal-Flows sowie Paket-Billing-Abläufe überarbeitet; neue PayPal SDK-Factory und Admin-API-Helper (`resources/js/admin/api.ts`) schaffen Grundlage für Billing/Members/Tasks-Seiten.
- DX & Tests: Neue Playwright/E2E-Struktur (docs/testing/e2e.md, `tests/e2e/tenant-onboarding-flow.test.ts`, Utilities), E2E-Tenant-Seeder und zusätzliche Übersetzungen/Factories zur Unterstützung der neuen Flows.
- Marketing-Kommunikation: Automatische Kontakt-Bestätigungsmail (`ContactConfirmation` + Blade-Template) implementiert; Guest-PWA unter `/event` erreichbar.
- Nebensitzung: Blogsystem gefixt und umfassenden BlogPostSeeder für Beispielinhalte angelegt.
2025-10-10 21:31:55 +02:00

5.2 KiB

Billing and Payments

Overview

The Fotospiel platform supports multiple payment providers for package purchases: Stripe for one-time and subscription payments, and PayPal for orders and subscriptions. Billing is handled through a freemium model with endcustomer event packages and reseller subscriptions. All payments are processed via API integrations, with webhooks for asynchronous updates.

Stripe Integration

  • One-time Payments: Use Stripe Checkout for endcustomer event packages. Create PaymentIntent via StripeController@createPaymentIntent.
  • Subscriptions: Reseller subscriptions use Stripe Subscriptions API. Webhook handling in StripeWebhookController@handleWebhook for events like invoice.paid, customer.subscription.deleted.
  • Configuration: Keys in config/services.php under stripe. Sandbox mode based on APP_ENV.
  • Models: PackagePurchase records all transactions with provider_id (Stripe PI ID), status, metadata.
  • Frontend: PurchaseWizard.tsx handles client-side Stripe Elements for card input and confirmation.

PayPal Integration

  • SDK: Migrated to PayPal Server SDK v1.0+ (paypal/paypal-server-sdk). Uses Builder pattern for requests and Controllers for API calls.
  • Orders (One-time Payments): Endcustomer event packages via Orders API. PayPalController@createOrder uses OrderRequestBuilder with CheckoutPaymentIntent::CAPTURE, custom_id for metadata (tenant_id, package_id, type). Capture in @captureOrder using OrdersController->captureOrder. DB creation in processPurchaseFromOrder.
  • Subscriptions (Recurring Payments): Reseller subscriptions via Orders API with StoredPaymentSource for recurring setup (no dedicated SubscriptionsController in SDK). PayPalController@createSubscription uses OrderRequestBuilder with StoredPaymentSource (payment_initiator: CUSTOMER, payment_type: RECURRING, usage: FIRST), custom_id including plan_id. Initial order capture sets up subscription; subsequent billing via PayPal dashboard or webhooks. DB records created on initial capture, with expires_at for annual billing.
  • Differences: One-time: Standard Order with payment_type ONE_TIME (default). Recurring: Order with StoredPaymentSource RECURRING to enable future charges without new approvals. plan_id stored in metadata for reference; no separate subscription ID from SDK.
  • Client Setup: OAuth2 Client Credentials flow. Builder: PaypalServerSdkClientBuilder::init()->clientCredentialsAuthCredentials(ClientCredentialsAuthCredentialsBuilder::init(client_id, secret))->environment(Environment::SANDBOX/PRODUCTION)->build().
  • Webhooks: PayPalWebhookController@verify handles events like PAYMENT.CAPTURE.COMPLETED (process initial/renewal purchase), BILLING.SUBSCRIPTION.CANCELLED or equivalent order events (deactivate package). Simplified signature verification (TODO: Implement VerifyWebhookSignature).
  • Idempotency: Check provider_id in PackagePurchase before creation. Transactions for DB safety.
  • Configuration: Keys in config/services.php under paypal. Sandbox mode via paypal.sandbox.
  • Migration Notes: Replaced old Checkout SDK (PayPalCheckoutSdk). Updated imports, requests (e.g., OrdersCreateRequest -> OrderRequestBuilder, Subscriptions -> StoredPaymentSource in Orders). Responses: Use getStatusCode() and getResult(). Tests mocked new structures. No breaking changes in auth or metadata handling; recurring flows now unified under Orders API.

Database Models

  • PackagePurchase: Records purchases with tenant_id, package_id, provider_id (Stripe PI/PayPal Order ID), price, type (endcustomer_event/reseller_subscription), status (completed/refunded), metadata (JSON with provider details).
  • TenantPackage: Active packages with tenant_id, package_id, price, purchased_at, expires_at, active flag. Updated on purchase/cancellation.
  • Constraints: type CHECK (endcustomer_event, reseller_subscription), price NOT NULL.

Flows

  1. Purchase Initiation: User selects package in PurchaseWizard. For free: direct assignment. Paid: Redirect to provider (Stripe Checkout or PayPal approve link).
  2. Completion: Provider callback/webhook triggers capture/confirmation. Create PackagePurchase and TenantPackage. Update tenant subscription_status to 'active'.
  3. Cancellation/Refund: Webhook updates status to 'cancelled', deactivates TenantPackage.
  4. Trial: First reseller subscription gets 14-day trial (expires_at = now() + 14 days).

Error Handling

  • Validation: Request validation for IDs, consent.
  • API Errors: Catch exceptions, log, return 400/500 JSON.
  • Idempotency: Prevent duplicate processing.
  • Webhook: Verify signature, handle unhandled events with logging.

Testing

  • Unit: Mock providers in PurchaseTest.php for order creation, capture, webhooks.
  • Integration: Sandbox keys for end-to-end. Assertions on DB state, responses.
  • Edge Cases: Failures, idempotency, trials, limits.

Security & Compliance

  • GDPR: No PII in logs/metadata beyond necessary (tenant_id anonymous).
  • Auth: Sanctum tokens for API, CSRF for web.
  • Webhooks: IP whitelisting (PayPal IPs), signature verification.
  • Retention: Purchases retained per Privacy policy; update on changes.