# BagelPay Python SDK
A comprehensive Python client library for the BagelPay API, providing developers with an easy-to-use payment integration solution.
## ๐ Table of Contents
- [Quick Start](#quick-start)
- [Installation Guide](#installation-guide)
- [Basic Configuration](#basic-configuration)
- [Beginner Tutorial](#beginner-tutorial)
- [API Reference](#api-reference)
- [Example Code](#example-code)
- [Error Handling](#error-handling)
- [Testing Guide](#testing-guide)
- [Development Guide](#development-guide)
- [Advanced Usage](#advanced-usage)
- [Best Practices](#best-practices)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
## ๐ Quick Start
### 30-Second Quick Demo
```python
from bagelpay import BagelPayClient, CheckoutRequest, Customer
# 1. Initialize the client
client = BagelPayClient(
base_url="https://test.bagelpay.io",
api_key="your-test-api-key-here"
)
# 2. Create a payment session
from datetime import datetime
checkout_request = CheckoutRequest(
product_id="prod_123456789",
request_id=f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
units="1",
customer=Customer(
email="customer@example.com"
),
success_url="https://yoursite.com/success",
metadata={
"order_id": f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
}
)
# 3. Get payment URL
response = client.create_checkout(checkout_request)
print(f"Payment URL: {response.checkout_url}")
```
## ๐ฆ Installation Guide
### System Requirements
- **Python**: 3.11 or higher (recommended), minimum 3.8
- **Package Manager**: pip or poetry
- **Operating System**: Windows, macOS, Linux
- **Memory**: Minimum 512MB RAM
- **Network**: Internet connection for API calls
### Method 1: Install from Source (Recommended)
```bash
# Clone the repository
git clone https://github.com/bagelpay/bagelpay-sdk-python.git
cd bagelpay-sdk-python/generated-sdks/python
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # Linux/Mac
# or venv\Scripts\activate # Windows
# Install SDK in development mode
pip install -e .
# Verify installation
python -c "import bagelpay; print('Installation successful!')"
```
### Method 2: Install from PyPI (Coming Soon)
```bash
# Install latest stable version
pip install bagelpay-sdk
# Install specific version
pip install bagelpay-sdk==1.0.0
# Install with optional dependencies
pip install bagelpay-sdk[dev,test]
```
### Method 3: Using Poetry
```bash
# Add to your project
poetry add bagelpay-sdk
# Or add from git repository
poetry add git+https://github.com/bagelpay/bagelpay-sdk-python.git
```
### Verify Installation
```python
import bagelpay
from bagelpay import BagelPayClient
print(f"BagelPay SDK Version: {bagelpay.__version__}")
print(f"Available modules: {dir(bagelpay)}")
# Test basic functionality
try:
client = BagelPayClient(api_key="test")
print("โ
SDK imported successfully")
except Exception as e:
print(f"โ Import failed: {e}")
```
## โ๏ธ Basic Configuration
### Getting API Keys
1. **Sign up**: Create account at [BagelPay Dashboard](https://dashboard.bagelpay.io)
2. **Navigate**: Go to "Developer Settings" โ "API Keys"
3. **Create Key**: Generate new API key for your environment
4. **Copy**: Save your test and live keys securely
5. **Environment**: Start with test keys for development
### Environment Variables Setup
```bash
# Create .env file in your project root
echo "BAGELPAY_API_KEY=your-test-api-key-here" > .env
echo "BAGELPAY_BASE_URL=https://test.bagelpay.io" >> .env
echo "BAGELPAY_TIMEOUT=30" >> .env
echo "BAGELPAY_DEBUG=false" >> .env
# Load environment variables
export $(cat .env | xargs)
# Or use python-dotenv
pip install python-dotenv
```
### Client Initialization Options
```python
from bagelpay import BagelPayClient
import os
# Method 1: Direct parameters
client = BagelPayClient(
base_url="https://test.bagelpay.io",
api_key="your-api-key",
timeout=30, # Request timeout in seconds
)
# Method 2: Configuration dictionary
config = {
"base_url": "https://test.bagelpay.io",
"api_key": os.getenv("BAGELPAY_API_KEY"),
"timeout": 30
}
client = BagelPayClient(**config)
# Method 4: Context manager (recommended for production)
with BagelPayClient(api_key="your-api-key") as client:
# Automatically handles connection cleanup
response = client.list_products()
print(f"Found {response.total} products")
```
### Environment-Specific Configuration
```python
# Development environment
dev_client = BagelPayClient(
base_url="https://test.bagelpay.io",
api_key="test_key_xxx",
timeout=60
)
# Staging environment
staging_client = BagelPayClient(
base_url="https://staging.bagelpay.io",
api_key="staging_key_xxx",
timeout=30
)
# Production environment
production_client = BagelPayClient(
base_url="https://api.bagelpay.io",
api_key="live_key_xxx",
timeout=15,
)
```
## ๐ Beginner Tutorial
### Step 1: Create Your First Product
```python
from bagelpay import BagelPayClient, CreateProductRequest
# Initialize client
client = BagelPayClient(api_key="your-test-api-key")
# Create a digital product
product_request = CreateProductRequest(
name="Premium Membership",
description="Access to all premium features with monthly billing",
price=29.99,
currency="USD",
billing_type="subscription", # subscription or single_payment
tax_inclusive=True,
tax_category="digital_products", # digital_products, saas_services or ebooks
recurring_interval="daily", # daily, weekly, monthly, 3months or 6months
trial_days=1,
)
try:
product = client.create_product(product_request)
print(f"โ
Product created successfully!")
print(f"Product ID: {product.product_id}")
print(f"Product Name: {product.name}")
print(f"Price: ${product.price} {product.currency}")
except Exception as e:
print(f"โ Failed to create product: {e}")
```
### Step 2: Create a Payment Session
```python
from bagelpay import CheckoutRequest, Customer
# Prepare customer information
customer = Customer(
email="john.doe@example.com"
)
# Create checkout request
from datetime import datetime
checkout_request = CheckoutRequest(
product_id=product.product_id, # Use the product ID from step 1
request_id=f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
units="1",
customer=customer,
success_url="https://yoursite.com/success",
metadata={
"order_id": f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
"user_id": "user_12345",
"source": "web_app",
"campaign": "summer_promotion"
}
)
try:
checkout_response = client.create_checkout(checkout_request)
print(f"โ
Checkout session created!")
print(f"Payment URL: {checkout_response.checkout_url}")
print(f"Payment ID: {checkout_response.payment_id}")
print(f"Product ID: {checkout_response.product_id}")
print(f"Status: {checkout_response.status}")
print(f"Expires On: {checkout_response.expires_on}")
# Store payment ID for later reference
payment_id = checkout_response.payment_id
except Exception as e:
print(f"โ Failed to create checkout: {e}")
```
### Step 3: Monitor Transactions
```python
# Get transaction history
try:
transactions = client.list_transactions(pageNum=1, pageSize=20)
print(f"\n๐ Transaction Summary:")
print(f"Total Transactions: {transactions.total}")
print(f"Showing {len(transactions.items)} transactions on this page")
print(f"Items per Page: 20")
except Exception as e:
print(f"โ Failed to fetch transactions: {e}")
```
### Step 4: Manage Products
```python
# List all products
try:
products = client.list_products(pageNum=1, pageSize=50)
print(f"\n๐๏ธ Product Catalog ({products.total} total):")
for product in products.items:
status = "๐ข Active" if not product.is_archive else "๐ด Archived"
print(f"\n{status} {product.name}")
print(f" ID: {product.product_id}")
if product.recurring_interval:
print(f" Price: ${product.price} {product.currency}/{product.recurring_interval}")
else:
print(f" Price: ${product.price} {product.currency}")
print(f" Type: {product.billing_type}")
print(f" Created: {product.created_at}")
# Update a product
if products.items:
first_product = products.items[0]
from bagelpay import UpdateProductRequest
import random
update_request = UpdateProductRequest(
product_id=first_product.product_id,
name="New_Product_" + str(random.randint(1000, 9999)),
description="New_Description_of_product_" + str(random.randint(1000, 9999)),
price=random.uniform(50.5, 1024.5),
currency="USD",
billing_type=random.choice(["subscription", "subscription", "single_payment"]),
tax_inclusive=False,
tax_category=random.choice(["digital_products", "saas_services", "ebooks"]),
recurring_interval=random.choice(["daily", "weekly", "monthly", "3months", "6months"]),
trial_days=random.choice([0, 1, 7])
)
updated_product = client.update_product(update_request)
print(f"\nโ
Updated product: {updated_product.name}")
print(f" New price: ${updated_product.price}")
except Exception as e:
print(f"โ Failed to manage products: {e}")
```
## ๐ง API Reference
### Product Management API
#### Creating Products
```python
# One-time payment product
one_time_product = CreateProductRequest(
name="E-book: Python Programming Guide",
description="Comprehensive guide to Python programming",
price=49.99,
currency="USD",
billing_type="single_payment",
tax_inclusive=False,
tax_category="digital_products",
recurring_interval="none",
trial_days=0
)
# Subscription product
subscription_product = CreateProductRequest(
name="Monthly Pro Plan",
description="Professional features with monthly billing",
price=19.99,
currency="USD",
billing_type="subscription",
tax_inclusive=True,
tax_category="digital_products",
recurring_interval="monthly",
trial_days=14
)
```
#### Product Operations
```python
# Get product details
product = client.get_product("prod_123456")
print(f"Product: {product.name}")
print(f"Status: {'Active' if not product.is_archive else 'Archived'}")
# Archive product (stop selling but keep records)
archived_product = client.archive_product("prod_123456")
print(f"Product archived: {archived_product.is_archive}")
# Unarchive product
unarchived_product = client.unarchive_product("prod_123456")
print(f"Product restored: {not unarchived_product.is_archive}")
# Bulk product operations
all_products = []
page_num = 1
while True:
products = client.list_products(pageNum=page_num, pageSize=100)
all_products.extend(products.items)
if len(products.items) < 100:
break
page_num += 1
print(f"Total products loaded: {len(all_products)}")
# Filter products by criteria
active_products = [p for p in all_products if not p.is_archive]
subscription_products = [p for p in all_products if p.billing_type == "subscription"]
expensive_products = [p for p in all_products if p.price > 100]
print(f"Active products: {len(active_products)}")
print(f"Subscription products: {len(subscription_products)}")
print(f"Premium products (>$100): {len(expensive_products)}")
```
### Payment Session API
#### Advanced Checkout Configuration
```python
# Comprehensive checkout request
from datetime import datetime
advanced_checkout = CheckoutRequest(
product_id="prod_premium_plan",
request_id=f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
units="3",
customer=Customer(
email="premium.user@company.com"
),
success_url="https://yoursite.com/success",
metadata={
# Campaign tracking
"order_id": f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
"campaign_id": "black_friday_2024",
"discount_code": "SAVE30",
"affiliate_id": "partner_123",
# User context
"user_id": "user_789",
"user_tier": "enterprise",
"company": "Tech Corp Inc",
# Analytics
"source": "landing_page",
"medium": "organic",
"referrer": "https://google.com",
"utm_campaign": "product_launch"
}
)
response = client.create_checkout(advanced_checkout)
# Extract detailed checkout information
print(f"\n๐ณ Checkout Session Created:")
print(f"Payment ID: {response.payment_id}")
print(f"Checkout URL: {response.checkout_url}")
print(f"Product ID: {response.product_id}")
print(f"Status: {response.status}")
print(f"Expires On: {response.expires_on}")
print(f"Success URL: {response.success_url}")
```
### Subscription Management API
```python
# Comprehensive subscription management
def manage_subscriptions(client):
"""Manage customer subscriptions"""
try:
subscriptions = client.list_subscriptions(pageNum=1, pageSize=100)
print(f"\n๐ Subscription Management ({subscriptions.total} total):")
active_subs = []
cancelled_subs = []
paused_subs = []
trialing_subs = []
for subscription in subscriptions.items:
print(f"\n๐ Subscription: {subscription.subscription_id}")
print(f" Status: {subscription.status}")
print(f" Customer: {subscription.customer}")
print(f" Product: {subscription.product_name}")
print(f" Next Billing: {subscription.billing_period_end}")
print(f" Next Billing Amount: ${subscription.next_billing_amount}")
if subscription.status == "active":
active_subs.append(subscription)
elif subscription.status == "canceled":
cancelled_subs.append(subscription)
elif subscription.status == "paused":
paused_subs.append(subscription)
elif subscription.status == "trialing":
trialing_subs.append(subscription)
print(f"\n๐ Subscription Summary:")
print(f"Active: {len(active_subs)}")
print(f"Cancelled: {len(cancelled_subs)}")
print(f"Paused: {len(paused_subs)}")
print(f"Trialing: {len(trialing_subs)}")
# Calculate MRR (Monthly Recurring Revenue)
monthly_revenue = sum(
sub.next_billing_amount for sub in active_subs
if sub.recurring_interval == "monthly"
)
annual_revenue = sum(
sub.next_billing_amount / 12 for sub in active_subs
if sub.recurring_interval == "yearly"
)
total_mrr = monthly_revenue + annual_revenue
print(f"๐ฐ Monthly Recurring Revenue: ${total_mrr:.2f}")
return {
"active": len(active_subs),
"cancelled": len(cancelled_subs),
"paused_subs": len(paused_subs),
"trialing_subs": len(trialing_subs),
"mrr": total_mrr
}
except Exception as e:
print(f"โ Error managing subscriptions: {e}")
return None
# Cancel subscription with reason
def cancel_subscription_with_reason(client, subscription_id):
"""Cancel subscription with cancellation reason"""
try:
# Note: This assumes the SDK supports cancellation reasons
result = client.cancel_subscription(
subscription_id,
)
print(f"โ
Subscription {subscription_id} cancelled")
return result
except Exception as e:
print(f"โ Failed to cancel subscription: {e}")
return None
manage_subscriptions(client)
cancel_subscription_with_reason(client, "sub_1966676965965533186")
```
## ๐ก Example Code
The SDK includes comprehensive examples in the `examples/` directory:
### Available Examples
| File | Description | Use Case | Complexity |
|------|-------------|----------|------------|
| `basic_usage.py` | Basic SDK functionality | Getting started | Beginner |
| `checkout_payments.py` | Complete payment flow | E-commerce integration | Intermediate |
| `product_management.py` | Product CRUD operations | Catalog management | Intermediate |
| `subscription_customer_management.py` | Subscription & customer ops | SaaS applications | Advanced |
### Running Examples
```bash
# Set up environment
export BAGELPAY_API_KEY="your-test-api-key"
export BAGELPAY_BASE_URL="https://test.bagelpay.io"
# Run basic example
python examples/basic_usage.py
# Run with verbose output
BAGELPAY_DEBUG=true python examples/checkout_payments.py
```
## โ ๏ธ Error Handling
### Exception Hierarchy
```python
from bagelpay.exceptions import (
BagelPayError, # Base exception class
BagelPayAPIError, # API-related errors
BagelPayAuthenticationError, # Authentication failures
BagelPayValidationError, # Request validation errors
BagelPayNotFoundError, # Resource not found
BagelPayRateLimitError, # Rate limiting
BagelPayNetworkError, # Network connectivity issues
BagelPayTimeoutError # Request timeout
)
# Exception hierarchy:
# BagelPayError
# โโโ BagelPayAPIError
# โ โโโ BagelPayAuthenticationError
# โ โโโ BagelPayValidationError
# โ โโโ BagelPayNotFoundError
# โ โโโ BagelPayRateLimitError
# โโโ BagelPayNetworkError
# โโโ BagelPayTimeoutError
```
## ๐งช Testing Guide
### Test Suite Overview
The SDK includes a comprehensive test suite with multiple testing strategies:
```bash
# Test runner with all options
python run_tests.py --help
# Basic test execution
python run_tests.py # Run all tests
python run_tests.py --unit # Unit tests only
python run_tests.py --integration # Integration tests only
python run_tests.py --mock # Mock mode (no real API calls)
python run_tests.py --coverage # Generate coverage report
python run_tests.py --fast # Parallel execution
python run_tests.py --verbose # Detailed output
```
### Test Configuration
```bash
# Environment setup for testing
export BAGELPAY_API_KEY="test_key_12345"
export BAGELPAY_BASE_URL="https://test.bagelpay.io"
export BAGELPAY_TEST_MODE="true"
export BAGELPAY_DEBUG="false"
# Install test dependencies
pip install pytest pytest-mock pytest-cov pytest-xdist responses
# Or use the setup command
python run_tests.py --setup
```
### Project Structure
```
bagelpay-sdk-python/
โโโ bagelpay/ # Main SDK package
โ โโโ __init__.py # Package initialization
โ โโโ client.py # Main client class
โ โโโ models.py # Data models
โ โโโ exceptions.py # Custom exceptions
โ โโโ utils.py # Utility functions
โโโ examples/ # Example scripts
โ โโโ basic_usage.py # Basic functionality
โ โโโ checkout_payments.py # Payment processing
โ โโโ product_management.py # Product operations
โ โโโ subscription_customer_management.py # Advanced features
โโโ tests/ # Test suite
โ โโโ conftest.py # Test configuration
โ โโโ test_client.py # Client tests
โ โโโ test_models.py # Model tests
โ โโโ test_exceptions.py # Exception tests
โ โโโ test_integration.py # Integration tests
โโโ docs/ # Documentation
โโโ requirements.txt # Dependencies
โโโ setup.py # Package setup
โโโ run_tests.py # Test runner
โโโ pytest.ini # Pytest configuration
โโโ README.md # This file
```
### Contributing Guidelines
1. **Fork and Clone**
```bash
git fork https://github.com/bagelpay/bagelpay-sdk-python.git
git clone https://github.com/yourusername/bagelpay-sdk-python.git
```
2. **Create Feature Branch**
```bash
git checkout -b feature/amazing-new-feature
```
3. **Make Changes**
- Follow existing code style
- Add tests for new functionality
- Update documentation
- Ensure all tests pass
4. **Quality Checks**
```bash
# Run all tests
python run_tests.py --coverage
# Code quality
black bagelpay/
flake8 bagelpay/
mypy bagelpay/
```
5. **Commit and Push**
```bash
git add .
git commit -m "feat: add amazing new feature"
git push origin feature/amazing-new-feature
```
6. **Create Pull Request**
- Provide clear description
- Include test results
- Reference related issues
## ๐ Webhook Integration
```python
import hmac
import hashlib
import json
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import uvicorn
from pyngrok import ngrok
ngrok.set_auth_token("your_ngrok_key")
WEBHOOK_SECRET = "your_webhook_key"
app = FastAPI()
def verify_webhook_signature(signature_data: bytes, signature: str, secret: str) -> bool:
"""Verify webhook signature for security"""
expected_signature = hmac.new(
secret.encode('utf-8'),
signature_data,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected_signature, signature)
@app.post("/api/webhooks")
async def handle_post(request: Request):
"""Handle BagelPay webhook notifications"""
payload = await request.body()
timestamp = request.headers.get('timestamp').encode()
signature = request.headers.get('bagelpay_signature')
# Combine payload and timestamp
signature_data = timestamp + ".".encode() + payload
if not verify_webhook_signature(signature_data, signature, WEBHOOK_SECRET):
return JSONResponse(status_code=401, content={"error": "Invalid signature"})
try:
event = json.loads(payload)
event_type = event.get('event_type')
data = event.get('object')
if event_type == 'checkout.completed':
# handle checkout completed events
print(event)
elif event_type == 'checkout.failed':
# handle checkout failed events
print(event)
elif event_type == 'checkout.cancel':
# handle checkout cancelled events
print(event)
elif event_type == 'subscription.trialing':
# handle subscription trialing events
print(event)
elif event_type == 'subscription.paid':
# handle subscription paid events
print(event)
elif event_type == 'subscription.canceled':
# handle subscription cancelled events
print(event)
elif event_type == 'refund.created':
# handle refund created events
print(event)
else:
print(f"Unhandled event type: {event_type}")
return JSONResponse(status_code=200, content={"message": "Success"})
except Exception as e:
print(f"Webhook processing error: {e}")
return JSONResponse(status_code=500, content={"error": "Processing failed"})
if __name__ == "__main__":
listening_port = "8000"
public_url = ngrok.connect(
addr=listening_port,
proto="http",
hostname="stunning-crane-direct.ngrok-free.app"
)
print(f"ngrok Public URL: {public_url}")
uvicorn.run(app, host="0.0.0.0", port=int(listening_port))
```
## โ FAQ
### General Questions
**Q: What Python versions are supported?**
A: The SDK supports Python 3.8+ with the following recommendations:
- **Recommended**: Python 3.11 or higher
- **Minimum**: Python 3.8
- **Tested on**: Python 3.8, 3.9, 3.10, 3.11, 3.12
**Q: How do I switch between test and production environments?**
```python
# Test environment
test_client = BagelPayClient(
base_url="https://test.bagelpay.io",
api_key="test_key_xxx"
)
# Production environment
prod_client = BagelPayClient(
base_url="https://live.bagelpay.io",
api_key="live_key_xxx"
)
```
**Q: How do I handle webhook verification?**
```python
import hmac
import hashlib
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import uvicorn
from pyngrok import ngrok
ngrok.set_auth_token("your_ngrok_key")
WEBHOOK_SECRET = "your_webhook_key"
app = FastAPI()
def verify_webhook_signature(signature_data: bytes, signature: str, secret: str) -> bool:
"""Verify webhook signature for security"""
expected_signature = hmac.new(
secret.encode('utf-8'),
signature_data,
hashlib.sha256
).hexdigest()
print("expected_signature: ", expected_signature)
print("signature: ", signature)
return hmac.compare_digest(expected_signature, signature)
@app.post("/api/webhooks")
async def handle_post(request: Request):
"""Handle BagelPay webhook notifications"""
payload = await request.body()
timestamp = request.headers.get('timestamp').encode()
signature = request.headers.get('bagelpay_signature')
# Combine payload and timestamp
signature_data = timestamp + ".".encode() + payload
print("payload: ", payload)
print("timestamp: ", timestamp)
print("signature: ", signature)
print("signature_data: ", signature_data)
if not verify_webhook_signature(signature_data, signature, WEBHOOK_SECRET):
return JSONResponse(status_code=401, content={"error": "Invalid signature"})
print(payload)
return JSONResponse(status_code=200, content={"message": "Success"})
if __name__ == "__main__":
listening_port = "8000"
public_url = ngrok.connect(
addr=listening_port,
proto="http",
hostname="stunning-crane-direct.ngrok-free.app"
)
print(f"ngrok Public URL: {public_url}")
uvicorn.run(app, host="0.0.0.0", port=int(listening_port))
```
### Integration Questions
**Q: How do I integrate with popular web frameworks?**
**Flask Integration:**
```python
from flask import Flask, request, jsonify
from bagelpay import BagelPayClient
app = Flask(__name__)
client = BagelPayClient(api_key=os.getenv('BAGELPAY_API_KEY'))
@app.route('/create-payment', methods=['POST'])
def create_payment():
try:
data = request.get_json()
checkout_request = CheckoutRequest(...)
response = client.create_checkout(checkout_request)
return jsonify({
'success': True,
'payment_url': response.data.checkout_url,
'payment_id': response.data.payment_id
})
except Exception as e:
return jsonify({
'success': False,
'error': str(e)
}), 400
```
**Django Integration:**
```python
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
import json
@csrf_exempt
@require_http_methods(["POST"])
def create_payment(request):
try:
data = json.loads(request.body)
# Use your BagelPay client here
checkout_request = CheckoutRequest(...)
response = client.create_checkout(checkout_request)
return JsonResponse({
'success': True,
'payment_url': response.data.checkout_url
})
except Exception as e:
return JsonResponse({
'success': False,
'error': str(e)
}, status=400)
```
## ๐ Support and Resources
### Getting Help
- ๐ **Official Documentation**: [https://bagelpay.gitbook.io/docs](https://bagelpay.gitbook.io/docs)
- ๐ง **Technical Support**: support@bagelpayment.com
- ๐ **Bug Reports**: [GitHub Issues](https://github.com/bagelpay/bagelpay-sdk-python/issues)
## ๐ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## ๐ Related Links
- [BagelPay Website](https://bagelpay.io)
- [API Documentation](https://bagelpay.gitbook.io/docs/apireference)
- [Developer Dashboard](https://bagelpay.io/dashboard)
- [Privacy Policy](https://bagelpay.io/privacy)
- [Terms of Service](https://bagelpay.io/terms)
---
**Start building with BagelPay SDK and make payment integration simple!** ๐
*For the latest updates and announcements, follow us on [Twitter](https://x.com/BagelPay) and [LinkedIn](https://www.linkedin.com/company/bagel-payment).*
Raw data
{
"_id": null,
"home_page": "https://github.com/bagelpay/bagelpay-sdk-python",
"name": "bagelpay",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "bagelpay, payment, api, sdk, python",
"author": "BagelPay",
"author_email": "BagelPay <support@bagelpayment.com>",
"download_url": "https://files.pythonhosted.org/packages/6c/a1/bbe460aa002075f9e2d080a342a40c30168705e26e812b652554bcd667b2/bagelpay-1.0.1.tar.gz",
"platform": null,
"description": "# BagelPay Python SDK\n\nA comprehensive Python client library for the BagelPay API, providing developers with an easy-to-use payment integration solution.\n\n## \ud83d\udccb Table of Contents\n\n- [Quick Start](#quick-start)\n- [Installation Guide](#installation-guide)\n- [Basic Configuration](#basic-configuration)\n- [Beginner Tutorial](#beginner-tutorial)\n- [API Reference](#api-reference)\n- [Example Code](#example-code)\n- [Error Handling](#error-handling)\n- [Testing Guide](#testing-guide)\n- [Development Guide](#development-guide)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n- [Troubleshooting](#troubleshooting)\n- [FAQ](#faq)\n\n## \ud83d\ude80 Quick Start\n\n### 30-Second Quick Demo\n\n```python\nfrom bagelpay import BagelPayClient, CheckoutRequest, Customer\n\n# 1. Initialize the client\nclient = BagelPayClient(\n base_url=\"https://test.bagelpay.io\",\n api_key=\"your-test-api-key-here\"\n)\n\n# 2. Create a payment session\nfrom datetime import datetime\n\ncheckout_request = CheckoutRequest(\n product_id=\"prod_123456789\",\n request_id=f\"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}\",\n units=\"1\",\n customer=Customer(\n email=\"customer@example.com\"\n ),\n success_url=\"https://yoursite.com/success\",\n metadata={\n \"order_id\": f\"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}\"\n }\n)\n\n# 3. Get payment URL\nresponse = client.create_checkout(checkout_request)\nprint(f\"Payment URL: {response.checkout_url}\")\n```\n\n## \ud83d\udce6 Installation Guide\n\n### System Requirements\n\n- **Python**: 3.11 or higher (recommended), minimum 3.8\n- **Package Manager**: pip or poetry\n- **Operating System**: Windows, macOS, Linux\n- **Memory**: Minimum 512MB RAM\n- **Network**: Internet connection for API calls\n\n### Method 1: Install from Source (Recommended)\n\n```bash\n# Clone the repository\ngit clone https://github.com/bagelpay/bagelpay-sdk-python.git\ncd bagelpay-sdk-python/generated-sdks/python\n\n# Create virtual environment\npython3 -m venv venv\nsource venv/bin/activate # Linux/Mac\n# or venv\\Scripts\\activate # Windows\n\n# Install SDK in development mode\npip install -e .\n\n# Verify installation\npython -c \"import bagelpay; print('Installation successful!')\"\n```\n\n### Method 2: Install from PyPI (Coming Soon)\n\n```bash\n# Install latest stable version\npip install bagelpay-sdk\n\n# Install specific version\npip install bagelpay-sdk==1.0.0\n\n# Install with optional dependencies\npip install bagelpay-sdk[dev,test]\n```\n\n### Method 3: Using Poetry\n\n```bash\n# Add to your project\npoetry add bagelpay-sdk\n\n# Or add from git repository\npoetry add git+https://github.com/bagelpay/bagelpay-sdk-python.git\n```\n\n### Verify Installation\n\n```python\nimport bagelpay\nfrom bagelpay import BagelPayClient\n\nprint(f\"BagelPay SDK Version: {bagelpay.__version__}\")\nprint(f\"Available modules: {dir(bagelpay)}\")\n\n# Test basic functionality\ntry:\n client = BagelPayClient(api_key=\"test\")\n print(\"\u2705 SDK imported successfully\")\nexcept Exception as e:\n print(f\"\u274c Import failed: {e}\")\n```\n\n## \u2699\ufe0f Basic Configuration\n\n### Getting API Keys\n\n1. **Sign up**: Create account at [BagelPay Dashboard](https://dashboard.bagelpay.io)\n2. **Navigate**: Go to \"Developer Settings\" \u2192 \"API Keys\"\n3. **Create Key**: Generate new API key for your environment\n4. **Copy**: Save your test and live keys securely\n5. **Environment**: Start with test keys for development\n\n### Environment Variables Setup\n\n```bash\n# Create .env file in your project root\necho \"BAGELPAY_API_KEY=your-test-api-key-here\" > .env\necho \"BAGELPAY_BASE_URL=https://test.bagelpay.io\" >> .env\necho \"BAGELPAY_TIMEOUT=30\" >> .env\necho \"BAGELPAY_DEBUG=false\" >> .env\n\n# Load environment variables\nexport $(cat .env | xargs)\n\n# Or use python-dotenv\npip install python-dotenv\n```\n\n### Client Initialization Options\n\n```python\nfrom bagelpay import BagelPayClient\nimport os\n\n\n# Method 1: Direct parameters\nclient = BagelPayClient(\n base_url=\"https://test.bagelpay.io\",\n api_key=\"your-api-key\",\n timeout=30, # Request timeout in seconds\n)\n\n# Method 2: Configuration dictionary\nconfig = {\n \"base_url\": \"https://test.bagelpay.io\",\n \"api_key\": os.getenv(\"BAGELPAY_API_KEY\"),\n \"timeout\": 30\n}\nclient = BagelPayClient(**config)\n\n# Method 4: Context manager (recommended for production)\nwith BagelPayClient(api_key=\"your-api-key\") as client:\n # Automatically handles connection cleanup\n response = client.list_products()\n print(f\"Found {response.total} products\")\n```\n\n### Environment-Specific Configuration\n\n```python\n# Development environment\ndev_client = BagelPayClient(\n base_url=\"https://test.bagelpay.io\",\n api_key=\"test_key_xxx\",\n timeout=60\n)\n\n# Staging environment\nstaging_client = BagelPayClient(\n base_url=\"https://staging.bagelpay.io\",\n api_key=\"staging_key_xxx\",\n timeout=30\n)\n\n# Production environment\nproduction_client = BagelPayClient(\n base_url=\"https://api.bagelpay.io\",\n api_key=\"live_key_xxx\",\n timeout=15,\n)\n```\n\n## \ud83d\udcda Beginner Tutorial\n\n### Step 1: Create Your First Product\n\n```python\nfrom bagelpay import BagelPayClient, CreateProductRequest\n\n# Initialize client\nclient = BagelPayClient(api_key=\"your-test-api-key\")\n\n# Create a digital product\nproduct_request = CreateProductRequest(\n name=\"Premium Membership\",\n description=\"Access to all premium features with monthly billing\",\n price=29.99,\n currency=\"USD\",\n billing_type=\"subscription\", # subscription or single_payment\n tax_inclusive=True,\n tax_category=\"digital_products\", # digital_products, saas_services or ebooks\n recurring_interval=\"daily\", # daily, weekly, monthly, 3months or 6months\n trial_days=1,\n)\n\ntry:\n product = client.create_product(product_request)\n print(f\"\u2705 Product created successfully!\")\n print(f\"Product ID: {product.product_id}\")\n print(f\"Product Name: {product.name}\")\n print(f\"Price: ${product.price} {product.currency}\")\nexcept Exception as e:\n print(f\"\u274c Failed to create product: {e}\")\n```\n\n### Step 2: Create a Payment Session\n\n```python\nfrom bagelpay import CheckoutRequest, Customer\n\n# Prepare customer information\ncustomer = Customer(\n email=\"john.doe@example.com\"\n)\n\n# Create checkout request\nfrom datetime import datetime\n\ncheckout_request = CheckoutRequest(\n product_id=product.product_id, # Use the product ID from step 1\n request_id=f\"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}\",\n units=\"1\",\n customer=customer,\n success_url=\"https://yoursite.com/success\",\n metadata={\n \"order_id\": f\"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}\",\n \"user_id\": \"user_12345\",\n \"source\": \"web_app\",\n \"campaign\": \"summer_promotion\"\n }\n)\n\ntry:\n checkout_response = client.create_checkout(checkout_request)\n \n print(f\"\u2705 Checkout session created!\")\n print(f\"Payment URL: {checkout_response.checkout_url}\")\n print(f\"Payment ID: {checkout_response.payment_id}\")\n print(f\"Product ID: {checkout_response.product_id}\")\n print(f\"Status: {checkout_response.status}\")\n print(f\"Expires On: {checkout_response.expires_on}\")\n \n # Store payment ID for later reference\n payment_id = checkout_response.payment_id\n \nexcept Exception as e:\n print(f\"\u274c Failed to create checkout: {e}\")\n```\n\n### Step 3: Monitor Transactions\n\n```python\n# Get transaction history\ntry:\n transactions = client.list_transactions(pageNum=1, pageSize=20)\n \n print(f\"\\n\ud83d\udcca Transaction Summary:\")\n print(f\"Total Transactions: {transactions.total}\")\n print(f\"Showing {len(transactions.items)} transactions on this page\")\n print(f\"Items per Page: 20\")\nexcept Exception as e:\n print(f\"\u274c Failed to fetch transactions: {e}\")\n```\n\n### Step 4: Manage Products\n\n```python\n# List all products\ntry:\n products = client.list_products(pageNum=1, pageSize=50)\n \n print(f\"\\n\ud83d\udecd\ufe0f Product Catalog ({products.total} total):\")\n \n for product in products.items:\n status = \"\ud83d\udfe2 Active\" if not product.is_archive else \"\ud83d\udd34 Archived\"\n print(f\"\\n{status} {product.name}\")\n print(f\" ID: {product.product_id}\")\n if product.recurring_interval:\n print(f\" Price: ${product.price} {product.currency}/{product.recurring_interval}\")\n else:\n print(f\" Price: ${product.price} {product.currency}\")\n print(f\" Type: {product.billing_type}\")\n print(f\" Created: {product.created_at}\")\n \n # Update a product\n if products.items:\n first_product = products.items[0]\n \n from bagelpay import UpdateProductRequest\n import random\n \n update_request = UpdateProductRequest(\n product_id=first_product.product_id,\n name=\"New_Product_\" + str(random.randint(1000, 9999)),\n description=\"New_Description_of_product_\" + str(random.randint(1000, 9999)),\n price=random.uniform(50.5, 1024.5),\n currency=\"USD\",\n billing_type=random.choice([\"subscription\", \"subscription\", \"single_payment\"]),\n tax_inclusive=False,\n tax_category=random.choice([\"digital_products\", \"saas_services\", \"ebooks\"]),\n recurring_interval=random.choice([\"daily\", \"weekly\", \"monthly\", \"3months\", \"6months\"]),\n trial_days=random.choice([0, 1, 7])\n )\n \n updated_product = client.update_product(update_request)\n print(f\"\\n\u2705 Updated product: {updated_product.name}\")\n print(f\" New price: ${updated_product.price}\")\n \nexcept Exception as e:\n print(f\"\u274c Failed to manage products: {e}\")\n```\n\n## \ud83d\udd27 API Reference\n\n### Product Management API\n\n#### Creating Products\n\n```python\n# One-time payment product\none_time_product = CreateProductRequest(\n name=\"E-book: Python Programming Guide\",\n description=\"Comprehensive guide to Python programming\",\n price=49.99,\n currency=\"USD\",\n billing_type=\"single_payment\",\n tax_inclusive=False,\n tax_category=\"digital_products\",\n recurring_interval=\"none\",\n trial_days=0\n)\n\n# Subscription product\nsubscription_product = CreateProductRequest(\n name=\"Monthly Pro Plan\",\n description=\"Professional features with monthly billing\",\n price=19.99,\n currency=\"USD\",\n billing_type=\"subscription\",\n tax_inclusive=True,\n tax_category=\"digital_products\",\n recurring_interval=\"monthly\",\n trial_days=14\n)\n```\n\n#### Product Operations\n\n```python\n# Get product details\nproduct = client.get_product(\"prod_123456\")\nprint(f\"Product: {product.name}\")\nprint(f\"Status: {'Active' if not product.is_archive else 'Archived'}\")\n\n# Archive product (stop selling but keep records)\narchived_product = client.archive_product(\"prod_123456\")\nprint(f\"Product archived: {archived_product.is_archive}\")\n\n# Unarchive product\nunarchived_product = client.unarchive_product(\"prod_123456\")\nprint(f\"Product restored: {not unarchived_product.is_archive}\")\n\n# Bulk product operations\nall_products = []\npage_num = 1\nwhile True:\n products = client.list_products(pageNum=page_num, pageSize=100)\n all_products.extend(products.items)\n \n if len(products.items) < 100:\n break\n page_num += 1\n\nprint(f\"Total products loaded: {len(all_products)}\")\n\n# Filter products by criteria\nactive_products = [p for p in all_products if not p.is_archive]\nsubscription_products = [p for p in all_products if p.billing_type == \"subscription\"]\nexpensive_products = [p for p in all_products if p.price > 100]\n\nprint(f\"Active products: {len(active_products)}\")\nprint(f\"Subscription products: {len(subscription_products)}\")\nprint(f\"Premium products (>$100): {len(expensive_products)}\")\n```\n\n### Payment Session API\n\n#### Advanced Checkout Configuration\n\n```python\n# Comprehensive checkout request\nfrom datetime import datetime\n\nadvanced_checkout = CheckoutRequest(\n product_id=\"prod_premium_plan\",\n request_id=f\"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}\",\n units=\"3\",\n customer=Customer(\n email=\"premium.user@company.com\"\n ),\n success_url=\"https://yoursite.com/success\",\n metadata={\n # Campaign tracking\n \"order_id\": f\"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}\",\n \"campaign_id\": \"black_friday_2024\",\n \"discount_code\": \"SAVE30\",\n \"affiliate_id\": \"partner_123\",\n \n # User context\n \"user_id\": \"user_789\",\n \"user_tier\": \"enterprise\",\n \"company\": \"Tech Corp Inc\",\n \n # Analytics\n \"source\": \"landing_page\",\n \"medium\": \"organic\",\n \"referrer\": \"https://google.com\",\n \"utm_campaign\": \"product_launch\"\n }\n)\n\nresponse = client.create_checkout(advanced_checkout)\n\n# Extract detailed checkout information\nprint(f\"\\n\ud83d\udcb3 Checkout Session Created:\")\nprint(f\"Payment ID: {response.payment_id}\")\nprint(f\"Checkout URL: {response.checkout_url}\")\nprint(f\"Product ID: {response.product_id}\")\nprint(f\"Status: {response.status}\")\nprint(f\"Expires On: {response.expires_on}\")\nprint(f\"Success URL: {response.success_url}\")\n```\n\n\n### Subscription Management API\n\n```python\n# Comprehensive subscription management\ndef manage_subscriptions(client):\n \"\"\"Manage customer subscriptions\"\"\"\n try:\n subscriptions = client.list_subscriptions(pageNum=1, pageSize=100)\n \n print(f\"\\n\ud83d\udd04 Subscription Management ({subscriptions.total} total):\")\n \n active_subs = []\n cancelled_subs = []\n paused_subs = []\n trialing_subs = []\n \n for subscription in subscriptions.items:\n print(f\"\\n\ud83d\udccb Subscription: {subscription.subscription_id}\")\n print(f\" Status: {subscription.status}\")\n print(f\" Customer: {subscription.customer}\")\n print(f\" Product: {subscription.product_name}\")\n print(f\" Next Billing: {subscription.billing_period_end}\")\n print(f\" Next Billing Amount: ${subscription.next_billing_amount}\")\n \n if subscription.status == \"active\":\n active_subs.append(subscription)\n elif subscription.status == \"canceled\":\n cancelled_subs.append(subscription)\n elif subscription.status == \"paused\":\n paused_subs.append(subscription)\n elif subscription.status == \"trialing\":\n trialing_subs.append(subscription)\n\n print(f\"\\n\ud83d\udcc8 Subscription Summary:\")\n print(f\"Active: {len(active_subs)}\")\n print(f\"Cancelled: {len(cancelled_subs)}\")\n print(f\"Paused: {len(paused_subs)}\")\n print(f\"Trialing: {len(trialing_subs)}\")\n \n # Calculate MRR (Monthly Recurring Revenue)\n monthly_revenue = sum(\n sub.next_billing_amount for sub in active_subs \n if sub.recurring_interval == \"monthly\"\n )\n annual_revenue = sum(\n sub.next_billing_amount / 12 for sub in active_subs \n if sub.recurring_interval == \"yearly\"\n )\n total_mrr = monthly_revenue + annual_revenue\n \n print(f\"\ud83d\udcb0 Monthly Recurring Revenue: ${total_mrr:.2f}\")\n \n return {\n \"active\": len(active_subs),\n \"cancelled\": len(cancelled_subs),\n \"paused_subs\": len(paused_subs),\n \"trialing_subs\": len(trialing_subs),\n \"mrr\": total_mrr\n }\n \n except Exception as e:\n print(f\"\u274c Error managing subscriptions: {e}\")\n return None\n\n# Cancel subscription with reason\ndef cancel_subscription_with_reason(client, subscription_id):\n \"\"\"Cancel subscription with cancellation reason\"\"\"\n try:\n # Note: This assumes the SDK supports cancellation reasons\n result = client.cancel_subscription(\n subscription_id,\n )\n print(f\"\u2705 Subscription {subscription_id} cancelled\")\n return result\n except Exception as e:\n print(f\"\u274c Failed to cancel subscription: {e}\")\n return None\n\nmanage_subscriptions(client)\ncancel_subscription_with_reason(client, \"sub_1966676965965533186\")\n```\n\n\n## \ud83d\udca1 Example Code\n\nThe SDK includes comprehensive examples in the `examples/` directory:\n\n### Available Examples\n\n| File | Description | Use Case | Complexity |\n|------|-------------|----------|------------|\n| `basic_usage.py` | Basic SDK functionality | Getting started | Beginner |\n| `checkout_payments.py` | Complete payment flow | E-commerce integration | Intermediate |\n| `product_management.py` | Product CRUD operations | Catalog management | Intermediate |\n| `subscription_customer_management.py` | Subscription & customer ops | SaaS applications | Advanced |\n\n### Running Examples\n\n```bash\n# Set up environment\nexport BAGELPAY_API_KEY=\"your-test-api-key\"\nexport BAGELPAY_BASE_URL=\"https://test.bagelpay.io\"\n\n# Run basic example\npython examples/basic_usage.py\n\n# Run with verbose output\nBAGELPAY_DEBUG=true python examples/checkout_payments.py\n```\n\n\n## \u26a0\ufe0f Error Handling\n\n### Exception Hierarchy\n\n```python\nfrom bagelpay.exceptions import (\n BagelPayError, # Base exception class\n BagelPayAPIError, # API-related errors\n BagelPayAuthenticationError, # Authentication failures\n BagelPayValidationError, # Request validation errors\n BagelPayNotFoundError, # Resource not found\n BagelPayRateLimitError, # Rate limiting\n BagelPayNetworkError, # Network connectivity issues\n BagelPayTimeoutError # Request timeout\n)\n\n# Exception hierarchy:\n# BagelPayError\n# \u251c\u2500\u2500 BagelPayAPIError\n# \u2502 \u251c\u2500\u2500 BagelPayAuthenticationError\n# \u2502 \u251c\u2500\u2500 BagelPayValidationError\n# \u2502 \u251c\u2500\u2500 BagelPayNotFoundError\n# \u2502 \u2514\u2500\u2500 BagelPayRateLimitError\n# \u251c\u2500\u2500 BagelPayNetworkError\n# \u2514\u2500\u2500 BagelPayTimeoutError\n```\n\n## \ud83e\uddea Testing Guide\n\n### Test Suite Overview\n\nThe SDK includes a comprehensive test suite with multiple testing strategies:\n\n```bash\n# Test runner with all options\npython run_tests.py --help\n\n# Basic test execution\npython run_tests.py # Run all tests\npython run_tests.py --unit # Unit tests only\npython run_tests.py --integration # Integration tests only\npython run_tests.py --mock # Mock mode (no real API calls)\npython run_tests.py --coverage # Generate coverage report\npython run_tests.py --fast # Parallel execution\npython run_tests.py --verbose # Detailed output\n```\n\n### Test Configuration\n\n```bash\n# Environment setup for testing\nexport BAGELPAY_API_KEY=\"test_key_12345\"\nexport BAGELPAY_BASE_URL=\"https://test.bagelpay.io\"\nexport BAGELPAY_TEST_MODE=\"true\"\nexport BAGELPAY_DEBUG=\"false\"\n\n# Install test dependencies\npip install pytest pytest-mock pytest-cov pytest-xdist responses\n\n# Or use the setup command\npython run_tests.py --setup\n```\n\n\n### Project Structure\n\n```\nbagelpay-sdk-python/\n\u251c\u2500\u2500 bagelpay/ # Main SDK package\n\u2502 \u251c\u2500\u2500 __init__.py # Package initialization\n\u2502 \u251c\u2500\u2500 client.py # Main client class\n\u2502 \u251c\u2500\u2500 models.py # Data models\n\u2502 \u251c\u2500\u2500 exceptions.py # Custom exceptions\n\u2502 \u2514\u2500\u2500 utils.py # Utility functions\n\u251c\u2500\u2500 examples/ # Example scripts\n\u2502 \u251c\u2500\u2500 basic_usage.py # Basic functionality\n\u2502 \u251c\u2500\u2500 checkout_payments.py # Payment processing\n\u2502 \u251c\u2500\u2500 product_management.py # Product operations\n\u2502 \u2514\u2500\u2500 subscription_customer_management.py # Advanced features\n\u251c\u2500\u2500 tests/ # Test suite\n\u2502 \u251c\u2500\u2500 conftest.py # Test configuration\n\u2502 \u251c\u2500\u2500 test_client.py # Client tests\n\u2502 \u251c\u2500\u2500 test_models.py # Model tests\n\u2502 \u251c\u2500\u2500 test_exceptions.py # Exception tests\n\u2502 \u2514\u2500\u2500 test_integration.py # Integration tests\n\u251c\u2500\u2500 docs/ # Documentation\n\u251c\u2500\u2500 requirements.txt # Dependencies\n\u251c\u2500\u2500 setup.py # Package setup\n\u251c\u2500\u2500 run_tests.py # Test runner\n\u251c\u2500\u2500 pytest.ini # Pytest configuration\n\u2514\u2500\u2500 README.md # This file\n```\n\n### Contributing Guidelines\n\n1. **Fork and Clone**\n ```bash\n git fork https://github.com/bagelpay/bagelpay-sdk-python.git\n git clone https://github.com/yourusername/bagelpay-sdk-python.git\n ```\n\n2. **Create Feature Branch**\n ```bash\n git checkout -b feature/amazing-new-feature\n ```\n\n3. **Make Changes**\n - Follow existing code style\n - Add tests for new functionality\n - Update documentation\n - Ensure all tests pass\n\n4. **Quality Checks**\n ```bash\n # Run all tests\n python run_tests.py --coverage\n \n # Code quality\n black bagelpay/\n flake8 bagelpay/\n mypy bagelpay/\n ```\n\n5. **Commit and Push**\n ```bash\n git add .\n git commit -m \"feat: add amazing new feature\"\n git push origin feature/amazing-new-feature\n ```\n\n6. **Create Pull Request**\n - Provide clear description\n - Include test results\n - Reference related issues\n\n\n## \ud83d\ude80 Webhook Integration\n\n```python\nimport hmac\nimport hashlib\nimport json\n\nfrom fastapi import FastAPI, Request\nfrom fastapi.responses import JSONResponse\nimport uvicorn\nfrom pyngrok import ngrok\nngrok.set_auth_token(\"your_ngrok_key\")\nWEBHOOK_SECRET = \"your_webhook_key\"\n\napp = FastAPI()\n\n\ndef verify_webhook_signature(signature_data: bytes, signature: str, secret: str) -> bool:\n \"\"\"Verify webhook signature for security\"\"\"\n expected_signature = hmac.new(\n secret.encode('utf-8'),\n signature_data,\n hashlib.sha256\n ).hexdigest()\n\n return hmac.compare_digest(expected_signature, signature)\n\n\n@app.post(\"/api/webhooks\")\nasync def handle_post(request: Request):\n \"\"\"Handle BagelPay webhook notifications\"\"\"\n payload = await request.body()\n timestamp = request.headers.get('timestamp').encode()\n signature = request.headers.get('bagelpay_signature')\n # Combine payload and timestamp\n signature_data = timestamp + \".\".encode() + payload\n\n if not verify_webhook_signature(signature_data, signature, WEBHOOK_SECRET):\n return JSONResponse(status_code=401, content={\"error\": \"Invalid signature\"})\n\n try:\n event = json.loads(payload)\n event_type = event.get('event_type')\n data = event.get('object')\n\n if event_type == 'checkout.completed':\n # handle checkout completed events\n print(event)\n elif event_type == 'checkout.failed':\n # handle checkout failed events\n print(event)\n elif event_type == 'checkout.cancel':\n # handle checkout cancelled events\n print(event)\n elif event_type == 'subscription.trialing':\n # handle subscription trialing events\n print(event)\n elif event_type == 'subscription.paid':\n # handle subscription paid events\n print(event)\n elif event_type == 'subscription.canceled':\n # handle subscription cancelled events\n print(event)\n elif event_type == 'refund.created':\n # handle refund created events\n print(event)\n else:\n print(f\"Unhandled event type: {event_type}\")\n\n return JSONResponse(status_code=200, content={\"message\": \"Success\"})\n except Exception as e:\n print(f\"Webhook processing error: {e}\")\n return JSONResponse(status_code=500, content={\"error\": \"Processing failed\"})\n\n\nif __name__ == \"__main__\":\n listening_port = \"8000\"\n public_url = ngrok.connect(\n addr=listening_port,\n proto=\"http\",\n hostname=\"stunning-crane-direct.ngrok-free.app\"\n )\n print(f\"ngrok Public URL: {public_url}\")\n uvicorn.run(app, host=\"0.0.0.0\", port=int(listening_port))\n```\n\n\n## \u2753 FAQ\n\n### General Questions\n\n**Q: What Python versions are supported?**\n\nA: The SDK supports Python 3.8+ with the following recommendations:\n- **Recommended**: Python 3.11 or higher\n- **Minimum**: Python 3.8\n- **Tested on**: Python 3.8, 3.9, 3.10, 3.11, 3.12\n\n**Q: How do I switch between test and production environments?**\n\n```python\n# Test environment\ntest_client = BagelPayClient(\n base_url=\"https://test.bagelpay.io\",\n api_key=\"test_key_xxx\"\n)\n\n# Production environment\nprod_client = BagelPayClient(\n base_url=\"https://live.bagelpay.io\",\n api_key=\"live_key_xxx\"\n)\n```\n\n**Q: How do I handle webhook verification?**\n\n```python\nimport hmac\nimport hashlib\n\nfrom fastapi import FastAPI, Request\nfrom fastapi.responses import JSONResponse\nimport uvicorn\nfrom pyngrok import ngrok\nngrok.set_auth_token(\"your_ngrok_key\")\nWEBHOOK_SECRET = \"your_webhook_key\"\n\napp = FastAPI()\n\n\ndef verify_webhook_signature(signature_data: bytes, signature: str, secret: str) -> bool:\n \"\"\"Verify webhook signature for security\"\"\"\n expected_signature = hmac.new(\n secret.encode('utf-8'),\n signature_data,\n hashlib.sha256\n ).hexdigest()\n\n print(\"expected_signature: \", expected_signature)\n print(\"signature: \", signature)\n\n return hmac.compare_digest(expected_signature, signature)\n\n\n@app.post(\"/api/webhooks\")\nasync def handle_post(request: Request):\n \"\"\"Handle BagelPay webhook notifications\"\"\"\n payload = await request.body()\n timestamp = request.headers.get('timestamp').encode()\n signature = request.headers.get('bagelpay_signature')\n # Combine payload and timestamp\n signature_data = timestamp + \".\".encode() + payload\n print(\"payload: \", payload)\n print(\"timestamp: \", timestamp)\n print(\"signature: \", signature)\n print(\"signature_data: \", signature_data)\n\n if not verify_webhook_signature(signature_data, signature, WEBHOOK_SECRET):\n return JSONResponse(status_code=401, content={\"error\": \"Invalid signature\"})\n\n print(payload)\n return JSONResponse(status_code=200, content={\"message\": \"Success\"})\n\n\nif __name__ == \"__main__\":\n listening_port = \"8000\"\n public_url = ngrok.connect(\n addr=listening_port,\n proto=\"http\",\n hostname=\"stunning-crane-direct.ngrok-free.app\"\n )\n print(f\"ngrok Public URL: {public_url}\")\n uvicorn.run(app, host=\"0.0.0.0\", port=int(listening_port))\n```\n\n\n### Integration Questions\n\n**Q: How do I integrate with popular web frameworks?**\n\n**Flask Integration:**\n```python\nfrom flask import Flask, request, jsonify\nfrom bagelpay import BagelPayClient\n\napp = Flask(__name__)\nclient = BagelPayClient(api_key=os.getenv('BAGELPAY_API_KEY'))\n\n@app.route('/create-payment', methods=['POST'])\ndef create_payment():\n try:\n data = request.get_json()\n \n checkout_request = CheckoutRequest(...)\n response = client.create_checkout(checkout_request)\n \n return jsonify({\n 'success': True,\n 'payment_url': response.data.checkout_url,\n 'payment_id': response.data.payment_id\n })\n \n except Exception as e:\n return jsonify({\n 'success': False,\n 'error': str(e)\n }), 400\n```\n\n**Django Integration:**\n```python\n# views.py\nfrom django.http import JsonResponse\nfrom django.views.decorators.csrf import csrf_exempt\nfrom django.views.decorators.http import require_http_methods\nimport json\n\n@csrf_exempt\n@require_http_methods([\"POST\"])\ndef create_payment(request):\n try:\n data = json.loads(request.body)\n \n # Use your BagelPay client here\n checkout_request = CheckoutRequest(...)\n response = client.create_checkout(checkout_request)\n \n return JsonResponse({\n 'success': True,\n 'payment_url': response.data.checkout_url\n })\n \n except Exception as e:\n return JsonResponse({\n 'success': False,\n 'error': str(e)\n }, status=400)\n```\n\n\n## \ud83d\udcde Support and Resources\n\n### Getting Help\n\n- \ud83d\udcd6 **Official Documentation**: [https://bagelpay.gitbook.io/docs](https://bagelpay.gitbook.io/docs)\n- \ud83d\udce7 **Technical Support**: support@bagelpayment.com\n- \ud83d\udc1b **Bug Reports**: [GitHub Issues](https://github.com/bagelpay/bagelpay-sdk-python/issues)\n\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## \ud83d\udd17 Related Links\n\n- [BagelPay Website](https://bagelpay.io)\n- [API Documentation](https://bagelpay.gitbook.io/docs/apireference)\n- [Developer Dashboard](https://bagelpay.io/dashboard)\n- [Privacy Policy](https://bagelpay.io/privacy)\n- [Terms of Service](https://bagelpay.io/terms)\n\n---\n\n**Start building with BagelPay SDK and make payment integration simple!** \ud83c\udf89\n\n*For the latest updates and announcements, follow us on [Twitter](https://x.com/BagelPay) and [LinkedIn](https://www.linkedin.com/company/bagel-payment).*\n",
"bugtrack_url": null,
"license": null,
"summary": "BagelPay Python SDK",
"version": "1.0.1",
"project_urls": {
"Bug Reports": "https://github.com/bagelpay/bagelpay-sdk-python/issues",
"Documentation": "https://bagelpay.gitbook.io/docs/documentation/sdks/python",
"Homepage": "https://bagelpay.io",
"Repository": "https://github.com/bagelpay/bagelpay-sdk-python"
},
"split_keywords": [
"bagelpay",
" payment",
" api",
" sdk",
" python"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "41b299736684565e6a4b4996855c1e860c738366528cd3aa94b6f299b3ab6200",
"md5": "d88556753b07f97d969593fe63f7d9d3",
"sha256": "8bf85421138f41aef0853bf4a4a2f28805dddb14f73e1de03ac8eba8d8a8f523"
},
"downloads": -1,
"filename": "bagelpay-1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d88556753b07f97d969593fe63f7d9d3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 15576,
"upload_time": "2025-09-15T01:15:22",
"upload_time_iso_8601": "2025-09-15T01:15:22.979031Z",
"url": "https://files.pythonhosted.org/packages/41/b2/99736684565e6a4b4996855c1e860c738366528cd3aa94b6f299b3ab6200/bagelpay-1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "6ca1bbe460aa002075f9e2d080a342a40c30168705e26e812b652554bcd667b2",
"md5": "3ea9c46601fda15f4b1c463525e53e3b",
"sha256": "c562d0ff144ae5d969d5173fd94ec835ec2e2e890b06d57543bdc6fb47bce8d5"
},
"downloads": -1,
"filename": "bagelpay-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "3ea9c46601fda15f4b1c463525e53e3b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 32997,
"upload_time": "2025-09-15T01:15:24",
"upload_time_iso_8601": "2025-09-15T01:15:24.530011Z",
"url": "https://files.pythonhosted.org/packages/6c/a1/bbe460aa002075f9e2d080a342a40c30168705e26e812b652554bcd667b2/bagelpay-1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-15 01:15:24",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bagelpay",
"github_project": "bagelpay-sdk-python",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "requests",
"specs": [
[
">=",
"2.25.0"
]
]
},
{
"name": "typing-extensions",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "pytest",
"specs": [
[
">=",
"7.0.0"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "pytest-mock",
"specs": [
[
">=",
"3.10.0"
]
]
},
{
"name": "coverage",
"specs": [
[
">=",
"7.0.0"
]
]
},
{
"name": "black",
"specs": [
[
">=",
"22.0.0"
]
]
},
{
"name": "flake8",
"specs": [
[
">=",
"5.0.0"
]
]
},
{
"name": "mypy",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "twine",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "wheel",
"specs": [
[
">=",
"0.38.0"
]
]
},
{
"name": "setuptools",
"specs": [
[
">=",
"65.0.0"
]
]
},
{
"name": "colorama",
"specs": [
[
">=",
"0.4.6"
]
]
},
{
"name": "tabulate",
"specs": [
[
">=",
"0.9.0"
]
]
}
],
"lcname": "bagelpay"
}