Common Errors - cmaliwal/aiagent-payments GitHub Wiki
Common Errors & Troubleshooting
This guide helps you resolve common issues and errors when using AIAgent Payments. Each error includes the cause, solution, and prevention tips.
🚨 Payment Processing Errors
1. Invalid API Key
Error Message:
Invalid API key provided
Cause:
- Incorrect or expired API key
- Using test key in production or vice versa
- API key not properly configured
Solution:
# Check your API key format
# Stripe test keys start with: sk_test_
# Stripe live keys start with: sk_live_
import os
from aiagent_payments import PaymentProcessor
# Verify environment variable is set
print(f"API Key: {os.getenv('STRIPE_SECRET_KEY')[:10]}...")
# Initialize with explicit key
processor = PaymentProcessor(
provider="stripe",
api_key="sk_test_your_actual_key_here"
)
Prevention:
- Use environment variables for API keys
- Never commit API keys to version control
- Regularly rotate API keys
- Use test keys for development
2. Insufficient Funds
Error Message:
Your card was declined
Cause:
- Card has insufficient funds
- Card limit exceeded
- Bank declined the transaction
Solution:
from aiagent_payments.exceptions import PaymentError
try:
result = processor.process_payment(
amount=1000,
currency="usd",
description="Test payment"
)
except PaymentError as e:
if "insufficient_funds" in str(e):
print("Card has insufficient funds")
# Ask user to use a different payment method
elif "card_declined" in str(e):
print("Card was declined by bank")
# Suggest contacting bank
Prevention:
- Use test cards for development
- Implement proper error handling
- Provide clear error messages to users
3. Invalid Currency
Error Message:
Currency not supported
Cause:
- Currency code not supported by payment provider
- Currency not enabled in your account
- Incorrect currency format
Solution:
# Check supported currencies
supported_currencies = ["usd", "eur", "gbp", "cad", "aud"]
currency = "usd" # Use lowercase
if currency.lower() not in supported_currencies:
print(f"Currency {currency} not supported")
# Process payment with valid currency
result = processor.process_payment(
amount=1000,
currency="usd", # Use supported currency
description="Test payment"
)
Prevention:
- Validate currency before processing
- Use lowercase currency codes
- Check provider documentation for supported currencies
4. Invalid Amount
Error Message:
Invalid amount
Cause:
- Amount is zero or negative
- Amount exceeds provider limits
- Amount format is incorrect
Solution:
# Validate amount before processing
def validate_amount(amount, currency):
if amount <= 0:
raise ValueError("Amount must be positive")
# Check minimum amount (varies by currency)
min_amounts = {"usd": 50, "eur": 50, "gbp": 30} # in cents
if amount < min_amounts.get(currency.lower(), 50):
raise ValueError(f"Amount too small for {currency}")
# Check maximum amount
if amount > 999999: # $9,999.99
raise ValueError("Amount too large")
return amount
# Use validated amount
valid_amount = validate_amount(1000, "usd")
result = processor.process_payment(
amount=valid_amount,
currency="usd",
description="Test payment"
)
Prevention:
- Always validate amounts before processing
- Use amounts in cents (smallest currency unit)
- Implement amount limits
🔧 Configuration Errors
5. Missing Environment Variables
Error Message:
Environment variable STRIPE_SECRET_KEY not found
Cause:
- Environment variable not set
- Incorrect variable name
- .env file not loaded
Solution:
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Check if variables are set
required_vars = ["STRIPE_SECRET_KEY", "PAYPAL_CLIENT_ID"]
missing_vars = [var for var in required_vars if not os.getenv(var)]
if missing_vars:
print(f"Missing environment variables: {missing_vars}")
print("Please set them in your .env file or environment")
# Set fallback values for development
if not os.getenv("STRIPE_SECRET_KEY"):
os.environ["STRIPE_SECRET_KEY"] = "sk_test_placeholder"
Prevention:
- Use a .env file for local development
- Document required environment variables
- Use environment variable validation
6. PayPal Provider Configuration Errors
6.1 "return_url cannot be empty" Error
Error Message:
ValidationError: return_url cannot be empty
Cause:
- Using the factory function without passing
return_url
andcancel_url
parameters - Parameters not being forwarded correctly to the PayPal provider (fixed in latest version)
Solution:
from aiagent_payments.providers import create_payment_provider
# ✅ Correct way (using factory function)
provider = create_payment_provider(
"paypal",
client_id="your_client_id",
client_secret="your_client_secret",
return_url="https://yourapp.com/success", # Required
cancel_url="https://yourapp.com/cancel" # Required
)
# ✅ Alternative: Direct initialization
from aiagent_payments.providers import PayPalProvider
provider = PayPalProvider(
client_id="your_client_id",
client_secret="your_client_secret",
return_url="https://yourapp.com/success",
cancel_url="https://yourapp.com/cancel"
)
# ❌ Wrong way (will cause error)
provider = create_payment_provider(
"paypal",
client_id="your_client_id",
client_secret="your_client_secret"
# Missing return_url and cancel_url
)
Prevention:
- Always provide
return_url
andcancel_url
when using PayPal - Use environment variables for URLs
- Test configuration in sandbox mode first
6.2 PayPal API "Unprocessable Request" Error
Error Message:
PayPal request unprocessable. Check request format.
Cause:
- PayPal sandbox account configuration issues
- Missing API permissions
- Test account restrictions
- Order capture attempted before user approval
Solution:
# Use two-step flow instead of direct capture
# Step 1: Create order
order_response = provider.create_order(
user_id="user_123",
amount=25.99,
currency="USD",
return_url="https://yourapp.com/success",
cancel_url="https://yourapp.com/cancel"
)
# Step 2: Get approval URL and redirect user
approval_url = None
for link in order_response.get("links", []):
if link.get("rel") == "approve":
approval_url = link.get("href")
break
# Step 3: Capture only after user approval (via webhook or return)
# Don't capture immediately in process_payment()
Prevention:
- Use sandbox accounts for testing
- Implement proper two-step payment flow
- Handle webhooks for order approval events
7. Invalid Provider Configuration
Error Message:
Invalid payment provider: unknown_provider
Cause:
- Provider name misspelled
- Provider not installed
- Provider not supported
Solution:
# Check available providers
from aiagent_payments.providers import get_available_providers
available_providers = get_available_providers()
print(f"Available providers: {available_providers}")
# Use correct provider name
processor = PaymentProcessor(
provider="stripe", # Use exact provider name
api_key="sk_test_..."
)
Prevention:
- Use exact provider names
- Install required dependencies
- Check provider documentation
8. Crypto Provider Storage Error
Error Message:
In-memory storage not allowed in production mode. Transaction data must be persisted.
Cause:
- Using
MemoryStorage
in production mode - Missing
AIAgentPayments_DevMode
environment variable
Solution:
# For development/testing
import os
os.environ["AIAgentPayments_DevMode"] = "1"
# For production, use persistent storage
from aiagent_payments.storage import DatabaseStorage, FileStorage
# Use database storage
storage = DatabaseStorage(database_url="sqlite:///payments.db")
# Or use file storage
storage = FileStorage(data_dir="./payments_data")
# Initialize provider with persistent storage
provider = create_payment_provider(
"crypto",
wallet_address="0x...",
infura_project_id="your_project_id",
storage=storage
)
Prevention:
- Set
AIAgentPayments_DevMode=1
for development - Use persistent storage in production
- Configure proper storage backends
🌐 Webhook Errors
9. Invalid Webhook Signature
Error Message:
Invalid webhook signature
Cause:
- Incorrect webhook secret
- Webhook payload tampered
- Wrong signature verification method
Solution:
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
signature = request.headers.get('Stripe-Signature')
if not signature:
return {'error': 'No signature provided'}, 400
try:
# Verify webhook signature
event = processor.verify_webhook(
payload=request.data,
signature=signature
)
except Exception as e:
print(f"Webhook verification failed: {e}")
return {'error': 'Invalid signature'}, 400
# Process the event
return {'status': 'success'}, 200
Prevention:
- Store webhook secrets securely
- Always verify webhook signatures
- Use HTTPS for webhook endpoints
10. Webhook Timeout
Error Message:
Webhook timeout
Cause:
- Webhook processing takes too long
- Network issues
- Server overload
Solution:
import asyncio
from concurrent.futures import ThreadPoolExecutor
@app.route('/webhook', methods=['POST'])
def handle_webhook():
# Process webhook asynchronously
def process_webhook():
# Your webhook processing logic
pass
# Run in background thread
with ThreadPoolExecutor() as executor:
executor.submit(process_webhook)
# Return immediately
return {'status': 'accepted'}, 202
Prevention:
- Process webhooks asynchronously
- Keep webhook handlers lightweight
- Implement proper error handling
💾 Storage Errors
11. Database Connection Error
Error Message:
Database connection failed
Cause:
- Database server down
- Incorrect connection string
- Network issues
Solution:
from aiagent_payments.storage import DatabaseStorage
# Test database connection
def test_database_connection():
try:
storage = DatabaseStorage(
database_url="postgresql://user:pass@localhost/payments"
)
# Test connection
storage.health_check()
print("Database connection successful")
except Exception as e:
print(f"Database connection failed: {e}")
# Fallback to file storage
return FileStorage(data_dir="./payments_data")
# Use fallback storage
storage = test_database_connection()
Prevention:
- Implement connection pooling
- Use connection retry logic
- Have fallback storage options
12. File Storage Permission Error
Error Message:
Permission denied
Cause:
- Insufficient file permissions
- Directory doesn't exist
- Disk space full
Solution:
import os
from aiagent_payments.storage import FileStorage
# Check and create directory
def setup_file_storage():
data_dir = "./payments_data"
# Create directory if it doesn't exist
if not os.path.exists(data_dir):
os.makedirs(data_dir, mode=0o755)
# Check permissions
if not os.access(data_dir, os.W_OK):
print(f"No write permission for {data_dir}")
# Use memory storage as fallback
return MemoryStorage()
return FileStorage(data_dir=data_dir)
storage = setup_file_storage()
Prevention:
- Set proper file permissions
- Monitor disk space
- Use absolute paths
🔐 Security Errors
13. SSL Certificate Error
Error Message:
SSL certificate verification failed
Cause:
- Invalid SSL certificate
- Self-signed certificate
- Certificate expired
Solution:
import ssl
import requests
# For development only - disable SSL verification
# WARNING: Never use this in production
requests.packages.urllib3.disable_warnings()
session = requests.Session()
session.verify = False
# Configure provider with custom session
provider = create_payment_provider(
"stripe",
api_key="sk_test_...",
session=session
)
Prevention:
- Use valid SSL certificates
- Keep certificates updated
- Never disable SSL in production
🔧 Recent Fixes & Updates
PayPal Provider Factory Fix
Issue: The create_payment_provider
factory function was not forwarding return_url
, cancel_url
, webhook_id
, and timeout
parameters to the PayPal provider constructor.
Fix: Updated the factory function to properly forward all configuration parameters.
Before (Broken):
# This would fail with "return_url cannot be empty" error
provider = create_payment_provider(
"paypal",
client_id="your_client_id",
client_secret="your_client_secret",
return_url="https://yourapp.com/success", # ❌ Not forwarded
cancel_url="https://yourapp.com/cancel" # ❌ Not forwarded
)
After (Fixed):
# This now works correctly
provider = create_payment_provider(
"paypal",
client_id="your_client_id",
client_secret="your_client_secret",
return_url="https://yourapp.com/success", # ✅ Properly forwarded
cancel_url="https://yourapp.com/cancel" # ✅ Properly forwarded
)
📚 Additional Resources
🆘 Still Need Help?
If you're still experiencing issues:
- Check the logs for detailed error messages
- Verify your configuration using the examples above
- Test in sandbox mode before going to production
- Open an issue on GitHub with:
- Error message and stack trace
- Your configuration (without sensitive data)
- Steps to reproduce the issue
- Environment details (Python version, OS, etc.)
Remember: Always test your payment integration thoroughly in sandbox/test mode before deploying to production!