- Add check-stripe-bank-account.js for bank account verification - Add verify-stripe-portal.js for portal configuration validation - Tools help troubleshoot bank account holder name issues - Automated verification of portal features and requirements Part of Stripe troubleshooting workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
222 lines
9.1 KiB
JavaScript
Executable file
222 lines
9.1 KiB
JavaScript
Executable file
#!/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);
|