validate([ 'package_id' => ['required', 'exists:packages,id'], 'locale' => ['nullable', 'string'], ]); $payload = [ 'package_id' => (int) $validated['package_id'], 'locale' => $validated['locale'] ?? app()->getLocale(), ]; $request->session()->put(self::SESSION_KEY, $payload); $request->session()->put('selected_package_id', $payload['package_id']); return Socialite::driver('google') ->scopes(['email', 'profile']) ->with(['prompt' => 'select_account']) ->redirect(); } public function callback(Request $request): RedirectResponse { $payload = $request->session()->get(self::SESSION_KEY, []); $packageId = $payload['package_id'] ?? null; try { $googleUser = Socialite::driver('google')->user(); } catch (\Throwable $e) { Log::warning('Google checkout login failed', ['message' => $e->getMessage()]); $this->flashError($request, __('checkout.google_error_fallback')); return $this->redirectBackToWizard($packageId); } $email = $googleUser->getEmail(); if (! $email) { $this->flashError($request, __('checkout.google_missing_email')); return $this->redirectBackToWizard($packageId); } $user = DB::transaction(function () use ($googleUser, $email) { $existing = User::where('email', $email)->first(); if ($existing) { $existing->forceFill([ 'name' => $googleUser->getName() ?: $existing->name, 'pending_purchase' => true, 'email_verified_at' => $existing->email_verified_at ?? now(), ])->save(); if (! $existing->tenant) { $this->createTenantForUser($existing, $googleUser->getName(), $email); } return $existing->fresh(); } $user = User::create([ 'name' => $googleUser->getName(), 'email' => $email, 'password' => Hash::make(Str::random(32)), 'pending_purchase' => true, 'email_verified_at' => now(), ]); event(new Registered($user)); $tenant = $this->createTenantForUser($user, $googleUser->getName(), $email); try { Mail::to($user) ->locale($user->preferred_locale ?? app()->getLocale()) ->queue(new Welcome($user)); } catch (\Throwable $exception) { Log::warning('Failed to queue welcome mail after Google signup', [ 'user_id' => $user->id, 'error' => $exception->getMessage(), ]); } return tap($user)->setRelation('tenant', $tenant); }); if (! $user->tenant) { $this->createTenantForUser($user, $googleUser->getName(), $email); } Auth::login($user, true); $request->session()->regenerate(); $request->session()->forget(self::SESSION_KEY); $request->session()->put('checkout_google_status', 'success'); if ($packageId) { $this->ensurePackageAttached($user, (int) $packageId); } return $this->redirectBackToWizard($packageId); } private function createTenantForUser(User $user, ?string $displayName, string $email): Tenant { $tenantName = trim($displayName ?: Str::before($email, '@')) ?: 'Fotospiel Tenant'; $slugBase = Str::slug($tenantName) ?: 'tenant'; $slug = $slugBase; $counter = 1; while (Tenant::where('slug', $slug)->exists()) { $slug = $slugBase . '-' . $counter; $counter++; } $tenant = Tenant::create([ 'user_id' => $user->id, 'name' => $tenantName, 'slug' => $slug, 'email' => $email, 'contact_email' => $email, 'is_active' => true, 'is_suspended' => false, 'event_credits_balance' => 0, 'subscription_tier' => 'free', 'subscription_status' => 'free', 'subscription_expires_at' => null, 'settings' => json_encode([ 'branding' => [ 'logo_url' => null, 'primary_color' => '#3B82F6', 'secondary_color' => '#1F2937', 'font_family' => 'Inter, sans-serif', ], 'features' => [ 'photo_likes_enabled' => false, 'event_checklist' => false, 'custom_domain' => false, 'advanced_analytics' => false, ], 'custom_domain' => null, 'contact_email' => $email, 'event_default_type' => 'general', ]), ]); $user->forceFill(['tenant_id' => $tenant->id])->save(); return $tenant; } private function ensurePackageAttached(User $user, int $packageId): void { $tenant = $user->tenant; if (! $tenant) { return; } $package = Package::find($packageId); if (! $package) { return; } if ($tenant->packages()->where('package_id', $packageId)->exists()) { return; } $tenant->packages()->attach($packageId, [ 'price' => $package->price, 'purchased_at' => now(), 'expires_at' => now()->addYear(), 'active' => $package->price <= 0, ]); } private function redirectBackToWizard(?int $packageId): RedirectResponse { if ($packageId) { return redirect()->route('purchase.wizard', ['package' => $packageId]); } $firstPackageId = Package::query()->orderBy('price')->value('id'); if ($firstPackageId) { return redirect()->route('purchase.wizard', ['package' => $firstPackageId]); } return redirect()->route('packages'); } private function flashError(Request $request, string $message): void { $request->session()->flash('checkout_google_error', $message); } }