374 lines
12 KiB
Python
374 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Payment Workflow API Integration Examples
|
|
Demonstrates how to interact with the payment APIs programmatically
|
|
"""
|
|
|
|
import requests
|
|
import json
|
|
from decimal import Decimal
|
|
|
|
# Base URL for the API
|
|
BASE_URL = "http://localhost:8011/api/v1"
|
|
|
|
class PaymentAPIClient:
|
|
"""Example API client for payment workflow"""
|
|
|
|
def __init__(self, base_url=BASE_URL):
|
|
self.base_url = base_url
|
|
self.token = None
|
|
self.session = requests.Session()
|
|
|
|
def register_free_trial(self, email, password, first_name, last_name):
|
|
"""Register a new free trial user"""
|
|
url = f"{self.base_url}/auth/register/"
|
|
data = {
|
|
"email": email,
|
|
"password": password,
|
|
"password_confirm": password,
|
|
"first_name": first_name,
|
|
"last_name": last_name
|
|
}
|
|
|
|
response = self.session.post(url, json=data)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
|
|
print(f"✓ Free trial account created: {result['data']['account']['name']}")
|
|
print(f" Status: {result['data']['account']['status']}")
|
|
print(f" Credits: {result['data']['account']['credits']}")
|
|
|
|
return result['data']
|
|
|
|
def register_paid_user(self, email, password, first_name, last_name,
|
|
plan_slug, billing_info):
|
|
"""Register a new paid user with billing information"""
|
|
url = f"{self.base_url}/auth/register/"
|
|
data = {
|
|
"email": email,
|
|
"password": password,
|
|
"password_confirm": password,
|
|
"first_name": first_name,
|
|
"last_name": last_name,
|
|
"plan_slug": plan_slug,
|
|
**billing_info
|
|
}
|
|
|
|
response = self.session.post(url, json=data)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
|
|
print(f"✓ Paid account created: {result['data']['account']['name']}")
|
|
print(f" Status: {result['data']['account']['status']}")
|
|
print(f" Credits: {result['data']['account']['credits']}")
|
|
|
|
if 'invoice' in result['data']:
|
|
inv = result['data']['invoice']
|
|
print(f" Invoice: {inv['invoice_number']} - ${inv['total']}")
|
|
|
|
return result['data']
|
|
|
|
def login(self, email, password):
|
|
"""Login and get authentication token"""
|
|
url = f"{self.base_url}/auth/login/"
|
|
data = {
|
|
"email": email,
|
|
"password": password
|
|
}
|
|
|
|
response = self.session.post(url, json=data)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
|
|
self.token = result['data']['token']
|
|
self.session.headers.update({
|
|
'Authorization': f'Bearer {self.token}'
|
|
})
|
|
|
|
print(f"✓ Logged in as: {email}")
|
|
return result['data']
|
|
|
|
def get_payment_methods(self, country_code=None):
|
|
"""Get available payment methods for a country"""
|
|
url = f"{self.base_url}/billing/admin/payment-methods/"
|
|
params = {}
|
|
if country_code:
|
|
params['country'] = country_code
|
|
|
|
response = self.session.get(url, params=params)
|
|
response.raise_for_status()
|
|
methods = response.json()
|
|
|
|
print(f"✓ Payment methods available: {len(methods)}")
|
|
for method in methods:
|
|
print(f" - {method['display_name']} ({method['payment_method']})")
|
|
|
|
return methods
|
|
|
|
def confirm_payment(self, invoice_id, payment_method, amount,
|
|
manual_reference, manual_notes=""):
|
|
"""Submit payment confirmation for manual payments"""
|
|
url = f"{self.base_url}/billing/admin/payments/confirm/"
|
|
data = {
|
|
"invoice_id": invoice_id,
|
|
"payment_method": payment_method,
|
|
"amount": str(amount),
|
|
"manual_reference": manual_reference,
|
|
"manual_notes": manual_notes
|
|
}
|
|
|
|
response = self.session.post(url, json=data)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
|
|
payment = result['data']
|
|
print(f"✓ Payment confirmation submitted")
|
|
print(f" Payment ID: {payment['payment_id']}")
|
|
print(f" Invoice: {payment['invoice_number']}")
|
|
print(f" Status: {payment['status']}")
|
|
print(f" Reference: {payment['manual_reference']}")
|
|
|
|
return result['data']
|
|
|
|
def approve_payment(self, payment_id, admin_notes=""):
|
|
"""Approve a pending payment (admin only)"""
|
|
url = f"{self.base_url}/billing/admin/payments/{payment_id}/approve/"
|
|
data = {
|
|
"admin_notes": admin_notes
|
|
}
|
|
|
|
response = self.session.post(url, json=data)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
|
|
payment = result['data']
|
|
print(f"✓ Payment approved")
|
|
print(f" Account Status: {payment['account_status']}")
|
|
print(f" Subscription Status: {payment['subscription_status']}")
|
|
print(f" Credits Added: {payment['credits_added']}")
|
|
print(f" Total Credits: {payment['total_credits']}")
|
|
|
|
return result['data']
|
|
|
|
def reject_payment(self, payment_id, admin_notes):
|
|
"""Reject a pending payment (admin only)"""
|
|
url = f"{self.base_url}/billing/admin/payments/{payment_id}/reject/"
|
|
data = {
|
|
"admin_notes": admin_notes
|
|
}
|
|
|
|
response = self.session.post(url, json=data)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
|
|
payment = result['data']
|
|
print(f"✓ Payment rejected")
|
|
print(f" Status: {payment['status']}")
|
|
print(f" Reason: {admin_notes}")
|
|
|
|
return result['data']
|
|
|
|
|
|
def example_free_trial_workflow():
|
|
"""Example: Free trial signup workflow"""
|
|
print("\n" + "="*60)
|
|
print("EXAMPLE 1: FREE TRIAL SIGNUP")
|
|
print("="*60 + "\n")
|
|
|
|
client = PaymentAPIClient()
|
|
|
|
# Step 1: Register free trial user
|
|
user_data = client.register_free_trial(
|
|
email="freetrial_demo@example.com",
|
|
password="SecurePass123!",
|
|
first_name="Free",
|
|
last_name="Trial"
|
|
)
|
|
|
|
# Step 2: Login
|
|
login_data = client.login(
|
|
email="freetrial_demo@example.com",
|
|
password="SecurePass123!"
|
|
)
|
|
|
|
print(f"\n✓ Free trial workflow complete!")
|
|
print(f" User can now create {user_data['account']['max_sites']} site(s)")
|
|
print(f" Available credits: {user_data['account']['credits']}")
|
|
|
|
|
|
def example_paid_signup_workflow():
|
|
"""Example: Paid signup with manual payment approval"""
|
|
print("\n" + "="*60)
|
|
print("EXAMPLE 2: PAID SIGNUP WITH MANUAL PAYMENT")
|
|
print("="*60 + "\n")
|
|
|
|
client = PaymentAPIClient()
|
|
|
|
# Step 1: Check available payment methods
|
|
print("Step 1: Check Payment Methods for Pakistan")
|
|
methods = client.get_payment_methods(country_code="PK")
|
|
|
|
# Step 2: Register with paid plan
|
|
print("\nStep 2: Register Paid User")
|
|
billing_info = {
|
|
"billing_email": "billing@example.com",
|
|
"billing_address_line1": "123 Main Street",
|
|
"billing_city": "Karachi",
|
|
"billing_country": "PK",
|
|
"payment_method": "bank_transfer"
|
|
}
|
|
|
|
user_data = client.register_paid_user(
|
|
email="paiduser_demo@example.com",
|
|
password="SecurePass123!",
|
|
first_name="Paid",
|
|
last_name="User",
|
|
plan_slug="starter",
|
|
billing_info=billing_info
|
|
)
|
|
|
|
# Step 3: Login
|
|
print("\nStep 3: User Login")
|
|
login_data = client.login(
|
|
email="paiduser_demo@example.com",
|
|
password="SecurePass123!"
|
|
)
|
|
|
|
# Step 4: User makes external payment and submits confirmation
|
|
print("\nStep 4: Submit Payment Confirmation")
|
|
invoice_id = user_data['invoice']['id']
|
|
invoice_total = user_data['invoice']['total']
|
|
|
|
payment_data = client.confirm_payment(
|
|
invoice_id=invoice_id,
|
|
payment_method="bank_transfer",
|
|
amount=invoice_total,
|
|
manual_reference="DEMO-BANK-2025-001",
|
|
manual_notes="Transferred via ABC Bank on Dec 8, 2025"
|
|
)
|
|
|
|
print(f"\n✓ Payment submitted! Waiting for admin approval...")
|
|
print(f" Payment ID: {payment_data['payment_id']}")
|
|
print(f" Account remains in 'pending_payment' status")
|
|
|
|
# Step 5: Admin approves (requires admin token)
|
|
print("\nStep 5: Admin Approval (requires admin credentials)")
|
|
print(" → Admin would login separately and approve the payment")
|
|
print(f" → POST /billing/admin/payments/{payment_data['payment_id']}/approve/")
|
|
print(" → Account status changes to 'active'")
|
|
print(" → Credits allocated: 1000")
|
|
|
|
return payment_data
|
|
|
|
|
|
def example_admin_approval():
|
|
"""Example: Admin approving a payment"""
|
|
print("\n" + "="*60)
|
|
print("EXAMPLE 3: ADMIN PAYMENT APPROVAL")
|
|
print("="*60 + "\n")
|
|
|
|
# This requires admin credentials
|
|
admin_client = PaymentAPIClient()
|
|
|
|
print("Step 1: Admin Login")
|
|
try:
|
|
admin_client.login(
|
|
email="dev@igny8.com", # Replace with actual admin email
|
|
password="admin_password" # Replace with actual password
|
|
)
|
|
|
|
print("\nStep 2: Approve Payment")
|
|
# Replace with actual payment ID
|
|
payment_id = 5 # Example payment ID
|
|
|
|
result = admin_client.approve_payment(
|
|
payment_id=payment_id,
|
|
admin_notes="Verified payment in bank statement. Reference matches."
|
|
)
|
|
|
|
print(f"\n✓ Payment approval complete!")
|
|
print(f" Account activated with {result['total_credits']} credits")
|
|
|
|
except requests.exceptions.HTTPError as e:
|
|
print(f"✗ Admin approval failed: {e}")
|
|
print(" (This is expected if you don't have admin credentials)")
|
|
|
|
|
|
def example_payment_rejection():
|
|
"""Example: Admin rejecting a payment"""
|
|
print("\n" + "="*60)
|
|
print("EXAMPLE 4: ADMIN PAYMENT REJECTION")
|
|
print("="*60 + "\n")
|
|
|
|
admin_client = PaymentAPIClient()
|
|
|
|
print("Step 1: Admin Login")
|
|
try:
|
|
admin_client.login(
|
|
email="dev@igny8.com",
|
|
password="admin_password"
|
|
)
|
|
|
|
print("\nStep 2: Reject Payment")
|
|
payment_id = 7 # Example payment ID
|
|
|
|
result = admin_client.reject_payment(
|
|
payment_id=payment_id,
|
|
admin_notes="Reference number not found in bank statement. Please verify and resubmit."
|
|
)
|
|
|
|
print(f"\n✓ Payment rejected!")
|
|
print(f" User can resubmit with correct reference")
|
|
|
|
except requests.exceptions.HTTPError as e:
|
|
print(f"✗ Payment rejection failed: {e}")
|
|
print(" (This is expected if you don't have admin credentials)")
|
|
|
|
|
|
def main():
|
|
"""Run all examples"""
|
|
print("\n" + "="*60)
|
|
print("PAYMENT WORKFLOW API INTEGRATION EXAMPLES")
|
|
print("="*60)
|
|
print("\nThese examples demonstrate how to integrate with the")
|
|
print("multi-tenancy payment workflow APIs.\n")
|
|
|
|
try:
|
|
# Example 1: Free trial
|
|
example_free_trial_workflow()
|
|
|
|
# Example 2: Paid signup
|
|
# example_paid_signup_workflow()
|
|
|
|
# Example 3: Admin approval (requires admin credentials)
|
|
# example_admin_approval()
|
|
|
|
# Example 4: Payment rejection (requires admin credentials)
|
|
# example_payment_rejection()
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
print(f"\n✗ API Error: {e}")
|
|
print("\nMake sure the backend is running on http://localhost:8011")
|
|
except Exception as e:
|
|
print(f"\n✗ Error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Note: Uncomment examples you want to run
|
|
# Some examples may create actual data in the database
|
|
|
|
print("\n" + "="*60)
|
|
print("API INTEGRATION EXAMPLES - READ ONLY MODE")
|
|
print("="*60)
|
|
print("\nTo run examples, uncomment the desired function calls")
|
|
print("in the main() function.\n")
|
|
print("Available examples:")
|
|
print(" 1. example_free_trial_workflow()")
|
|
print(" 2. example_paid_signup_workflow()")
|
|
print(" 3. example_admin_approval()")
|
|
print(" 4. example_payment_rejection()")
|
|
print("\nWarning: Running these will create data in the database!")
|
|
print("="*60 + "\n")
|