Complete setup guide for Stripe subscriptions with webhook integration.
This guide covers:
- Basic Stripe configuration (API keys, products, prices)
- Critical webhook setup (the complex part)
- Testing and troubleshooting
- Go to Stripe Dashboard → Products
- Click "Add product"
- Create a product:
- Name: "Professional Plan"
- Description: "Premium features for power users"
- Add pricing:
- Type: Recurring
- Price: $10.00
- Billing period: Monthly
- Currency: USD
- Save and copy the Price ID (starts with
price_)
Add these to your .env file:
# Stripe API Keys
STRIPE_PUBLISHABLE_KEY=pk_live_... # or pk_test_... for testing
STRIPE_SECRET_KEY=sk_live_... # or sk_test_... for testing
STRIPE_WEBHOOK_SECRET=whsec_... # Get this from webhook setup (Part 2)
# Stripe Price IDs (copy from step 1.1)
STRIPE_PRICE_PREMIUM_MONTHLY=price_1ABC123def456
STRIPE_PRICE_PREMIUM_YEARLY=price_1XYZ789ghi012Note: The Django settings are already configured with DJSTRIPE_WEBHOOK_VALIDATION = 'retrieve_event' to avoid signature validation complexity.
Run these commands in order:
# 1. Create API key in djstripe database
python manage.py shell -c "
from djstripe.models import APIKey
import os
secret_key = os.getenv('STRIPE_SECRET_KEY', '')
livemode = secret_key.startswith('sk_live_')
api_key, created = APIKey.objects.get_or_create(
secret=secret_key,
defaults={
'livemode': livemode,
'name': f'Auto-created {\"live\" if livemode else \"test\"} key'
}
)
print(f'API Key: {api_key.name} (livemode: {api_key.livemode})')
"
# 2. Sync Stripe account
python manage.py djstripe_sync_models Account
# 3. Sync required models for webhook processing
python manage.py djstripe_sync_models Product Price Plan Invoice Customer
# 4. Associate webhook endpoint with account
python manage.py shell -c "
from djstripe.models import WebhookEndpoint, Account
account = Account.objects.first()
endpoint = WebhookEndpoint.objects.first()
if endpoint and account:
endpoint.djstripe_owner_account = account
endpoint.djstripe_validation_method = 'retrieve_event'
endpoint.save()
print(f'Webhook endpoint configured: {endpoint.url}')
print(f'Associated with account: {account.id}')
else:
print('ERROR: Missing webhook endpoint or account')
"python manage.py shell -c "
from djstripe.models import WebhookEndpoint
endpoint = WebhookEndpoint.objects.first()
print(f'Use this webhook URL in Stripe Dashboard:')
print(f'{endpoint.url}')
"- Go to Stripe Dashboard → Webhooks
- Click your existing webhook or create a new one
- Set the endpoint URL to the output from step 2.2
- Select these events:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
- Save the webhook
- Copy the Signing Secret (starts with
whsec_) and add it to your.envfile asSTRIPE_WEBHOOK_SECRET
./deploy.sh restart
# or
python manage.py runserver # for development- Go to
/pricing/while logged in - Click "Upgrade to Professional"
- Complete test payment in Stripe Checkout
- Verify user becomes premium:
python manage.py shell -c "
from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.get(email='YOUR_EMAIL')
print(f'User {user.email} is_premium: {user.is_premium}')
"# Check recent logs for successful webhook processing
tail -20 logs/citis.log | grep -E "(stripe|webhook)" -i
# Should see successful Stripe API calls with 200 responses- Missing Stripe price IDs in environment variables
- Add
STRIPE_PRICE_PREMIUM_MONTHLYto your.envfile
- Wrong webhook URL in Stripe Dashboard
- The webhook URL must use the
djstripe_uuidfield, not theidfield - Run step 2.2 to get the correct URL with proper
djstripe_uuid
- Missing account association
- Run steps 2.1 commands in order
- Missing synced models
- Run:
python manage.py djstripe_sync_models Product Price Plan Invoice Customer
- Webhook validation method is wrong
- Ensure
endpoint.djstripe_validation_method = 'retrieve_event'is set
- Webhook not processing correctly
- Check logs with:
tail -50 logs/citis.log | grep -E "(error|stripe)" -i - Verify webhook URL is correct in Stripe Dashboard
- Use
sk_test_andpk_test_keys - Webhook events are test events
- Use Stripe's test card numbers
- Use
sk_live_andpk_live_keys - Real payments and webhook events
- Ensure webhook URL matches your production domain
- Never commit API keys to version control
- Use environment variables for all sensitive data
- Use
retrieve_eventvalidation to avoid signature complexity - Monitor webhook failures in Stripe Dashboard
If you still have issues after following this guide, check the Django logs (logs/citis.log) for specific error messages and consult the troubleshooting section above.