From 8209f5a1085c2b862e30a4836309ec14d9a0296e Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Tue, 9 Dec 2025 03:45:45 -0800 Subject: [PATCH] feat: add Stripe pricing table integration for subscription dialog (conditional on feature flag) (#7288) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrates Stripe's pricing table web component into the subscription dialog when the subscription_tiers_enabled feature flag is active. The implementation includes a new StripePricingTable component that loads Stripe's pricing table script and renders the table with proper error handling and loading states. The subscription dialog now displays the Stripe pricing table with contact us and enterprise links, using a 1100px width that balances multi-column layout with visual design. Configuration supports environment variables, remote config, and window config for the Stripe publishable key and pricing table ID. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7288-feat-add-Stripe-pricing-table-integration-for-subscription-dialog-conditional-on-featur-2c46d73d365081fa9d93c213df118996) by [Unito](https://www.unito.io) --- .env_example | 4 + global.d.ts | 2 + src/config/stripePricingTableConfig.ts | 34 ++++ src/locales/en/main.json | 11 ++ .../components/StripePricingTable.vue | 117 +++++++++++ .../components/SubscribeButton.vue | 28 ++- .../SubscriptionRequiredDialogContent.vue | 181 +++++++++++++++++- .../useStripePricingTableLoader.ts | 118 ++++++++++++ .../composables/useSubscription.ts | 6 +- .../composables/useSubscriptionDialog.ts | 27 ++- src/platform/remoteConfig/types.ts | 2 + .../settings/composables/useSettingUI.ts | 17 +- src/vite-env.d.ts | 9 + .../components/StripePricingTable.test.ts | 113 +++++++++++ 14 files changed, 651 insertions(+), 18 deletions(-) create mode 100644 src/config/stripePricingTableConfig.ts create mode 100644 src/platform/cloud/subscription/components/StripePricingTable.vue create mode 100644 src/platform/cloud/subscription/composables/useStripePricingTableLoader.ts create mode 100644 tests-ui/tests/platform/cloud/subscription/components/StripePricingTable.test.ts diff --git a/.env_example b/.env_example index b77b87bc0..d8624b1ec 100644 --- a/.env_example +++ b/.env_example @@ -42,3 +42,7 @@ ALGOLIA_API_KEY=684d998c36b67a9a9fce8fc2d8860579 # SENTRY_AUTH_TOKEN=private-token # get from sentry # SENTRY_ORG=comfy-org # SENTRY_PROJECT=cloud-frontend-staging + +# Stripe pricing table configuration (used by feature-flagged subscription tiers UI) +# VITE_STRIPE_PUBLISHABLE_KEY=pk_test_123 +# VITE_STRIPE_PRICING_TABLE_ID=prctbl_123 diff --git a/global.d.ts b/global.d.ts index 7f7dd832f..d24c7c40b 100644 --- a/global.d.ts +++ b/global.d.ts @@ -13,6 +13,8 @@ interface Window { max_upload_size?: number comfy_api_base_url?: string comfy_platform_base_url?: string + stripe_publishable_key?: string + stripe_pricing_table_id?: string firebase_config?: { apiKey: string authDomain: string diff --git a/src/config/stripePricingTableConfig.ts b/src/config/stripePricingTableConfig.ts new file mode 100644 index 000000000..6c1f0e0cf --- /dev/null +++ b/src/config/stripePricingTableConfig.ts @@ -0,0 +1,34 @@ +import { remoteConfig } from '@/platform/remoteConfig/remoteConfig' + +export const STRIPE_PRICING_TABLE_SCRIPT_SRC = + 'https://js.stripe.com/v3/pricing-table.js' + +interface StripePricingTableConfig { + publishableKey: string + pricingTableId: string +} + +function getEnvValue( + key: 'VITE_STRIPE_PUBLISHABLE_KEY' | 'VITE_STRIPE_PRICING_TABLE_ID' +) { + return import.meta.env[key] +} + +export function getStripePricingTableConfig(): StripePricingTableConfig { + const publishableKey = + remoteConfig.value.stripe_publishable_key || + window.__CONFIG__?.stripe_publishable_key || + getEnvValue('VITE_STRIPE_PUBLISHABLE_KEY') || + '' + + const pricingTableId = + remoteConfig.value.stripe_pricing_table_id || + window.__CONFIG__?.stripe_pricing_table_id || + getEnvValue('VITE_STRIPE_PRICING_TABLE_ID') || + '' + + return { + publishableKey, + pricingTableId + } +} diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 73908a376..f7cbee358 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -97,6 +97,7 @@ "no": "No", "cancel": "Cancel", "close": "Close", + "or": "or", "pressKeysForNewBinding": "Press keys for new binding", "defaultBanner": "default banner", "enableOrDisablePack": "Enable or disable pack", @@ -1894,10 +1895,20 @@ "waitingForSubscription": "Complete your subscription in the new tab. We'll automatically detect when you're done!", "subscribe": "Subscribe" }, + "pricingTable": { + "description": "Access cloud-powered ComfyUI workflows with straightforward, usage-based pricing.", + "loading": "Loading pricing options...", + "loadError": "We couldn't load the pricing table. Please refresh and try again.", + "missingConfig": "Stripe pricing table configuration missing. Provide the publishable key and pricing table ID via remote config or .env." + }, "subscribeToRun": "Subscribe", "subscribeToRunFull": "Subscribe to Run", "subscribeNow": "Subscribe Now", "subscribeToComfyCloud": "Subscribe to Comfy Cloud", + "description": "Choose the best plan for you", + "haveQuestions": "Have questions or wondering about enterprise?", + "contactUs": "Contact us", + "viewEnterprise": "view enterprise", "partnerNodesCredits": "Partner Nodes pricing table" }, "userSettings": { diff --git a/src/platform/cloud/subscription/components/StripePricingTable.vue b/src/platform/cloud/subscription/components/StripePricingTable.vue new file mode 100644 index 000000000..8efa7c21e --- /dev/null +++ b/src/platform/cloud/subscription/components/StripePricingTable.vue @@ -0,0 +1,117 @@ + + + diff --git a/src/platform/cloud/subscription/components/SubscribeButton.vue b/src/platform/cloud/subscription/components/SubscribeButton.vue index be57d3dad..670fb48b0 100644 --- a/src/platform/cloud/subscription/components/SubscribeButton.vue +++ b/src/platform/cloud/subscription/components/SubscribeButton.vue @@ -24,8 +24,9 @@ diff --git a/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue b/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue index 54f32c0a8..2dd4ae548 100644 --- a/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue +++ b/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue @@ -1,5 +1,68 @@