⚠️ Current payment provider: Razorpay. See razorpay_setup_guide.md for the active setup.
This guide is for Phase 8 — Stripe Integration (international billing). The
IPaymentProviderabstraction in the codebase means adding Stripe requires only implementingStripeProvider— no changes to billing routes, services, or DB schema.
Step-by-step Stripe Dashboard configuration to get billing working. Complete this before writing any code (Phase 0 of the implementation plan).
Docs: user_journeys.md · architecture.md · api_specification.md · razorpay_setup_guide.md
Prerequisites
- Stripe account created at dashboard.stripe.com
- Test Mode enabled (toggle in top-right of Dashboard — orange "TEST" badge should be visible)
- Access to LogicSpike
.env.localfile for storing keys
Step 1: Collect API Keys
Dashboard → Developers → API Keys
| Key | Where to Store | Notes |
|---|---|---|
Publishable key (pk_test_...) |
STRIPE_PUBLISHABLE_KEY in .env.local |
Used on frontend for Stripe.js (if needed) |
Secret key (sk_test_...) |
STRIPE_SECRET_KEY in .env.local |
Used on Manager backend. Never expose to frontend. |
# .env.local
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...Step 2: Enable Stripe Tax
Dashboard → Settings → Tax → Tax Automation
- Click "Get started" or "Enable" on Stripe Tax
- Set origin address (your business address — used for tax calculation)
- Enable "Automatic tax calculation"
- Set product tax category to "Software as a Service (SaaS)" (default for cloud subscriptions)
This ensures
automatic_tax: { enabled: true }works in Checkout Sessions. Stripe handles VAT/GST/sales tax per customer location.
Step 3: Create Products & Prices
Dashboard → Product Catalog → + Add Product
Create the following products and their prices. Record every Price ID — you'll insert them into the plans table.
3a. Subscription Products
LogicSpike Free
- Name: LogicSpike Free
- Description: Free forever plan with basic features
- No price needed — tracked internally only, no Stripe subscription created
- Record:
stripe_price_id_monthly = null,stripe_price_id_yearly = null
LogicSpike Starter
- Name: LogicSpike Starter
- Description: For small teams getting started
- Price 1 (Monthly):
- Pricing model: Standard
- Amount: $12.00 / month
- Recurring: Monthly
- → Record the Price ID:
price_starter_monthly = price_...
- Price 2 (Yearly):
- Amount: $120.00 / year ($10/mo effective — 17% savings)
- Recurring: Yearly
- → Record the Price ID:
price_starter_yearly = price_...
LogicSpike Pro
- Name: LogicSpike Pro
- Description: For growing teams with advanced features
- Price 1 (Monthly):
- Amount: $29.00 / month
- → Record:
price_pro_monthly = price_...
- Price 2 (Yearly):
- Amount: $288.00 / year ($24/mo effective — 17% savings)
- → Record:
price_pro_yearly = price_...
LogicSpike Business
- Name: LogicSpike Business
- Description: For agencies and large teams
- Price 1 (Monthly):
- Amount: $79.00 / month
- → Record:
price_business_monthly = price_...
- Price 2 (Yearly):
- Amount: $780.00 / year ($65/mo effective — 18% savings)
- → Record:
price_business_yearly = price_...
3b. Coin Pack Products (One-Time)
Coin Pack — Small
- Name: LogicSpike Coins - Small Pack
- Description: 500 LogicSpike Coins
- Price: $5.00 (one-time)
- → Record:
price_coins_small = price_...
Coin Pack — Medium
- Name: LogicSpike Coins - Medium Pack
- Description: 2,200 LogicSpike Coins (10% bonus)
- Price: $20.00 (one-time)
- → Record:
price_coins_medium = price_...
Coin Pack — Large
- Name: LogicSpike Coins - Large Pack
- Description: 6,000 LogicSpike Coins (20% bonus)
- Price: $50.00 (one-time)
- → Record:
price_coins_large = price_...
Price ID Reference Table
After creating all products, fill in this table. You'll use it for the database seed:
| Plan / Pack | Monthly Price ID | Yearly Price ID |
|---|---|---|
| Free | — | — |
| Starter | price_... |
price_... |
| Pro | price_... |
price_... |
| Business | price_... |
price_... |
| Coin Pack | Price ID |
|---|---|
| Small (500 coins) | price_... |
| Medium (2,200 coins) | price_... |
| Large (6,000 coins) | price_... |
Step 4: Configure Customer Portal
Dashboard → Settings → Billing → Customer Portal
Enable these features:
| Feature | Setting |
|---|---|
| Update payment method | ✅ Enabled |
| Cancel subscription | ✅ Enabled |
| Switch plan | ❌ Disabled (we handle this with our own UI via POST /billing/change-plan) |
| View invoice history | ✅ Enabled |
| Update billing information | ✅ Enabled |
Portal Branding
- Upload LogicSpike logo
- Set brand color to match LogicSpike theme
- Set business name: "LogicSpike"
- Set terms of service URL (when available)
- Set privacy policy URL (when available)
Step 5: Register Webhook Endpoint
Dashboard → Developers → Webhooks → + Add Endpoint
Production
| Field | Value |
|---|---|
| Endpoint URL | https://api.logicspike.com/webhooks/stripe |
| Events to listen | See list below |
| API version | Latest (auto-selected) |
Local Development
Use the Stripe CLI instead of a Dashboard webhook:
# Install Stripe CLI
# macOS: brew install stripe/stripe-cli/stripe
# Windows: scoop install stripe
# Login
stripe login
# Forward events to local Manager service
stripe listen --forward-to http://localhost:8787/webhooks/stripeThe CLI will print a webhook signing secret (whsec_...) — use this locally.
Events to Subscribe
Select these events when creating the webhook:
| Event | Why |
|---|---|
checkout.session.completed |
Subscription created OR coin pack purchased |
invoice.payment_succeeded |
Monthly/yearly renewal succeeded |
invoice.payment_failed |
Payment failed — trigger past_due |
customer.subscription.updated |
Plan change, trial status, cycle switch |
customer.subscription.deleted |
Subscription canceled (voluntary or involuntary) |
Webhook Secret
After creating the endpoint, copy the Signing Secret:
# .env.local
STRIPE_WEBHOOK_SECRET=whsec_...Step 6: Create Promotion Codes (Optional)
Dashboard → Product Catalog → Coupons → + Create Coupon
Example: LAUNCH50
| Field | Value |
|---|---|
| Name | Launch Promo |
| Type | Percentage off |
| Percentage | 50% |
| Duration | Repeating — 3 months |
| Max redemptions | 100 (optional) |
| Code | LAUNCH50 |
Promo codes are managed entirely in Stripe Dashboard. The backend just sets
allow_promotion_codes: trueon Checkout Sessions.
Step 7: Configure Payment Retry Settings
Dashboard → Settings → Billing → Subscriptions and emails → Manage failed payments
Recommended settings:
| Setting | Value |
|---|---|
| Retry schedule | Stripe Smart Retries (recommended) |
| Number of retries | 3 attempts |
| Retry window | 7 days |
| After all retries fail | Cancel subscription |
| Send email to customer | ✅ Enabled (Stripe sends dunning emails automatically) |
This aligns with the 7-day grace period documented in Journey 6 (user_journeys.md).
Step 8: Invoice Settings
Dashboard → Settings → Billing → Invoices
| Setting | Value |
|---|---|
| Default footer | "Thank you for using LogicSpike!" |
| Default memo | (leave blank) |
| Invoice numbering | Auto (Stripe handles) |
| PDF branding | Upload LogicSpike logo |
Customer-specific Company Name + Tax ID will be set programmatically via
PUT /billing/info→ Stripe Customer update.
Final Checklist
After completing all steps, verify you have:
-
STRIPE_SECRET_KEYin.env.local -
STRIPE_PUBLISHABLE_KEYin.env.local -
STRIPE_WEBHOOK_SECRETin.env.local - 3 subscription products created (Starter, Pro, Business) with monthly + yearly prices
- 3 coin pack products created (Small, Medium, Large) with one-time prices
- All 6 subscription Price IDs recorded (for
planstable seed) - All 3 coin pack Price IDs recorded (for
coins.service.ts) - Stripe Tax enabled
- Webhook endpoint registered with 5 events
- Customer Portal configured
- Payment retry set to 7 days / 3 retries / cancel after
- Test Mode active (not live!)
Environment Variables Summary
# Stripe API
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
# Price IDs (from Step 3)
STRIPE_PRICE_STARTER_MONTHLY=price_...
STRIPE_PRICE_STARTER_YEARLY=price_...
STRIPE_PRICE_PRO_MONTHLY=price_...
STRIPE_PRICE_PRO_YEARLY=price_...
STRIPE_PRICE_BUSINESS_MONTHLY=price_...
STRIPE_PRICE_BUSINESS_YEARLY=price_...
STRIPE_PRICE_COINS_SMALL=price_...
STRIPE_PRICE_COINS_MEDIUM=price_...
STRIPE_PRICE_COINS_LARGE=price_...Alternative: Price IDs can be stored in the
plansDB table instead of env vars. Env vars for API keys + webhook secret only. The Price IDs are included here as a reference during initial setup — they go into the database seed (see Phase 1 in implementation_plan.md).
Test Cards
Use these during development:
| Card Number | Scenario |
|---|---|
4242 4242 4242 4242 |
Successful payment |
4000 0000 0000 3220 |
3D Secure authentication required |
4000 0000 0000 9995 |
Payment declined |
4000 0000 0000 0341 |
Attaching card fails |
4000 0025 0000 3155 |
Requires authentication (SCA) |
CVC: any 3 digits · Expiry: any future date · ZIP: any 5 digits
Going Live Checklist
When ready to switch from test to production:
- Switch to Live Mode in Stripe Dashboard
- Create all products + prices again in Live Mode (they don't carry over from Test Mode)
- Update
.envwith live keys (sk_live_...,pk_live_...) - Register a new webhook endpoint with the production URL
- Update
STRIPE_WEBHOOK_SECRETwith the live signing secret - Verify tax settings are correct for live
- Run a real $1 test transaction and refund it
- Enable Stripe Radar for fraud protection