Abo-Recovery: fehlgeschlagene Folgezahlung im Checkout nachholen
- Pay-now-Flow: bei fehlgeschlagenem Abo (Status 3) begleicht der Inhaber die offene Rechnung im Standard-Checkout mit frei waehlbarer, abo-faehiger Zahlart (nur eigenes Abo: Berater me-View + Kundenportal), payNow-Controller + Routen - AboRecoveryCheckoutService baut die ShoppingInstance aus den Abo-Artikeln; neue Spalte shopping_orders.recovery_user_abo_id verknuepft Bestellung<->Abo - Bei Erfolg: AboHelper::advanceAboAfterRecoveryPayment schreibt das Abo fort (Status->2, next_date) und uebernimmt die gewaehlte Zahlart als neues Token fuer kuenftige Abbuchungen - Neue Pay-now-Fehlermail (AboPaymentFailedMail) ersetzt die generische Fehlermail im Abo-Cron; Link fuehrt auf die Abo-Detailseite (CRM bzw. Portal) - Retry-/"extern erledigt"-Buttons nur noch fuer Admins; tote user/portal- Retry-Routen entfernt - Checkout: Recovery-Hinweis statt "Abschluss des Abonnements", Lieferadresse vorbelegt, korrekter Zurueck-Link (Abo statt Shop) - UserAbo::selfServiceDetailUrl zentralisiert die Abo-URL (Mail, Back-Links) - Test-Command abo:test-recovery; Tests fuer payNow, Advance-Logik, Fehlermail Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
78db952130
commit
0660f4e0a0
28 changed files with 1535 additions and 181 deletions
|
|
@ -58,6 +58,7 @@ class CheckoutController extends Controller
|
|||
$is_for = $shopping_data['is_for'] ?? false;
|
||||
$is_abo = isset($shopping_data['is_abo']) ? (bool) $shopping_data['is_abo'] : false;
|
||||
$abo_interval = $shopping_data['abo_interval'] ?? 0;
|
||||
$recovery_user_abo_id = $shopping_data['recovery_user_abo_id'] ?? null;
|
||||
$homeparty_id = $shopping_data['homeparty_id'] ?? null;
|
||||
$shopping_user = null;
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ class CheckoutController extends Controller
|
|||
'is_for' => $is_for,
|
||||
'is_abo' => $is_abo,
|
||||
'abo_interval' => $abo_interval,
|
||||
'recovery_user_abo_id' => $recovery_user_abo_id,
|
||||
'customer_order_source_options' => ShoppingOrder::customerOrderSourceOptions(),
|
||||
'shopping_data' => $shopping_data,
|
||||
'user_shop' => Util::getUserShop(),
|
||||
|
|
@ -522,8 +524,10 @@ class CheckoutController extends Controller
|
|||
$this->checkoutRepo->sessionDestroy(true);
|
||||
Util::setInstanceStatus(3, true); // link_pending
|
||||
|
||||
// Abo erstellen, falls nötig
|
||||
if ($ShoppingPayment->shopping_order->is_abo) {
|
||||
// Abo erstellen bzw. bei Recovery-Zahlung das bestehende Abo fortschreiben
|
||||
if ($ShoppingPayment->shopping_order->recovery_user_abo_id) {
|
||||
AboHelper::advanceAboAfterRecoveryPayment($ShoppingPayment);
|
||||
} elseif ($ShoppingPayment->shopping_order->is_abo) {
|
||||
AboHelper::createNewAbo($ShoppingPayment);
|
||||
}
|
||||
|
||||
|
|
@ -534,6 +538,7 @@ class CheckoutController extends Controller
|
|||
'pay_trans' => $payt,
|
||||
'is_checkout' => true,
|
||||
'yard_instance' => $this->instance,
|
||||
'back_url' => $this->recoveryBackUrl($ShoppingPayment->shopping_order),
|
||||
];
|
||||
|
||||
return view('web.templates.checkout-final', $data);
|
||||
|
|
@ -562,8 +567,10 @@ class CheckoutController extends Controller
|
|||
$this->checkoutRepo->sessionDestroy(true);
|
||||
Util::setInstanceStatus(3, true); // link_pending
|
||||
|
||||
// Abo erstellen, falls nötig
|
||||
if ($payt->shopping_payment->shopping_order->is_abo) {
|
||||
// Abo erstellen bzw. bei Recovery-Zahlung das bestehende Abo fortschreiben
|
||||
if ($payt->shopping_payment->shopping_order->recovery_user_abo_id) {
|
||||
AboHelper::advanceAboAfterRecoveryPayment($payt->shopping_payment);
|
||||
} elseif ($payt->shopping_payment->shopping_order->is_abo) {
|
||||
AboHelper::createNewAbo($payt->shopping_payment);
|
||||
}
|
||||
|
||||
|
|
@ -578,11 +585,25 @@ class CheckoutController extends Controller
|
|||
'pay_trans' => $payt,
|
||||
'is_checkout' => true,
|
||||
'yard_instance' => $this->instance,
|
||||
'back_url' => $this->recoveryBackUrl($payt->shopping_payment->shopping_order),
|
||||
];
|
||||
|
||||
return view('web.templates.checkout-final', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Back-Link auf der Bestätigungsseite: bei einer Recovery-Zahlung zurück auf die Abo-Detailseite
|
||||
* (Berater-CRM bzw. Kundenportal), sonst null → das Blade fällt auf den Shop-Back-Link zurück.
|
||||
*/
|
||||
private function recoveryBackUrl($shoppingOrder): ?string
|
||||
{
|
||||
if (! $shoppingOrder || ! $shoppingOrder->recovery_user_abo_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \App\Models\UserAbo::find($shoppingOrder->recovery_user_abo_id)?->selfServiceDetailUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert die Zahlungsdaten des Benutzers
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue