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>
48 lines
1.8 KiB
PHP
48 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace App\Mail;
|
|
|
|
use App\Models\UserAbo;
|
|
use App\Services\AboPaymentMethodService;
|
|
use App\Services\Util;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Mail\Mailable;
|
|
use Illuminate\Queue\SerializesModels;
|
|
|
|
class AboCardUpdateLinkMail extends Mailable
|
|
{
|
|
use Queueable, SerializesModels;
|
|
|
|
public function __construct(public UserAbo $userAbo, public string $token) {}
|
|
|
|
public function build(): self
|
|
{
|
|
$firstname = $this->userAbo->shopping_user?->billing_firstname;
|
|
$salutation = $firstname ? __('email.hello').' '.$firstname : __('email.hello');
|
|
|
|
// Link zeigt immer auf das Kundenportal (in.mivita.care), unabhängig vom Versand-Kontext.
|
|
$link = rtrim(Util::getMyMivitaPortalUrl(), '/').'/abo/karte/'.$this->token;
|
|
|
|
// Texte je Flow: Stripe = freie Zahlartenwahl (Plan S5), PAYONE-Legacy = Kreditkarte.
|
|
$stripeChange = app(AboPaymentMethodService::class)->usesStripeChange();
|
|
$subject = $stripeChange
|
|
? __('abo.payment_method_change_link_mail_subject')
|
|
: __('abo.card_update_link_mail_subject');
|
|
|
|
return $this->subject($subject)
|
|
->view('emails.abo_card_update_link')
|
|
->with([
|
|
'salutation' => $salutation,
|
|
'link' => $link,
|
|
'mailTitle' => $subject,
|
|
'mailIntro' => $stripeChange
|
|
? __('abo.payment_method_change_link_mail_intro')
|
|
: __('abo.card_update_link_mail_intro'),
|
|
'mailButton' => $stripeChange
|
|
? __('abo.payment_method_change_link_mail_button')
|
|
: __('abo.card_update_link_mail_button'),
|
|
'greetings' => __('email.greetings'),
|
|
'sender' => __('email.sender'),
|
|
]);
|
|
}
|
|
}
|