This guide will help you complete the Stripe integration for SciWeave billing with support for both monthly and annual billing options.
- Stripe account with Dashboard access
- Environment variables properly configured
- Database migration completed
In your Stripe Dashboard, create products with BOTH monthly and annual pricing:
- Monthly Price: Create recurring price with 1-month interval
- Annual Price: Create recurring price with 1-year interval
- Copy both price IDs (format:
price_xxxxx...)
- Monthly Price: Create recurring price with 1-month interval
- Annual Price: Create recurring price with 1-year interval
- Copy both price IDs
- Monthly Price: Create recurring price with 1-month interval
- Annual Price: Create recurring price with 1-year interval
- Copy both price IDs
Edit /desci-server/src/config/stripe.ts and replace the example price IDs:
export const STRIPE_PRICE_IDS = {
AI_REFEREE_FINDER: {
MONTHLY: 'price_YOUR_ACTUAL_MONTHLY_PRICE_ID', // ← Replace this
ANNUAL: 'price_YOUR_ACTUAL_ANNUAL_PRICE_ID', // ← Replace this
},
OMNI_CHATS: {
MONTHLY: 'price_YOUR_ACTUAL_MONTHLY_PRICE_ID', // ← Replace this
ANNUAL: 'price_YOUR_ACTUAL_ANNUAL_PRICE_ID', // ← Replace this
},
PREMIUM: {
MONTHLY: 'price_YOUR_ACTUAL_MONTHLY_PRICE_ID', // ← Replace this
ANNUAL: 'price_YOUR_ACTUAL_ANNUAL_PRICE_ID', // ← Replace this
},
};Add these to your .env file:
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_xxxxx... # Your secret key
STRIPE_WEBHOOK_SECRET=whsec_xxxxx... # Webhook endpoint secret- In Stripe Dashboard → Developers → Webhooks
- Add endpoint:
https://your-domain.com/v1/stripe/webhook - Select these events:
customer.createdcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.createdinvoice.payment_succeededinvoice.payment_failedpayment_method.attachedpayment_method.detached
- Copy the webhook signing secret
cd desci-server
npx prisma migrate dev --name add_billing_interval_support
npx prisma generateThe configuration includes example pricing. Update the pricing section in /desci-server/src/config/stripe.ts to match your actual prices:
pricing: {
monthly: { amount: 29, currency: 'USD' },
annual: { amount: 290, currency: 'USD', savings: '17%' },
}curl -X POST https://your-domain.com/v1/stripe/subscription/checkout \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"priceId": "price_monthly_ai_referee_finder",
"successUrl": "https://your-domain.com/success",
"cancelUrl": "https://your-domain.com/cancel"
}'curl -X POST https://your-domain.com/v1/stripe/subscription/checkout \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"priceId": "price_annual_ai_referee_finder",
"successUrl": "https://your-domain.com/success",
"cancelUrl": "https://your-domain.com/cancel"
}'curl https://your-domain.com/v1/stripe/pricingThe pricing API endpoint returns both monthly and annual options:
// Example API response from /v1/stripe/pricing
{
"plans": [
{
"planName": "AI_REFEREE_FINDER",
"name": "AI Referee Finder",
"planType": "AI_REFEREE_FINDER",
"features": ["AI-powered referee recommendations", "Advanced analytics"],
"pricing": {
"monthly": { "amount": 29, "currency": "USD" },
"annual": { "amount": 290, "currency": "USD", "savings": "17%" }
},
"priceIds": {
"MONTHLY": "price_monthly_ai_referee_finder",
"ANNUAL": "price_annual_ai_referee_finder"
}
}
]
}- ✅ Stripe products and prices created (both monthly and annual)
- ✅ Price IDs updated in config file
- ✅ Environment variables set
- ✅ Webhook endpoint configured and tested
- ✅ Database migration completed
- ✅ Test subscriptions work for both billing intervals
- ✅ Billing interval properly detected and stored in database
- Backend: Handles webhooks, database operations, subscription management
- Frontend: Makes API calls to backend, no direct Stripe integration
- Billing Detection: Automatically detects monthly vs annual from Stripe price IDs
- Database: Tracks
billingIntervalfield alongside subscription data
- Ensure price IDs in config exactly match your Stripe Dashboard
- Check that helper functions in
stripe.tsare working correctly
- Verify webhook secret matches Stripe Dashboard
- Ensure raw body parsing is enabled for webhook endpoint
- Run
npx prisma db pushif migration fails - Check that
BillingIntervalenum is properly added
Your Stripe integration with monthly and annual billing support is now complete! 🎉