diff --git a/frontend/src/proprietary/components/shared/StripeCheckout.tsx b/frontend/src/proprietary/components/shared/StripeCheckout.tsx index 35d85b289..7e1cb43f2 100644 --- a/frontend/src/proprietary/components/shared/StripeCheckout.tsx +++ b/frontend/src/proprietary/components/shared/StripeCheckout.tsx @@ -59,6 +59,7 @@ const StripeCheckout: React.FC = ({ planGroup.yearly ? 'yearly' : 'monthly' ); const [installationId, setInstallationId] = useState(null); + const [currentLicenseKey, setCurrentLicenseKey] = useState(null); const [licenseKey, setLicenseKey] = useState(null); const [pollingStatus, setPollingStatus] = useState<'idle' | 'polling' | 'ready' | 'timeout'>('idle'); @@ -89,11 +90,12 @@ const StripeCheckout: React.FC = ({ } // Fetch current license key for upgrades - let currentLicenseKey: string | undefined; + let existingLicenseKey: string | undefined; try { const licenseInfo = await licenseService.getLicenseInfo(); if (licenseInfo && licenseInfo.licenseKey) { - currentLicenseKey = licenseInfo.licenseKey; + existingLicenseKey = licenseInfo.licenseKey; + setCurrentLicenseKey(existingLicenseKey); console.log('Found existing license for upgrade'); } } catch (error) { @@ -103,7 +105,7 @@ const StripeCheckout: React.FC = ({ const response = await licenseService.createCheckoutSession({ lookup_key: selectedPlan.lookupKey, installation_id: fetchedInstallationId, - current_license_key: currentLicenseKey, + current_license_key: existingLicenseKey, requires_seats: selectedPlan.requiresSeats, seat_count: Math.max(1, Math.min(minimumSeats || 1, 10000)), successUrl: `${window.location.origin}/settings/adminPlan?session_id={CHECKOUT_SESSION_ID}`, @@ -225,19 +227,54 @@ const StripeCheckout: React.FC = ({ await poll(); }, [onLicenseActivated]); - const handlePaymentComplete = () => { + const handlePaymentComplete = async () => { // Preserve state when changing status setState(prev => ({ ...prev, status: 'success' })); - // Start polling BEFORE notifying parent (so modal stays open) - if (installationId) { - pollForLicenseKey(installationId).finally(() => { - // Only notify parent after polling completes or times out - onSuccess?.(state.sessionId || ''); - }); - } else { - // No installation ID, notify immediately + // Check if this is an upgrade (existing license key) or new plan + if (currentLicenseKey) { + // UPGRADE FLOW: Force license re-verification by saving existing key + console.log('Upgrade detected - syncing existing license key'); + setPollingStatus('polling'); + + try { + const saveResponse = await licenseService.saveLicenseKey(currentLicenseKey); + + if (saveResponse.success) { + console.log(`License upgraded successfully: ${saveResponse.licenseType}`); + setPollingStatus('ready'); + + // Fetch and pass updated license info to parent + try { + const licenseInfo = await licenseService.getLicenseInfo(); + onLicenseActivated?.(licenseInfo); + } catch (infoError) { + console.error('Error fetching updated license info:', infoError); + } + } else { + console.error('Failed to sync upgraded license:', saveResponse.error); + setPollingStatus('timeout'); + } + } catch (error) { + console.error('Error syncing upgraded license:', error); + setPollingStatus('timeout'); + } + + // Notify parent (don't wait - upgrade is complete) onSuccess?.(state.sessionId || ''); + } else { + // NEW PLAN FLOW: Poll for new license key + console.log('New subscription - polling for license key'); + + if (installationId) { + pollForLicenseKey(installationId).finally(() => { + // Only notify parent after polling completes or times out + onSuccess?.(state.sessionId || ''); + }); + } else { + // No installation ID, notify immediately + onSuccess?.(state.sessionId || ''); + } } }; @@ -250,6 +287,8 @@ const StripeCheckout: React.FC = ({ setState({ status: 'idle' }); setPollingStatus('idle'); + setCurrentLicenseKey(null); + setLicenseKey(null); // Reset to default period on close setSelectedPeriod(planGroup.yearly ? 'yearly' : 'monthly'); onClose(); @@ -398,29 +437,19 @@ const StripeCheckout: React.FC = ({ )} - {/* Installation ID Display */} - {installationId && ( - - - - {t('payment.installationId', 'Installation ID')} - - {installationId} - - - )} - {/* License Key Polling Status */} {pollingStatus === 'polling' && ( - {t('payment.generatingLicense', 'Generating your license key...')} + {currentLicenseKey + ? t('payment.syncingLicense', 'Syncing your upgraded license...') + : t('payment.generatingLicense', 'Generating your license key...')} )} - {pollingStatus === 'ready' && licenseKey && ( + {pollingStatus === 'ready' && !currentLicenseKey && licenseKey && ( @@ -444,6 +473,17 @@ const StripeCheckout: React.FC = ({ )} + {pollingStatus === 'ready' && currentLicenseKey && ( + + + {t( + 'payment.upgradeCompleteMessage', + 'Your subscription has been upgraded successfully. Your existing license key has been updated.' + )} + + + )} + {pollingStatus === 'timeout' && (