$changes */ public function syncAfterUpdate(Plan $plan, array $changes): void { if (! $this->isConfigured()) { return; } $stripe = Cashier::stripe(); if (! $plan->stripe_product_id) { $this->createProductWithPrices($stripe, $plan); return; } if (array_key_exists('name', $changes)) { $stripe->products->update($plan->stripe_product_id, ['name' => $plan->name]); } if (array_key_exists('monthly_price_cents', $changes)) { $plan->forceFill([ 'stripe_price_id_monthly' => $this->rotatePrice( $stripe, $plan, $plan->stripe_price_id_monthly, $plan->monthly_price_cents, 'month', ), ])->save(); } if (array_key_exists('yearly_price_cents', $changes)) { $plan->forceFill([ 'stripe_price_id_yearly' => $this->rotatePrice( $stripe, $plan, $plan->stripe_price_id_yearly, $plan->yearly_price_cents, 'year', ), ])->save(); } } /** * Erstanlage für Tarife ohne Stripe-Verknüpfung — gleiche Struktur wie * `billing:sync-stripe-plans`, nur direkt aus der Admin-Oberfläche. */ private function createProductWithPrices(StripeClient $stripe, Plan $plan): void { $product = $stripe->products->create([ 'name' => $plan->name, 'metadata' => ['plan_slug' => $plan->slug], ]); $plan->forceFill([ 'stripe_product_id' => $product->id, 'stripe_price_id_monthly' => $this->createPrice($stripe, $product->id, $plan, $plan->monthly_price_cents, 'month'), 'stripe_price_id_yearly' => $this->createPrice($stripe, $product->id, $plan, $plan->yearly_price_cents, 'year'), ])->save(); } /** * Neuen Preis anlegen und den bisherigen (falls vorhanden) für neue * Buchungen deaktivieren. Gibt die neue Price-ID zurück. */ private function rotatePrice(StripeClient $stripe, Plan $plan, ?string $oldPriceId, int $unitAmount, string $interval): string { $newPriceId = $this->createPrice($stripe, (string) $plan->stripe_product_id, $plan, $unitAmount, $interval); if ($oldPriceId) { $stripe->prices->update($oldPriceId, ['active' => false]); } return $newPriceId; } private function createPrice(StripeClient $stripe, string $productId, Plan $plan, int $unitAmount, string $interval): string { $price = $stripe->prices->create([ 'product' => $productId, 'currency' => strtolower($plan->currency), 'unit_amount' => $unitAmount, 'tax_behavior' => 'exclusive', 'recurring' => ['interval' => $interval], 'metadata' => ['plan_slug' => $plan->slug], ]); return $price->id; } }