validated(); $user = Auth::user(); $tenant = $user?->tenant; if (! $tenant) { throw ValidationException::withMessages(['tenant' => 'Tenant context missing.']); } $package = Package::findOrFail((int) $data['package_id']); if (! $package->paddle_price_id) { throw ValidationException::withMessages(['package_id' => 'Package is not linked to a Paddle price.']); } $session = $this->sessions->createOrResume($user, $package, array_merge( CheckoutRequestContext::fromRequest($request), [ 'tenant' => $tenant, ] )); $this->sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE); $now = now(); $session->forceFill([ 'accepted_terms_at' => $now, 'accepted_privacy_at' => $now, 'accepted_withdrawal_notice_at' => $now, 'digital_content_waiver_at' => null, 'legal_version' => $this->resolveLegalVersion(), ])->save(); $couponCode = Str::upper(trim((string) ($data['coupon_code'] ?? ''))); $discountId = null; if ($couponCode !== '') { $preview = $this->coupons->preview($couponCode, $package, $tenant); $this->sessions->applyCoupon($session, $preview['coupon'], $preview['pricing']); $discountId = $preview['coupon']->paddle_discount_id; } if ($request->boolean('inline') && $discountId === null) { $metadata = array_merge($session->provider_metadata ?? [], [ 'mode' => 'inline', ]); $session->forceFill([ 'provider_metadata' => $metadata, ])->save(); return response()->json([ 'checkout_session_id' => $session->id, 'mode' => 'inline', 'items' => [ [ 'priceId' => $package->paddle_price_id, 'quantity' => 1, ], ], 'custom_data' => [ 'tenant_id' => (string) $tenant->id, 'package_id' => (string) $package->id, 'checkout_session_id' => (string) $session->id, 'legal_version' => $session->legal_version, 'accepted_terms' => '1', ], 'customer' => array_filter([ 'email' => $user->email, 'name' => trim(($user->first_name ?? '').' '.($user->last_name ?? '')) ?: ($user->name ?? null), ]), ]); } $checkout = $this->checkout->createCheckout($tenant, $package, [ 'success_url' => $data['success_url'] ?? null, 'return_url' => $data['return_url'] ?? null, 'metadata' => [ 'checkout_session_id' => $session->id, 'coupon_code' => $couponCode ?: null, 'legal_version' => $session->legal_version, 'accepted_terms' => true, ], 'discount_id' => $discountId, ]); $session->forceFill([ 'paddle_checkout_id' => $checkout['id'] ?? $session->paddle_checkout_id, 'provider_metadata' => array_merge($session->provider_metadata ?? [], array_filter([ 'paddle_checkout_id' => $checkout['id'] ?? null, 'paddle_checkout_url' => $checkout['checkout_url'] ?? null, 'paddle_expires_at' => $checkout['expires_at'] ?? null, ])), ])->save(); return response()->json(array_merge($checkout, [ 'checkout_session_id' => $session->id, ])); } protected function resolveLegalVersion(): string { return config('app.legal_version', now()->toDateString()); } }