โ
Migration Complete (Code Changes)
All backend code has been updated to support dynamic mode switching between TEST and LIVE Stripe API keys.
Date: December 2024
Status: Ready for production deployment
Current Mode: LIVE (configured via STRIPE_MODE=live in .env)
๐ What Was Changed
1. Environment Configuration (.env)
Added STRIPE_MODE variable to control which API keys are used:
# Stripe Mode (test or live)
STRIPE_MODE=live # โ ๏ธ Currently set to LIVE (production)
Live API keys now active:
- STRIPE_LIVE_SECRET_KEY=sk_live_51TBkCoJOCrsvRkaz...
- STRIPE_LIVE_PUBLISHABLE_KEY=pk_live_51TBkCoJOCrsvRkaz...
Test keys preserved for development:
- STRIPE_TEST_SECRET_KEY=sk_test_51TBkCoJOCrsvRkaz...
- STRIPE_TEST_PUBLISHABLE_KEY=pk_test_51TBkCoJOCrsvRkaz...
2. Updated Stripe Integration Files (6 files)
All Stripe API initializations now use dynamic key selection:
Routes:
- routes/invoice-payments.js - Payment intent creation
- Mode-based secret key selection
- Mode-based publishable key in API response
- Logs mode on startup: [Stripe] Invoice Payments initialized in LIVE mode
- routes/stripe-webhook.js - Webhook event processing
- Mode-based webhook secret selection (2 secrets: snapshot + thin)
- Logs mode on startup: [Stripe] Webhook handler initialized in LIVE mode
- routes/public-invoice-payment.js - Public payment page
- Mode-based secret key for public invoice payments
- Logs mode on startup: [Stripe] Public Invoice Payment initialized in LIVE mode
- routes/refunds.js - Refund processing
- Mode-based secret key for refund operations
- Logs mode on startup: [Stripe] Refunds initialized in LIVE mode
Services:
- services/stripeService.js - Core Stripe operations
- Mode-based secret key for Connected Account management
- Logs mode on startup: [Stripe] Service initialized in LIVE mode
Indirect (no changes needed):
- routes/stripe-connect.js - Uses stripeService (inherits mode automatically)
โ ๏ธ CRITICAL: Webhook Configuration Required
Current Status โ NOT CONFIGURED
Your live webhook secrets are currently placeholders and must be updated:
# .env (lines to update):
STRIPE_LIVE_WEBHOOK_SECRET=whsec_REPLACE_WITH_LIVE_WEBHOOK_SECRET
STRIPE_LIVE_WEBHOOK_SECRET_THIN=whsec_REPLACE_WITH_LIVE_THIN_WEBHOOK_SECRET
How to Configure Live Webhooks
- Go to Stripe Dashboard (LIVE mode):
- Create Snapshot Webhook (Primary):
- Click "Add endpoint"
- Endpoint URL: https://rmm-psa-backend-t9f7k.ondigitalocean.app/api/stripe/webhook
- Description: "RMM-PSA Main Webhook (Snapshot)"
- Events to send: Select all events OR minimum:
- payment_intent.succeeded
- payment_intent.payment_failed
- charge.succeeded
- charge.failed
- charge.refunded
- customer.subscription.created
- customer.subscription.updated
- customer.subscription.deleted
- invoice.payment_succeeded
- invoice.payment_failed
- account.updated (for Connected Accounts)
- API version: Latest (default)
- Click "Add endpoint"
- Copy Webhook Signing Secret:
- After creating, click "Reveal" next to "Signing secret"
- Copy the secret (starts with whsec_...)
- Update .env:
STRIPE_LIVE_WEBHOOK_SECRET=whsec_[your-secret-here]
- Create Thin Webhook (Fallback):
- Repeat steps 2-3 for a second webhook
- Same URL, different description: "RMM-PSA Fallback Webhook (Thin)"
- Copy signing secret to:
STRIPE_LIVE_WEBHOOK_SECRET_THIN=whsec_[your-second-secret-here]
- Update DigitalOcean Environment:
- Go to: DigitalOcean โ Apps โ rmm-psa-backend โ Settings โ Environment Variables
- Update:
- STRIPE_LIVE_WEBHOOK_SECRET
- STRIPE_LIVE_WEBHOOK_SECRET_THIN
- Click "Save" (triggers redeployment)
๐งช Testing Checklist
Before Going Live
- Verify STRIPE_MODE=live in production .env
- Confirm live API keys are correct (check first/last 4 chars)
- Configure live webhooks in Stripe Dashboard
- Update webhook secrets in .env and DigitalOcean
- Deploy backend to production
- Check startup logs for: [Stripe] ... initialized in LIVE mode
Test Payments (Use Stripe Test Cards in Live Mode)
โ ๏ธ IMPORTANT: Even in live mode, you can test without charges using these cards:
- Success: 4242 4242 4242 4242 (Visa)
- Decline: 4000 0000 0000 0002 (Visa - card declined)
- 3D Secure: 4000 0025 0000 3155 (Visa - requires authentication)
- Expiry: Any future date (e.g., 12/25)
- CVC: Any 3 digits (e.g., 123)
Test Flow:
- Create a test invoice in dashboard
- Open invoice payment page
- Enter test card: 4242 4242 4242 4242
- Complete payment
- Verify:
- Payment Intent created in Stripe Dashboard (Payments tab)
- Webhook received (Webhooks โ Events)
- Invoice marked as paid in RMM-PSA database
- Payment record created in payments table
Verify Webhook Processing
- Check Webhook Delivery:
- Stripe Dashboard โ Webhooks โ [Your endpoint]
- Recent deliveries should show HTTP 200 responses
- If 401/500 errors: webhook secret incorrect
- Check Backend Logs:
- DigitalOcean โ Apps โ rmm-psa-backend โ Runtime Logs
- Look for: [Stripe] Webhook handler initialized in LIVE mode
- Verify event processing: Webhook received: payment_intent.succeeded
- Check Database:
SELECT * FROM stripe_webhook_events
ORDER BY created_at DESC
LIMIT 10;
SELECT * FROM payments
WHERE stripe_payment_intent_id IS NOT NULL
ORDER BY created_at DESC
LIMIT 10;
๐ Switching Back to Test Mode
If you need to revert to test mode (e.g., for development/debugging):
- Update .env:
- Restart backend (or redeploy on DigitalOcean)
- Verify logs show:
[Stripe] Invoice Payments initialized in TEST mode
[Stripe] Webhook handler initialized in TEST mode
[Stripe] Service initialized in TEST mode
No code changes needed - the mode switch is purely configuration-driven.
๐ Stripe Connect Architecture
Platform Model:
- One platform account (your main Stripe account)
- Multiple Connected Accounts (one per tenant/MSP)
- Application fee: 3% on all transactions
Payment Flow:
- Customer pays invoice via frontend
- Payment processed on tenant's Connected Account
- Platform automatically receives 3% application fee
- Tenant receives 97% of payment (minus Stripe's processing fee)
Connected Account Onboarding:
- Tenant clicks "Connect Stripe" in dashboard
- POST /api/stripe/connect/account creates Connected Account
- Redirect to Stripe-hosted onboarding flow
- Tenant completes verification (business details, bank info)
- Webhook: account.updated confirms charges_enabled: true
- System stores stripe_account_id in stripe_config table
- All future payments route via this Connected Account
๐ก๏ธ Security Notes
- Live API Keys:
- Never commit live keys to Git
- Store in .env only (excluded by .gitignore)
- Rotate keys if exposed
- Webhook Secrets:
- Protects against unauthorized webhook calls
- Each endpoint has unique signing secret
- Backend verifies signature before processing
- Connected Accounts:
- Stripe handles all KYC/verification
- Platform never stores tenant bank details
- OAuth-based authorization only
๐ Stripe Dashboard Links
Remember to toggle to LIVE mode (top right) when configuring production settings.
โ
Post-Migration Verification
After deploying and configuring webhooks:
# Check backend logs for mode confirmation
# DigitalOcean โ Apps โ rmm-psa-backend โ Runtime Logs
Expected output on startup:
[Stripe] Invoice Payments initialized in LIVE mode
[Stripe] Webhook handler initialized in LIVE mode
[Stripe] Service initialized in LIVE mode
[Stripe] Public Invoice Payment initialized in LIVE mode
[Stripe] Refunds initialized in LIVE mode
Test with real payment:
- Create invoice
- Process payment with test card 4242 4242 4242 4242
- Verify webhook received (Stripe Dashboard โ Webhooks)
- Verify payment recorded (RMM-PSA โ Invoices)
- Verify application fee collected (Stripe Dashboard โ Balance โ Application fees)
๐ Deployment Commands
# Commit changes
git add .
git commit -m "Enable Stripe LIVE mode with dynamic key selection"
# Push to GitHub (triggers DigitalOcean auto-deploy)
git push origin main
# Monitor deployment
# DigitalOcean โ Apps โ rmm-psa-backend โ Activity
After deployment completes (~2-3 minutes), verify startup logs show LIVE mode.
Questions? Check Stripe documentation: