Buchungsseite: Buchungs- und Verlaengerungsdatum des Abos aus Stripe

Cashier spiegelt die Periode nicht lokal; neuer SubscriptionPeriodResolver
holt start_date + current_period_end (Item-Ebene) gecacht, Fallback null.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-09 15:34:28 +00:00
parent 75d7baab2a
commit c2ec18be5f
3 changed files with 140 additions and 0 deletions

View file

@ -0,0 +1,47 @@
<?php
namespace App\Services\Billing;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Laravel\Cashier\Subscription;
use Throwable;
/**
* Ermittelt Buchungs- und Verlängerungsdatum eines echten Stripe-Abos.
*
* Cashier v15 spiegelt die Abrechnungsperiode nicht lokal in die
* `subscriptions`-Tabelle; in der aktuellen Stripe-API liegt
* `current_period_end` zudem auf Item-Ebene. Deshalb ein einmaliger,
* kurz gecachter Stripe-Abruf (überlebt Livewire-Re-Renders, invalidiert
* bei jeder Abo-Änderung über `updated_at`). Bei Netzwerk-/API-Fehlern
* wird still `null` zurückgegeben, damit die Buchungsseite immer rendert.
*/
class SubscriptionPeriodResolver
{
/**
* @return array{booked_at: Carbon, renews_at: Carbon}|null
*/
public function resolve(Subscription $subscription): ?array
{
$cacheKey = "subscription-period:{$subscription->stripe_id}:".($subscription->updated_at?->timestamp ?? 0);
return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($subscription): ?array {
try {
$stripe = $subscription->asStripeSubscription();
$renewsAt = $stripe->items->data[0]->current_period_end ?? null;
if (! $renewsAt) {
return null;
}
return [
'booked_at' => Carbon::createFromTimestamp($stripe->start_date),
'renews_at' => Carbon::createFromTimestamp($renewsAt),
];
} catch (Throwable) {
return null;
}
});
}
}