Python SDK for SnapPay payment and subscription platform
Project description
SnapPay Python SDK
A modern, production-ready Python SDK for integrating with SnapPay's payment and subscription platform. Built with async/await support, comprehensive error handling, and enterprise-grade features.
✨ Features
- 🚀 Async/Await Support: Built on aiohttp for high-performance async operations
- 🔄 Automatic Retry Logic: Smart exponential backoff with jitter
- 🛡️ Type Safety: Full type hints and TypedDict definitions
- 📊 Usage Tracking: Built-in metered billing support
- 🔐 Access Control: Feature-based access management
- 📡 Real-time Events: SSE support for webhook events
- 🎯 Idempotency: Prevent duplicate operations
- 📝 Comprehensive Logging: Detailed request/response logging
- 🧪 Well Tested: Extensive test coverage with mocks
- 📚 Rich Documentation: Detailed examples and API documentation
📦 Installation
pip install snappay
For development:
pip install snappay[dev]
🚀 Quick Start
import asyncio
from snappay import SnapPay
async def main():
# Initialize client with API key
async with SnapPay(api_key="pk_test_your_api_key") as client:
# Create or retrieve a customer
customer = await client.customers.get(
cusId="user_123",
email="user@example.com",
name="John Doe"
)
# Create a checkout session
checkout = await client.checkout.create_session(
customer_id=customer["customer_id"],
product_id="pro_monthly",
success_url="https://example.com/success",
cancel_url="https://example.com/cancel"
)
print(f"Checkout URL: {checkout['url']}")
# Run the async function
asyncio.run(main())
📖 Configuration
Environment Variables
export SNAPPAY_API_KEY="pk_test_your_api_key"
export SNAPPAY_BASE_URL="https://api.snappay.dev" # Optional
export SNAPPAY_MAX_RETRIES="3" # Optional
export SNAPPAY_TIMEOUT="30" # Optional
Advanced Configuration
from snappay import SnapPay, SnapPayConfig
from snappay.config import RetryConfig, TimeoutConfig
# Create custom configuration
config = SnapPayConfig(
api_key="pk_test_your_api_key",
base_url="https://api.snappay.dev",
retry=RetryConfig(
max_retries=5,
base_delay=1.0,
max_delay=60.0,
jitter=True
),
timeout=TimeoutConfig(
total=30,
connect=10
),
logging={
"enabled": True,
"level": "DEBUG",
"log_requests": True,
"log_responses": True,
"redact_sensitive": True
}
)
# Use custom configuration
async with SnapPay(config=config) as client:
# Your code here
pass
🔧 Core Features
Customer Management
# Create or get customer
customer = await client.customers.get(
cusId="user_123",
email="user@example.com",
name="John Doe",
metadata={"source": "mobile_app", "plan": "free"}
)
# Update customer
updated = await client.customers.update_customer(
customer_id=customer["customer_id"],
name="Jane Doe",
metadata={"plan": "pro"}
)
# List customers with pagination
customers = await client.customers.list_customers(
limit=20,
starting_after="cus_abc123"
)
# Get customer by email
customer = await client.customers.get_customer_by_email("user@example.com")
# Delete customer (soft delete)
success = await client.customers.delete_customer(customer["customer_id"])
Checkout Sessions
# Create checkout session
checkout = await client.checkout.create_session(
customer_id="cus_123",
product_id="pro_monthly",
success_url="https://example.com/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://example.com/cancel",
metadata={
"campaign": "summer_sale",
"referrer": "blog"
}
)
print(f"Send customer to: {checkout['url']}")
Access Control
# Check feature access
access = await client.access.check(
customer_id="cus_123",
feature_id="premium_features"
)
if access["has_access"]:
print(f"Access granted! Remaining: {access.get('usage_remaining', 'Unlimited')}")
else:
print("Access denied - subscription required")
Usage Tracking
# Track usage for metered features
result = await client.usage.track(
customer_id="cus_123",
feature_id="api_calls",
usage=25,
idempotency_key="unique_key_123" # Prevent duplicates
)
# Get current usage
usage = await client.usage.get(
customer_id="cus_123",
feature_id="api_calls"
)
print(f"Used: {usage['total_usage']} / {usage.get('limit', 'Unlimited')}")
Real-time Events (SSE)
# Subscribe to webhook events via SSE
def handle_subscription_created(event):
print(f"New subscription: {event.customer_id}")
print(f"Data: {event.event_data}")
def handle_payment_failed(event):
print(f"Payment failed for: {event.customer_id}")
# Register event handlers
client.on_event("subscription.created", handle_subscription_created)
client.on_event("invoice.payment.failed", handle_payment_failed)
# Start listening
await client.start_events()
# Keep running
await asyncio.sleep(3600) # Listen for 1 hour
# Stop listening
await client.stop_events()
Event Streaming with Async Generator
# Stream events using async generator
async for event in client.stream_events():
print(f"Event: {event.webhook_event_type}")
print(f"Customer: {event.customer_id}")
print(f"Data: {event.event_data}")
# Process specific events
if event.webhook_event_type == "subscription.created":
await process_new_subscription(event)
🔒 Error Handling
The SDK provides comprehensive error handling with specific exception types:
from snappay.types import (
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError,
ConflictError,
PaymentError,
ServerError,
SnapPayError
)
try:
customer = await client.customers.get("user_123")
except AuthenticationError as e:
print(f"Invalid API key: {e}")
except ValidationError as e:
print(f"Invalid parameters: {e}")
print(f"Failed parameter: {e.details.get('param')}")
except NotFoundError as e:
print(f"Resource not found: {e}")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after} seconds")
except SnapPayError as e:
print(f"API error: {e}")
print(f"Request ID: {e.request_id}")
🔄 Retry Logic
The SDK includes automatic retry with exponential backoff:
from snappay.utils import retry_on_failure
# Automatic retry for transient failures
@retry_on_failure(max_retries=3, base_delay=1.0)
async def critical_operation():
return await client.customers.get("user_123")
# Or configure globally
config = SnapPayConfig(
api_key="pk_test_key",
retry={"max_retries": 5, "base_delay": 2.0, "max_delay": 60.0}
)
📊 Pagination
Handle paginated responses efficiently:
# Manual pagination
all_customers = []
has_more = True
starting_after = None
while has_more:
response = await client.customers.list_customers(
limit=100,
starting_after=starting_after
)
all_customers.extend(response["data"])
has_more = response.get("has_more", False)
if response["data"]:
starting_after = response["data"][-1]["customer_id"]
# Or use the built-in paginate helper (for services that support it)
all_items = await client._paginate(
endpoint="/api/v1/customers",
limit=100,
max_items=1000 # Stop after 1000 items
)
🧪 Testing
Run tests with pytest:
# Run all tests
pytest
# Run with coverage
pytest --cov=snappay
# Run specific test file
pytest tests/test_client.py
# Run with verbose output
pytest -v
🛠️ Development
Setup Development Environment
# Clone repository
git clone https://github.com/snappay/snappay-sdk-py.git
cd snappay-sdk-py
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install
Code Quality
# Format code
black .
# Sort imports
isort .
# Type checking
mypy snappay
📚 Examples
See the example/ directory for comprehensive examples:
basic_usage.py- Basic SDK operationsadvanced_usage.py- Advanced features and patternssse_basic.py- Real-time event streaming
🤝 Contributing
We welcome contributions! Please see our Contributing Guidelines for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
🙏 Acknowledgments
Built with ❤️ by the SnapPay team. Special thanks to all our contributors and users.
Ready to integrate payments in minutes? Get started with SnapPay today!
# It's as simple as this!
async with SnapPay(api_key="your_key") as client:
checkout = await client.checkout.create_session(
customer_id="cus_123",
product_id="pro_plan",
success_url="https://yourapp.com/success"
)
print(f"Send customer to: {checkout['url']}")
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 snappay-0.0.1b0.tar.gz.
File metadata
- Download URL: snappay-0.0.1b0.tar.gz
- Upload date:
- Size: 42.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e602edce1b982f07f1f7688a1ed6f216c5827ac9b090e3b4a90f16655b7957f
|
|
| MD5 |
c8d5d15702c21c8717044fda99619a15
|
|
| BLAKE2b-256 |
1c8b7b670f9b26635be36ddb28e8766a51ac0162dfbb58250a2bf4e72955d818
|
File details
Details for the file snappay-0.0.1b0-py3-none-any.whl.
File metadata
- Download URL: snappay-0.0.1b0-py3-none-any.whl
- Upload date:
- Size: 41.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a00e09d2a561c4fcbb8107ad9a258f850568605ce25ab2373dde29542fb08a3
|
|
| MD5 |
3eb48a18b9a6a3700a39f960f680ccd7
|
|
| BLAKE2b-256 |
93f14cea0df27ce74497edfe47cb6706df706e6d1e3fadaec7fe7fc6227b3869
|