subscription = $subscription; $this->sessionToken = $sessionToken; // Validate that we have a subscription to check if (! $this->subscription) { Log::warning('PaymentConfirmation: No subscription provided', [ 'user_id' => auth()->id(), 'session_token' => $sessionToken, ]); $this->status = 'error'; $this->errorMessage = 'No subscription found for this payment session.'; return; } // Validate subscription belongs to current user if ($this->subscription->user_id !== auth()->id()) { Log::warning('PaymentConfirmation: Subscription does not belong to current user', [ 'user_id' => auth()->id(), 'subscription_user_id' => $this->subscription->user_id, 'subscription_id' => $this->subscription->id, ]); $this->status = 'error'; $this->errorMessage = 'Invalid subscription for this user.'; return; } Log::info('PaymentConfirmation: Mounted with subscription', [ 'user_id' => auth()->id(), 'subscription_id' => $this->subscription->id, 'provider' => $this->subscription->provider, 'provider_subscription_id' => $this->subscription->provider_subscription_id, 'current_status' => $this->subscription->status, 'created_at' => $this->subscription->created_at, 'minutes_ago' => $this->subscription->created_at->diffInMinutes(now()), ]); // Initial status check $this->checkSubscriptionStatus(); // Debug: If subscription is already active, show confetti immediately if ($this->subscription && $this->subscription->status === 'active') { $this->status = 'activated'; $this->showConfetti = true; $this->pollCount = $this->maxPolls; Log::info('PaymentConfirmation: Active subscription detected, showing confetti immediately', [ 'subscription_id' => $this->subscription->id, 'status' => $this->subscription->status, ]); } } /** * Check subscription status via payment provider */ public function checkSubscriptionStatus(): void { if (! $this->subscription || $this->pollCount >= $this->maxPolls) { if ($this->pollCount >= $this->maxPolls) { Log::info('PaymentConfirmation: Max polls reached, redirecting to dashboard', [ 'subscription_id' => $this->subscription?->id, 'poll_count' => $this->pollCount, ]); $this->redirect(route('dashboard')); } return; } // Increment poll count first $this->pollCount++; try { $orchestrator = app(PaymentOrchestrator::class); $user = auth()->user(); Log::info('PaymentConfirmation: Checking subscription status', [ 'subscription_id' => $this->subscription->id, 'provider_subscription_id' => $this->subscription->provider_subscription_id, 'provider' => $this->subscription->provider, 'poll_count' => $this->pollCount, ]); // Check status via provider (only if we have a provider subscription ID) if (empty($this->subscription->provider_subscription_id)) { Log::info('PaymentConfirmation: Skipping provider status check - no provider subscription ID yet', [ 'subscription_id' => $this->subscription->id, 'provider' => $this->subscription->provider, 'provider_checkout_id' => $this->subscription->provider_checkout_id, 'poll_count' => $this->pollCount, ]); // Don't update status, just continue polling return; } $statusResult = $orchestrator->checkSubscriptionStatus( $user, $this->subscription->provider, $this->subscription->provider_subscription_id ); if ($statusResult['success']) { $providerStatus = $statusResult['status']; Log::info('PaymentConfirmation: Provider status received', [ 'provider_status' => $providerStatus, 'subscription_id' => $this->subscription->id, ]); // Update local subscription if status changed if ($providerStatus !== $this->subscription->status) { $this->subscription->status = $providerStatus; $this->subscription->save(); Log::info('PaymentConfirmation: Updated local subscription status', [ 'old_status' => $this->subscription->getOriginal('status'), 'new_status' => $providerStatus, ]); } // Check if subscription is now active if ($providerStatus === 'active') { $this->status = 'activated'; $this->showConfetti = true; // Stop polling when activated $this->pollCount = $this->maxPolls; Log::info('PaymentConfirmation: Subscription activated successfully', [ 'subscription_id' => $this->subscription->id, ]); return; } } else { // Handle status check failure Log::warning('PaymentConfirmation: Provider status check failed', [ 'error' => $statusResult['error'] ?? 'Unknown error', 'subscription_id' => $this->subscription->id, 'retry_suggested' => $statusResult['retry_suggested'] ?? false, ]); // If retry is suggested (e.g., webhook not processed yet), continue polling if (! ($statusResult['retry_suggested'] ?? false)) { // If retry is not suggested, we might want to show an error // but for now, continue polling to be safe } } // Continue polling if not active and max polls not reached if ($this->pollCount < $this->maxPolls) { $this->status = 'verifying'; } else { // Max polls reached, check final status $this->status = in_array($this->subscription->status, ['active', 'trialing']) ? 'activated' : 'pending'; Log::info('PaymentConfirmation: Max polls reached, final status determined', [ 'final_status' => $this->status, 'subscription_status' => $this->subscription->status, ]); } } catch (\Exception $e) { Log::error('PaymentConfirmation: Error checking subscription status', [ 'subscription_id' => $this->subscription->id, 'error' => $e->getMessage(), 'poll_count' => $this->pollCount, ]); // Don't immediately set error status, continue trying unless max polls reached if ($this->pollCount >= $this->maxPolls) { $this->errorMessage = 'Unable to verify payment status after multiple attempts. Please check your subscription page.'; $this->status = 'error'; } } } /** * Get polling interval in milliseconds */ public function getPollingIntervalProperty(): int { return 30000; // 30 seconds } /** * Check if polling should continue */ public function getShouldContinuePollingProperty(): bool { return $this->status === 'verifying' && $this->pollCount < $this->maxPolls; } /** * Get status display text */ public function getStatusTextProperty(): string { return match ($this->status) { 'verifying' => 'Verifying your payment...', 'activated' => 'Payment successful! Your subscription is now active.', 'pending' => 'Payment is being processed. Please check your subscription page.', 'error' => 'Unable to verify payment status.', default => 'Checking payment status...', }; } /** * Get status icon */ public function getStatusIconProperty(): string { return match ($this->status) { 'verifying' => 'clock', 'activated' => 'check-circle', 'pending' => 'clock', 'error' => 'exclamation-triangle', default => 'clock', }; } /** * Get status color */ public function getStatusColorProperty(): string { return match ($this->status) { 'verifying' => 'blue', 'activated' => 'green', 'pending' => 'yellow', 'error' => 'red', default => 'gray', }; } public function render(): Factory|View { return view('livewire.payment-confirmation'); } }