Stripe Setup Status & Recommendations
✅ What's Working Correctly
1. **Checkout Creation** (`/api/billing/checkout`)
- ✅ Creates Stripe checkout sessions with proper metadata
- ✅ Includes
tenant_idin metadata for tracking - ✅ Uses idempotency keys to prevent duplicate sessions
- ✅ Handles both subscription and trial charge ($1 verification) flows
- ✅ Success URL:
${tenantBaseUrl}/settings?success=true - ✅ Cancel URL:
${tenantBaseUrl}/pricing
2. **Webhook Handlers**
- ✅ **Backend**:
/api/v1/stripe/webhook - ✅ **Frontend**:
/api/webhooks/stripe - ✅ **Events handled**:
checkout.session.completedcustomer.subscription.created/updated/deletedinvoice.paidinvoice.payment_failed- ✅ **Security**: Signature verification, tenant validation, duplicate protection
3. **Stripe Secrets (Fly.io)**
- ✅
STRIPE_SECRET_KEY - ✅
STRIPE_WEBHOOK_SECRET - ✅ All price IDs configured
---
⚠️ Issues Found
**Issue #1: Settings Page Doesn't Handle Success Parameter**
**Problem**: When Stripe redirects to /settings?success=true&trial=true, the page doesn't show a success message.
**Current code** (/app/settings/page.tsx):
export default function SettingsPage() {
return (
<div>
<h2>Profile</h2>
<p>Manage your profile settings here.</p>
</div>
);
}**Fix**: Update to handle success/trial parameters:
'use client'
import { useSearchParams } from 'next/navigation'
import { useEffect } from 'react'
import { toast } from 'sonner'
export default function SettingsPage() {
const searchParams = useSearchParams()
useEffect(() => {
const success = searchParams.get('success')
const trial = searchParams.get('trial')
if (success === 'true') {
if (trial === 'true') {
toast.success('🎉 Trial verified! Your workspace has been upgraded to the Team plan.')
} else {
toast.success('✅ Payment successful! Your subscription is now active.')
}
// Clear the URL parameters
window.history.replaceState({}, '', '/settings')
}
}, [searchParams])
return (
<div>
<h2 className="text-xl font-semibold mb-4">Settings</h2>
<p>Manage your workspace settings here.</p>
</div>
)
}---
**Issue #2: Missing Success URL Parameter for Stripe Dashboard**
The success URL should include {CHECKOUT_SESSION_ID} for verification:
**Current**:
success_url: `${tenantBaseUrl}/settings?success=true`**Recommended**:
success_url: `${tenantBaseUrl}/settings?success=true&session_id={CHECKOUT_SESSION_ID}`This allows you to verify the session in Stripe if needed.
---
**Issue #3: Price ID Validation**
**Status**: ✅ Validation exists but might be using placeholders
**Check your environment variables**:
# On Fly.io
fly secrets list -a atom-saas | grep STRIPE_PRICE
# Should show real price IDs like:
# STRIPE_PRICE_SOLO_MONTHLY = price_1Sn09eGHtIVNNi8sSVFY32U2
# STRIPE_PRICE_TEAM_MONTHLY = price_1SnJ2UGHtIVNNi8sUGQfPOm2
# STRIPE_PRICE_ENTERPRISE_MONTHLY = price_1SnJ8BGHtIVNNi8sCdtGwN25**If still using placeholders**, update in Stripe Dashboard:
- Go to **Products** → Find your price
- Copy the **Price ID** (starts with
price_) - Set as environment variable
---
📋 Complete Stripe Flow
**Step 1: User Clicks Upgrade**
**Frontend** (/pricing/page.tsx):
const response = await fetch('/api/billing/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
priceId: 'price_...',
successUrl: `${window.location.origin}/settings?success=true&session_id={CHECKOUT_SESSION_ID}`
}),
})
window.location.href = data.url // Redirects to Stripe Checkout**Step 2: Stripe Checkout**
- User enters payment details
- Stripe processes payment
- Stripe creates
checkout.session.completedevent
**Step 3: Webhook Processing**
**Backend** (/api/v1/stripe/webhook):
@router.post("/webhook")
async def stripe_webhook(request: Request):
event = stripe.Webhook.construct_event(payload, signature, webhook_secret)
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
tenant_id = session['metadata']['tenant_id']
# Update tenant plan
# Update subscription_id
# Send confirmation email**Step 4: Success Redirect**
- Stripe redirects to:
https://atomagentos.com/settings?success=true - Settings page shows success toast
- (Optional) Verify session with Stripe API
---
🔧 Required Actions
**1. Update Settings Page** (HIGH PRIORITY)
- [ ] Add success/trial parameter handling
- [ ] Show success toast message
- [ ] Clear URL parameters after showing message
**2. Add Webhook to Stripe Dashboard** (CRITICAL)
**Webhook URL**: https://atomagentos.com/api/v1/stripe/webhook
**Events to select**:
- [x]
checkout.session.completed - [x]
customer.subscription.created - [x]
customer.subscription.updated - [x]
customer.subscription.deleted - [x]
invoice.paid - [x]
invoice.payment_failed
**3. Verify Price IDs**
- [ ] Check all price IDs are real (not placeholders)
- [ ] Test checkout flow with real payment
**4. Test End-to-End**
- [ ] Create test checkout session
- [ ] Complete payment
- [ ] Verify webhook fires
- [ ] Check tenant plan updates
- [ ] Verify success page appears
---
📝 Stripe Dashboard Configuration
**Webhook Settings**
- **URL**:
https://atomagentos.com/api/v1/stripe/webhook - **Events**: All 6 events listed above
- **HTTP Method**: POST
- **Signing Secret**: Already configured (
STRIPE_WEBHOOK_SECRET)
**Product/Price Configuration**
| Plan | Price ID Env Var | Amount | Description |
|---|---|---|---|
| Solo | STRIPE_PRICE_SOLO_MONTHLY | $19/mo | For individuals |
| Team | STRIPE_PRICE_TEAM_MONTHLY | $79/mo | For growing teams |
| Enterprise | STRIPE_PRICE_ENTERPRISE_MONTHLY | $299/mo | Unlimited |
---
✅ Deployment Status
**Current Deployment**: ✅ Live on https://atomagentos.com
**Changes Deployed**:
- ✅ ACU tracking for skill execution
- ✅ Commit:
2b1934d3b - ✅ Pushed to GitHub
- ✅ Deployed to Fly.io
---
🚀 Next Steps
- **Add webhook URL to Stripe Dashboard** (5 minutes)
- **Update settings page** to handle success parameter (15 minutes)
- **Test checkout flow** (10 minutes)
- **Verify webhook delivery** in logs
Need help with any of these?