From 46cd4deb211abaf89c88e48ea9913a15f58c53c1 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 b77b87bc0e4..d8624b1ec13 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 7f7dd832f89..d24c7c40b5f 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 00000000000..6c1f0e0cf1d --- /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 1d4b62a1f17..acb31bd330a 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", @@ -1883,10 +1884,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 00000000000..8efa7c21edd --- /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 be57d3dada4..670fb48b0c5 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 54f32c0a8be..2dd4ae548ce 100644 --- a/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue +++ b/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue @@ -1,5 +1,68 @@