error('STRIPE_SECRET ist nicht gesetzt.'); return self::FAILURE; } $dryRun = (bool) $this->option('dry-run'); $stripe = Cashier::stripe(); foreach (Plan::query()->active()->get() as $plan) { if ($plan->stripe_product_id && $plan->stripe_price_id_monthly && $plan->stripe_price_id_yearly) { $this->line("{$plan->slug}: vollständig verknüpft, übersprungen."); continue; } if ($dryRun) { $this->line(sprintf( '[dry-run] %s: Produkt + Preise %s €/Monat, %s €/Jahr (netto) anlegen.', $plan->slug, number_format($plan->monthly_price_cents / 100, 2, ',', '.'), number_format($plan->yearly_price_cents / 100, 2, ',', '.'), )); continue; } $productId = $plan->stripe_product_id; if (! $productId) { $product = $stripe->products->create([ 'name' => $plan->name, 'metadata' => ['plan_slug' => $plan->slug], ]); $productId = $product->id; } $monthlyId = $plan->stripe_price_id_monthly ?: $this->createPrice($stripe, $productId, $plan, $plan->monthly_price_cents, 'month'); $yearlyId = $plan->stripe_price_id_yearly ?: $this->createPrice($stripe, $productId, $plan, $plan->yearly_price_cents, 'year'); $plan->update([ 'stripe_product_id' => $productId, 'stripe_price_id_monthly' => $monthlyId, 'stripe_price_id_yearly' => $yearlyId, ]); $this->info("{$plan->slug}: {$productId} · monatlich {$monthlyId} · jährlich {$yearlyId}"); } return self::SUCCESS; } private function createPrice(object $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; } }