From 4e0f1768425e2ab81938daccd0d5cc7028e60744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=8A?= Date: Mon, 30 Mar 2026 07:51:45 +0530 Subject: [PATCH] Add strict Stripe checkout guard via env flag --- backend/services/subscription/stripe_service.py | 13 +++++++++++++ frontend/src/components/Pricing/PricingPage.tsx | 17 +++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/backend/services/subscription/stripe_service.py b/backend/services/subscription/stripe_service.py index 0a67a99e..2e20e7c2 100644 --- a/backend/services/subscription/stripe_service.py +++ b/backend/services/subscription/stripe_service.py @@ -16,6 +16,10 @@ } +def _is_truthy_env(var_name: str) -> bool: + return os.getenv(var_name, "").strip().lower() in {"1", "true", "yes", "on"} + + def _detect_stripe_mode() -> str: configured_mode = os.getenv("STRIPE_MODE", "").strip().lower() if configured_mode in {"test", "live"}: @@ -98,7 +102,16 @@ def __init__(self, db: Session): self.db = db self.api_key = os.getenv("STRIPE_SECRET_KEY") self.webhook_secret = os.getenv("STRIPE_WEBHOOK_SECRET") + self.require_stripe_checkout = _is_truthy_env("REQUIRE_STRIPE_CHECKOUT") if not self.api_key: + if self.require_stripe_checkout: + raise HTTPException( + status_code=500, + detail=( + "REQUIRE_STRIPE_CHECKOUT=true but STRIPE_SECRET_KEY is missing. " + "Configure STRIPE_SECRET_KEY to enable Stripe checkout." + ), + ) logger.warning("STRIPE_SECRET_KEY is not set. Stripe integration will not work.") else: stripe.api_key = self.api_key diff --git a/frontend/src/components/Pricing/PricingPage.tsx b/frontend/src/components/Pricing/PricingPage.tsx index 80c4d811..89b23740 100644 --- a/frontend/src/components/Pricing/PricingPage.tsx +++ b/frontend/src/components/Pricing/PricingPage.tsx @@ -52,6 +52,10 @@ export interface SubscriptionPlan { } const PricingPage: React.FC = () => { + const requireStripeCheckout = ['1', 'true', 'yes', 'on'].includes( + (process.env.REACT_APP_REQUIRE_STRIPE_CHECKOUT || '').toLowerCase() + ); + const stripePublishableKey = process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY; const navigate = useNavigate(); const [plans, setPlans] = useState([]); const [loading, setLoading] = useState(true); @@ -173,7 +177,7 @@ const PricingPage: React.FC = () => { const userId = localStorage.getItem('user_id') || 'anonymous'; // Check if Stripe is configured - if (process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY) { + if (stripePublishableKey) { console.log('[PricingPage] Initiating Stripe Checkout'); const response = await apiClient.post('/api/subscription/create-checkout-session', { @@ -187,6 +191,14 @@ const PricingPage: React.FC = () => { window.location.href = response.data.url; return; } + + if (requireStripeCheckout) { + throw new Error('Stripe checkout is required but checkout URL was not returned.'); + } + } else if (requireStripeCheckout) { + throw new Error( + 'Stripe checkout is required but REACT_APP_STRIPE_PUBLISHABLE_KEY is not configured.' + ); } console.log('[PricingPage] Making legacy subscription API call:', { @@ -271,7 +283,8 @@ const PricingPage: React.FC = () => { }, 3000); } catch (err) { console.error('Error subscribing:', err); - setError('Failed to process subscription'); + const errorMessage = err instanceof Error ? err.message : 'Failed to process subscription'; + setError(errorMessage); setSuccessSnackbar({ open: false, message: '', countdown: 0 }); } finally { setSubscribing(false);