#!/usr/bin/env node /** * Verify Stripe Customer Portal Configuration * * This script checks if the Customer Portal is configured correctly * and provides guidance on what needs to be set up. * * Usage: * node scripts/verify-stripe-portal.js * * Environment: * STRIPE_SECRET_KEY - Your Stripe secret key (test or live) */ require('dotenv').config(); const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); async function verifyPortalConfiguration() { console.log('\nšŸ” Verifying Stripe Customer Portal Configuration\n'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); try { // Determine if we're in test or live mode const mode = process.env.STRIPE_SECRET_KEY.startsWith('sk_test_') ? 'TEST' : 'LIVE'; console.log(`šŸ“‹ Mode: ${mode}\n`); // Check for portal configurations const configurations = await stripe.billingPortal.configurations.list({ limit: 10 }); if (configurations.data.length === 0) { console.log('āŒ No Customer Portal configurations found\n'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); console.log('āš ļø YOU NEED TO CONFIGURE THE CUSTOMER PORTAL\n'); printConfigurationSteps(mode); return; } // Show existing configurations console.log(`āœ… Found ${configurations.data.length} portal configuration(s)\n`); configurations.data.forEach((config, index) => { console.log(`\nšŸ“¦ Configuration #${index + 1}:`); console.log(` ID: ${config.id}`); console.log(` Active: ${config.active ? 'Yes āœ…' : 'No āŒ'}`); console.log(` Default: ${config.is_default ? 'Yes āœ…' : 'No āŒ'}`); console.log(` Created: ${new Date(config.created * 1000).toLocaleString()}`); // Features console.log('\n šŸ“‹ Enabled Features:'); // Customer update if (config.features.customer_update) { const emailEnabled = config.features.customer_update.allowed_updates.includes('email'); console.log(` • Email editing: ${emailEnabled ? 'āœ… Enabled' : 'āŒ Disabled'}`); } // Payment method update if (config.features.payment_method_update) { console.log(` • Payment method update: āœ… Enabled`); } else { console.log(` • Payment method update: āŒ Disabled`); } // Subscription cancellation if (config.features.subscription_cancel) { console.log(` • Subscription cancellation: āœ… Enabled`); console.log(` Mode: ${config.features.subscription_cancel.mode || 'Not set'}`); // Check for cancellation survey if (config.features.subscription_cancel.cancellation_reason) { console.log(` Cancellation survey: āœ… Enabled`); console.log(` Survey enabled: ${config.features.subscription_cancel.cancellation_reason.enabled ? 'Yes āœ…' : 'No āŒ'}`); if (config.features.subscription_cancel.cancellation_reason.options) { console.log(` Survey options: ${config.features.subscription_cancel.cancellation_reason.options.length} options`); } } else { console.log(` Cancellation survey: āŒ Not configured`); } } else { console.log(` • Subscription cancellation: āŒ Disabled`); } // Invoice history if (config.features.invoice_history) { console.log(` • Invoice history: āœ… Enabled`); } else { console.log(` • Invoice history: āŒ Disabled`); } // Business profile console.log('\n šŸ¢ Business Information:'); if (config.business_profile) { console.log(` • Headline: ${config.business_profile.headline || 'Not set'}`); console.log(` • Privacy policy URL: ${config.business_profile.privacy_policy_url || 'Not set'}`); console.log(` • Terms of service URL: ${config.business_profile.terms_of_service_url || 'Not set'}`); } else { console.log(` • Not configured`); } }); console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); // Verify against requirements const defaultConfig = configurations.data.find(c => c.is_default) || configurations.data[0]; console.log('āœ… VERIFICATION CHECKLIST:\n'); const checks = []; // Check 1: Email editing const emailEnabled = defaultConfig.features.customer_update?.allowed_updates?.includes('email'); checks.push({ name: 'Email editing enabled', status: emailEnabled, required: true }); // Check 2: Payment method update const paymentMethodEnabled = defaultConfig.features.payment_method_update?.enabled !== false; checks.push({ name: 'Payment method update enabled', status: paymentMethodEnabled, required: true }); // Check 3: Subscription cancellation const cancelEnabled = defaultConfig.features.subscription_cancel?.enabled !== false; checks.push({ name: 'Subscription cancellation enabled', status: cancelEnabled, required: true }); // Check 4: Cancellation survey const surveyEnabled = defaultConfig.features.subscription_cancel?.cancellation_reason?.enabled === true; checks.push({ name: 'Exit survey configured', status: surveyEnabled, required: true }); // Check 5: Invoice history const invoiceEnabled = defaultConfig.features.invoice_history?.enabled !== false; checks.push({ name: 'Invoice history enabled', status: invoiceEnabled, required: true }); // Print checklist checks.forEach(check => { const icon = check.status ? 'āœ…' : 'āŒ'; const required = check.required ? '(REQUIRED)' : '(optional)'; console.log(` ${icon} ${check.name} ${required}`); }); const allPassed = checks.filter(c => c.required).every(c => c.status); console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); if (allPassed) { console.log('šŸŽ‰ PORTAL CONFIGURATION COMPLETE!\n'); console.log(' All required features are enabled.'); console.log(' You can now use the Customer Portal.\n'); } else { console.log('āš ļø PORTAL CONFIGURATION INCOMPLETE\n'); console.log(' Some required features are not enabled.'); printConfigurationSteps(mode); } } catch (error) { console.error('āŒ Error verifying portal configuration:', error.message); if (error.type === 'StripeAuthenticationError') { console.error('\nāš ļø Authentication failed. Please check:'); console.error(' 1. STRIPE_SECRET_KEY is set in .env'); console.error(' 2. The key starts with sk_test_ or sk_live_'); console.error(' 3. The key is valid and not expired\n'); } } } function printConfigurationSteps(mode) { const dashboardUrl = mode === 'TEST' ? 'https://dashboard.stripe.com/test/settings/billing/portal' : 'https://dashboard.stripe.com/settings/billing/portal'; console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); console.log(`šŸ“ CONFIGURE CUSTOMER PORTAL (${mode} MODE)\n`); console.log(`Step 1: Open Dashboard`); console.log(` ${dashboardUrl}\n`); console.log(`Step 2: Enable Features (click each to enable)`); console.log(` ☐ Customer can edit email`); console.log(` ☐ Customer can update payment methods`); console.log(` ☐ Customer can cancel subscriptions`); console.log(` ☐ Customer can view invoice history\n`); console.log(`Step 3: Configure Cancellation Survey`); console.log(` ☐ Enable "Ask why they're cancelling"`); console.log(` ☐ Add question: "Why are you cancelling?"`); console.log(` ☐ Options:`); console.log(` • Too expensive`); console.log(` • No longer need it`); console.log(` • Found alternative`); console.log(` • Other`); console.log(` ☐ Add optional question: "How can we improve?"`); console.log(` Type: Text input (optional)\n`); console.log(`Step 4: Business Information`); console.log(` ☐ Business name: Tractatus AI Safety Framework`); console.log(` ☐ Support email: support@agenticgovernance.digital\n`); console.log(`Step 5: Save Configuration`); console.log(` ☐ Click "Save" or "Activate"\n`); console.log(`Step 6: Verify`); console.log(` ☐ Run this script again to verify:\n`); console.log(` node scripts/verify-stripe-portal.js\n`); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); console.log('šŸ“– Full guide: docs/STRIPE_PORTAL_CONFIGURATION_STEPS.md\n'); } // Run verification verifyPortalConfiguration().catch(console.error);