Phase S4 – Abos über Stripe (E2E komplett im Testmodus): - Abo-/Recovery-Checkout: customer_creation=always + setup_future_usage=off_session - StripePaymentService::chargeAbo (off-session PaymentIntent, Idempotency-Key), StripeGateway, Provider-Dispatch im Abbuchungs-Cron (PAYONE-Pfad unverändert) - Webhook: Zahlungsmittel-Capture vor Paid-Pfad, 503 payment_not_yet_visible bei Cron-Transaktions-Race; Command stripe:process-pending-events (Cron-Ende + 10-min Scheduler) verarbeitet liegengebliebene Events nach - createNewAbo/advanceAboAfterRecoveryPayment Stripe-aware inkl. Race-Absicherung; Recovery-Orders nutzen advanceAboAfterRecoveryPayment (latenter PAYONE-Duplikat-Bug) - Migrationen: Stripe-Abo-Spalten auf shopping_payments; clearingtype varchar(3)→(20) inkl. Reparatur der zu 'str' gekürzten Live-Zeilen Phase S5 – Zahlungsart ändern (Scope: jede Zahlart, nicht nur Kreditkarte): - Stripe Checkout mode=setup ohne Abbuchung; PAYONE-Abos ziehen beim Wechsel auf Stripe um (Auslaufmodell §7.2) - AboPaymentMethodService: beginStripeChange/finalize/applyStripePaymentMethod (idempotent, detacht alte PM, card_changes-Log); Webhook setup_intent.succeeded als Sicherheitsnetz; Einstiege Portal/CRM/Berater-Kunden-Link flow-abhängig - Views/Mails flow-abhängig („Zahlungsweise" statt „Kreditkarte") Phase S7.6 – Zahlarten-Kommunikation: - Einheitliche Zahlarten-Logos (SVG) + wiederverwendbares Partial payment_logos; Checkout/Footer zeigen Kern-Zahlarten + „···"-Icon, /zahlungsarten komplett neu mit allen aktiven Stripe-Zahlarten (gegen Account-Konfiguration verifiziert) und Vorkasse (PAYONE); Sofort/SEPA entfernt Tests: StripeAboTest (15), StripePaymentMethodChangeTest (10), PaymentMethodsCommunicationTest (28), PaymentProviderManagerTest angepasst. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
89 lines
3 KiB
PHP
89 lines
3 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Payment;
|
|
|
|
use App\Enums\PaymentProvider;
|
|
use App\Models\Setting;
|
|
use App\Models\ShoppingPayment;
|
|
use App\Models\UserAbo;
|
|
use App\Services\Payment\Contracts\PaymentGatewayInterface;
|
|
|
|
/**
|
|
* Zentrale Anbieter-Auflösung (dev/2026-07-08-stripe/, Konzept §4):
|
|
*
|
|
* - Neue Zahlungsvorgänge folgen dem Einstellungs-Schalter (Setting-Slug
|
|
* `payment-active-provider`).
|
|
* - Bestehende Zahlungen/Abos folgen IMMER ihrer eigenen
|
|
* `payment_provider`-Spalte — der Schalter wirkt nie rückwirkend.
|
|
* - Unbekannte/fehlende Werte fallen sicher auf PAYONE zurück
|
|
* (Bestandsverhalten vor der Stripe-Einführung).
|
|
*/
|
|
class PaymentProviderManager
|
|
{
|
|
public const SETTING_SLUG = 'payment-active-provider';
|
|
|
|
public const SETTING_VORKASSE_HIDDEN = 'payment-vorkasse-hidden';
|
|
|
|
public const SETTING_ABO_PAYMENTS_FROZEN = 'abo-payments-frozen';
|
|
|
|
public const SETTING_CHECKOUT_MAINTENANCE = 'checkout-maintenance';
|
|
|
|
/**
|
|
* Anbieter für neue Checkouts, neue Abos und neue Zahlungslinks.
|
|
*/
|
|
public function providerForNewCheckout(): PaymentProvider
|
|
{
|
|
$configured = Setting::getContentBySlug(self::SETTING_SLUG);
|
|
|
|
return PaymentProvider::tryFrom(is_string($configured) ? $configured : '')
|
|
?? PaymentProvider::Payone;
|
|
}
|
|
|
|
/**
|
|
* Anbieter eines bestehenden Vorgangs — schalterunabhängig.
|
|
*/
|
|
public function providerFor(UserAbo|ShoppingPayment $subject): PaymentProvider
|
|
{
|
|
return PaymentProvider::tryFrom((string) $subject->payment_provider)
|
|
?? PaymentProvider::Payone;
|
|
}
|
|
|
|
/**
|
|
* Sichtbarkeit der Vorkasse im Checkout (N3, 2026-07-08): Vorkasse läuft
|
|
* über PAYONE und ist über eine eigene Einstellung ausblendbar —
|
|
* unabhängig vom Provider-Schalter. Fehlende Einstellung = sichtbar.
|
|
*/
|
|
public function isVorkasseVisible(): bool
|
|
{
|
|
return Setting::getContentBySlug(self::SETTING_VORKASSE_HIDDEN) !== true;
|
|
}
|
|
|
|
/**
|
|
* Not-Schalter (2026-07-08, PAYONE-Ausfall): friert ALLE Abo-Zahlungen ein —
|
|
* Abo-Checkout, Recovery, Retry und den Abbuchungs-Cron. Einmalzahlungen
|
|
* (Stripe) laufen weiter. Wird nach Phase S4 (Abos über Stripe) aufgehoben.
|
|
*/
|
|
public function aboPaymentsFrozen(): bool
|
|
{
|
|
return Setting::getContentBySlug(self::SETTING_ABO_PAYMENTS_FROZEN) === true;
|
|
}
|
|
|
|
/**
|
|
* Checkout-Wartungsmodus: Nicht-Admins sehen im Checkout nur eine
|
|
* "Technische Schwierigkeiten"-Meldung; Admins können normal bestellen.
|
|
* Zweck: Stripe im Live-Modus verproben, bevor der Checkout für alle
|
|
* wieder öffnet (Go-Live 2026-07-08).
|
|
*/
|
|
public function checkoutMaintenanceActive(): bool
|
|
{
|
|
return Setting::getContentBySlug(self::SETTING_CHECKOUT_MAINTENANCE) === true;
|
|
}
|
|
|
|
public function gateway(PaymentProvider $provider): PaymentGatewayInterface
|
|
{
|
|
return match ($provider) {
|
|
PaymentProvider::Payone => app(PayoneGateway::class),
|
|
PaymentProvider::Stripe => app(StripeGateway::class),
|
|
};
|
|
}
|
|
}
|