diff --git a/apps/api/src/__tests__/config/stripe-config.test.ts b/apps/api/src/__tests__/config/stripe-config.test.ts new file mode 100644 index 0000000..e8f9ca6 --- /dev/null +++ b/apps/api/src/__tests__/config/stripe-config.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { createConfig } from "../../config.js"; +import type { Secrets } from "../../secrets.js"; + +const baseSecrets: Secrets = { + supabaseServiceRoleKey: "service-role-from-secret-manager", + supabaseConnectionString: "postgres://secret-manager", + supabaseCaCert: "ca-cert", + emailClientSecret: "email-client-secret", + emailRefreshToken: "email-refresh-token", + r2AccessKeyId: "r2-access-key-id", + r2SecretAccessKey: "r2-secret-access-key", + streamChatApiSecret: "stream-chat-api-secret", + stripeSecretKey: "sk_live_secret_manager", + stripeWebhookSecret: "whsec_live_secret_manager", + streamChatApiSecretStaging: "stream-chat-api-secret-staging", + stripeSecretKeyStaging: "sk_live_staging_secret_manager", + stripeWebhookSecretStaging: "whsec_live_staging_secret_manager", +}; + +describe("createConfig stripe env overrides", () => { + it("prefers env stripe keys in development to avoid local sandbox/account mismatch", () => { + process.env.NODE_ENV = "development"; + process.env.STRIPE_SECRET_KEY = "sk_test_env_override"; + process.env.STRIPE_WEBHOOK_SECRET = "whsec_test_env_override"; + + const config = createConfig(baseSecrets); + + expect(config.STRIPE_SECRET_KEY).toBe("sk_test_env_override"); + expect(config.STRIPE_WEBHOOK_SECRET).toBe("whsec_test_env_override"); + }); +}); diff --git a/apps/api/src/config.ts b/apps/api/src/config.ts index e8c8bc3..6510c1d 100644 --- a/apps/api/src/config.ts +++ b/apps/api/src/config.ts @@ -65,6 +65,8 @@ export function createConfig(secrets?: Secrets): AppConfig { isStagingMode ? secrets!.stripeSecretKeyStaging : secrets!.stripeSecretKey; const getStripeWebhookSecret = (isStagingMode: boolean) => isStagingMode ? secrets!.stripeWebhookSecretStaging : secrets!.stripeWebhookSecret; + const getStripeSecretKeyFromEnv = () => process.env.STRIPE_SECRET_KEY; + const getStripeWebhookSecretFromEnv = () => process.env.STRIPE_WEBHOOK_SECRET; // Base configuration const baseConfig: AppConfig = { @@ -87,13 +89,22 @@ export function createConfig(secrets?: Secrets): AppConfig { : getStreamChatApiSecret(isStagingMode), STRIPE_SECRET_KEY: isTestMode ? validateEnvVar("STRIPE_SECRET_KEY", process.env.STRIPE_SECRET_KEY) - : getStripeSecretKey(isStagingMode), + : getStripeSecretKeyFromEnv() || getStripeSecretKey(isStagingMode), STRIPE_WEBHOOK_SECRET: isTestMode ? validateEnvVar("STRIPE_WEBHOOK_SECRET", process.env.STRIPE_WEBHOOK_SECRET) - : getStripeWebhookSecret(isStagingMode), - STRIPE_SOLO_PRICE_ID: validateEnvVar("STRIPE_SOLO_PRICE_ID", process.env.STRIPE_SOLO_PRICE_ID), - STRIPE_TEAM_MONTHLY_PRICE_ID: validateEnvVar("STRIPE_TEAM_MONTHLY_PRICE_ID", process.env.STRIPE_TEAM_MONTHLY_PRICE_ID), - STRIPE_FOUNDER_PRICE_ID: validateEnvVar("STRIPE_FOUNDER_PRICE_ID", process.env.STRIPE_FOUNDER_PRICE_ID), + : getStripeWebhookSecretFromEnv() || getStripeWebhookSecret(isStagingMode), + STRIPE_SOLO_PRICE_ID: validateEnvVar( + "STRIPE_SOLO_PRICE_ID", + process.env.STRIPE_SOLO_PRICE_ID + ), + STRIPE_TEAM_MONTHLY_PRICE_ID: validateEnvVar( + "STRIPE_TEAM_MONTHLY_PRICE_ID", + process.env.STRIPE_TEAM_MONTHLY_PRICE_ID + ), + STRIPE_FOUNDER_PRICE_ID: validateEnvVar( + "STRIPE_FOUNDER_PRICE_ID", + process.env.STRIPE_FOUNDER_PRICE_ID + ), EMAIL_USER: validateEnvVar("EMAIL_USER", process.env.EMAIL_USER), EMAIL_CLIENT_ID: validateEnvVar("EMAIL_CLIENT_ID", process.env.EMAIL_CLIENT_ID), EMAIL_CLIENT_SECRET: isTestMode