Reusable subscription & feature gating library for FastAPI with Paddle integration
Project description
📦 Paygate
Reusable subscription & feature gating library for FastAPI with Paddle integration
Paygate is a Python library that provides subscription management and feature gating for FastAPI applications. It integrates seamlessly with Paddle to handle subscription lifecycles, enforce feature access based on subscription tiers, and track usage limits.
✨ Features
- 🔐 Feature Gating: Control access to features based on subscription plans
- 📊 Usage Limiting: Track and enforce usage limits per feature
- 🎣 Paddle Integration: Handle subscription webhooks automatically
- 🗄️ Database Ready: SQLAlchemy mixin for easy integration
- 🎯 FastAPI Native: Built specifically for FastAPI applications
- 🧪 Testing Friendly: Easy to mock and test
- 🔧 Configurable: Each app defines its own plans and features
🚀 Installation
pip install paygate
🏁 Quick Start
1. Define Your Subscription Plans
# yourapp/config/subscription_plans.py
PLANS = {
"free": {
"features": ["basic_usage", "ai_explain"],
"limits": {"ai_explain": 2},
"monthly_price": 0,
"yearly_price": 0,
},
"pro": {
"features": ["replay", "ai_explain", "advanced_features"],
"limits": {"ai_explain": 20},
"monthly_price": 9,
"yearly_price": 90,
"paddle_product_id": "prod_pro123"
},
"enterprise": {
"features": ["replay", "ai_explain", "advanced_features", "priority_support"],
"limits": {"ai_explain": 100},
"monthly_price": 49,
"yearly_price": 490,
"paddle_product_id": "prod_enterprise456"
}
}
2. Extend Your User Model
# yourapp/models.py
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from paygate import SubscriptionMixin
class Base(DeclarativeBase):
pass
class User(Base, SubscriptionMixin):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(String(255), unique=True)
# ... other user fields
# SubscriptionMixin adds subscription fields automatically
3. Initialize Paygate
# yourapp/main.py
from fastapi import FastAPI
import paygate
from yourapp.config.subscription_plans import PLANS
app = FastAPI()
# Initialize paygate with your plans
paygate.initialize_paygate(PLANS)
# Set up user handlers for webhooks
async def lookup_user(identifier: str):
# Find user by email or paddle_subscription_id
# Return user object or None
pass
async def update_user(user, update_data: dict):
# Update user subscription fields
# Save to database
pass
paygate.set_user_handlers(lookup_user, update_user)
4. Add Paddle Webhook Endpoint
# Add to your FastAPI app
from paygate import create_paddle_router
app.include_router(create_paddle_router())
5. Use Feature Gating
from fastapi import Depends
from paygate import requires_feature, requires_feature_with_limit
@app.post("/api/explain")
@requires_feature_with_limit("ai_explain", period="monthly")
async def explain_code(
code: str,
user: User = Depends(get_current_user)
):
# This endpoint requires ai_explain feature
# Usage will be automatically tracked and limited
return {"explanation": "..."}
@app.get("/api/advanced-feature")
@requires_feature("advanced_features")
async def advanced_endpoint(user: User = Depends(get_current_user)):
# Only users with plans that include "advanced_features" can access this
return {"data": "advanced stuff"}
📋 Environment Variables
# Required for webhook verification
PADDLE_WEBHOOK_SECRET=your_paddle_webhook_secret
# Optional - for future Paddle API integration
PADDLE_VENDOR_ID=your_paddle_vendor_id
PADDLE_API_KEY=your_paddle_api_key
PADDLE_PUBLIC_KEY=your_paddle_public_key
# Optional
PAYGATE_ENVIRONMENT=production # or development
🎯 Usage Limiting
Paygate supports sophisticated usage tracking:
from paygate import check_feature_limit, increment_feature_usage
# Check if user can use a feature
if await check_feature_limit(user, "ai_explain"):
# User is within limits
result = perform_ai_explain()
# Manually increment usage
await increment_feature_usage(user, "ai_explain")
return result
else:
raise HTTPException(429, "Usage limit exceeded")
Custom Usage Stores
By default, paygate uses in-memory storage. For production, use Redis:
import redis.asyncio as redis
from paygate import RedisUsageStore, set_usage_store
# Set up Redis usage store
redis_client = redis.Redis(host='localhost', port=6379, db=0)
usage_store = RedisUsageStore(redis_client)
set_usage_store(usage_store)
🧪 Testing
Paygate is designed to be easily testable:
import pytest
from paygate import initialize_paygate, has_feature
# Test plan configuration
TEST_PLANS = {
"free": {"features": ["basic"], "limits": {"basic": 5}},
"pro": {"features": ["basic", "advanced"], "limits": {"basic": 50}}
}
def test_feature_access():
initialize_paygate(TEST_PLANS)
user = MockUser(subscription_plan="pro")
assert has_feature(user, "basic") == True
assert has_feature(user, "advanced") == True
assert has_feature(user, "premium") == False
🔧 API Reference
Core Functions
initialize_paygate(plans)- Initialize with your plan configurationhas_feature(user, feature)- Check if user has access to a featureget_limit(user, feature)- Get usage limit for a featurerequires_feature(feature)- Decorator for feature gatingrequires_feature_with_limit(feature)- Decorator with usage limiting
Models
SubscriptionMixin- SQLAlchemy mixin for user models
Webhook Handling
handle_webhook(request)- Process Paddle webhookscreate_paddle_router()- Create FastAPI router with webhook endpointset_user_handlers(lookup, update)- Configure user management functions
🗺️ Roadmap
- Stripe integration
- Admin override UI
- Plan hierarchy system
- Paddle Checkout helpers
- Analytics and reporting
- Feature flags integration
📄 License
MIT License - see LICENSE file for details.
🤝 Contributing
Contributions welcome! Please read our contributing guidelines and submit pull requests.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paygate-0.1.0.tar.gz.
File metadata
- Download URL: paygate-0.1.0.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb235d186ae23ca486cd6b41483979c5a210253a16cd25db0a00cc9989957635
|
|
| MD5 |
ffce683b3164e551cf441c30752e2445
|
|
| BLAKE2b-256 |
301953317533ff9d67ab2255baa6f1463ecdd57dde06a3f8585e014cbfab63bf
|
File details
Details for the file paygate-0.1.0-py3-none-any.whl.
File metadata
- Download URL: paygate-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
554bc7fdf290ffc32ca7cbc892aea9e72737295459405555b9072e5a308ab1f7
|
|
| MD5 |
53fa437cca9f47387907004ad4218abc
|
|
| BLAKE2b-256 |
f42d21dab42f2499bce94787bed93372347c9e38d54e8ba3312dd6c941553240
|