Files
igny8/PAYMENT-WORKFLOW-QUICK-START.md
2025-12-09 00:11:35 +00:00

11 KiB

Payment Workflow Quick Start Guide

Date: December 8, 2025
Backend Port: 8011


🚀 Quick Test Commands

1. Test Payment Methods API

# Get payment methods for Pakistan
curl "http://localhost:8011/api/v1/billing/admin/payment-methods/?country=PK" | jq

# Get payment methods for USA
curl "http://localhost:8011/api/v1/billing/admin/payment-methods/?country=US" | jq

# Get all global payment methods
curl "http://localhost:8011/api/v1/billing/admin/payment-methods/" | jq

2. Register Free Trial User

curl -X POST http://localhost:8011/api/v1/auth/register/ \
  -H "Content-Type: application/json" \
  -d '{
    "email": "freetrial@test.com",
    "password": "TestPass123!",
    "password_confirm": "TestPass123!",
    "first_name": "Free",
    "last_name": "Trial"
  }' | jq

Expected Result:

  • Account created with status='trial'
  • 1000 credits allocated
  • Free plan assigned
  • No subscription/invoice created

3. Register Paid User with Billing Info

curl -X POST http://localhost:8011/api/v1/auth/register/ \
  -H "Content-Type: application/json" \
  -d '{
    "email": "paiduser@test.com",
    "password": "TestPass123!",
    "password_confirm": "TestPass123!",
    "first_name": "Paid",
    "last_name": "User",
    "plan_slug": "starter",
    "billing_email": "billing@test.com",
    "billing_country": "PK",
    "billing_city": "Karachi",
    "billing_address_line1": "123 Main Street",
    "payment_method": "bank_transfer"
  }' | jq

Expected Result:

  • Account created with status='pending_payment'
  • 0 credits (awaiting payment)
  • Subscription created with status='pending_payment'
  • Invoice created with status='pending'
  • AccountPaymentMethod created (type='bank_transfer')
  • Billing info saved in account AND snapshotted in invoice metadata

🔄 Complete Manual Payment Workflow

Step 1: User Registers with Paid Plan

# User fills signup form with billing info
# Backend creates: Account, Subscription, Invoice, AccountPaymentMethod

Step 2: User Sees Payment Instructions

# Frontend displays invoice details and payment instructions
# For bank_transfer: Bank account details
# For local_wallet: Mobile wallet number

Step 3: User Makes External Payment

User transfers money via bank or mobile wallet
User keeps transaction reference: "BT-20251208-12345"

Step 4: User Confirms Payment

# Get auth token first
TOKEN=$(curl -X POST http://localhost:8011/api/v1/auth/login/ \
  -H "Content-Type: application/json" \
  -d '{"email": "paiduser@test.com", "password": "TestPass123!"}' | jq -r '.data.token')

# Submit payment confirmation
curl -X POST http://localhost:8011/api/v1/billing/admin/payments/confirm/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_id": 1,
    "payment_method": "bank_transfer",
    "manual_reference": "BT-20251208-12345",
    "manual_notes": "Transferred via ABC Bank on Dec 8, 2025",
    "amount": "89.00"
  }' | jq

Expected Response:

{
  "success": true,
  "message": "Payment confirmation submitted for review. You will be notified once approved.",
  "data": {
    "payment_id": 1,
    "invoice_id": 1,
    "invoice_number": "INV-2-202512-0001",
    "status": "pending_approval",
    "amount": "89.00",
    "currency": "USD",
    "manual_reference": "BT-20251208-12345"
  }
}

Step 5: Admin Approves Payment

Option A: Via Django Admin Panel

1. Go to: http://localhost:8011/admin/billing/payment/
2. Filter by status: "pending_approval"
3. Select payment(s)
4. Actions dropdown: "Approve selected manual payments"
5. Click "Go"

Option B: Via API (Admin Token Required)

# Get admin token
ADMIN_TOKEN=$(curl -X POST http://localhost:8011/api/v1/auth/login/ \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@example.com", "password": "adminpass"}' | jq -r '.data.token')

# Approve payment
curl -X POST http://localhost:8011/api/v1/billing/admin/payments/1/approve/ \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "admin_notes": "Verified payment in bank statement on Dec 8, 2025"
  }' | jq

Expected Response:

{
  "success": true,
  "message": "Payment approved successfully. Account activated.",
  "data": {
    "payment_id": 1,
    "invoice_id": 1,
    "invoice_number": "INV-2-202512-0001",
    "account_id": 2,
    "account_status": "active",
    "subscription_status": "active",
    "credits_added": 1000,
    "total_credits": 1000,
    "approved_by": "admin@example.com",
    "approved_at": "2025-12-08T15:30:00Z"
  }
}

What Happens Atomically:

  1. Payment.status → 'succeeded'
  2. Invoice.status → 'paid'
  3. Subscription.status → 'active'
  4. Account.status → 'active'
  5. Credits added: 1000 (plan.included_credits)
  6. CreditTransaction logged

🔍 Verification Queries

Check Account Status

docker compose -f docker-compose.app.yml exec -T igny8_backend python manage.py shell <<'EOF'
from igny8_core.auth.models import Account

account = Account.objects.get(id=2)  # Replace with actual ID
print(f'Account: {account.name}')
print(f'Status: {account.status}')
print(f'Credits: {account.credits}')
print(f'Plan: {account.plan.name}')
print(f'Billing Email: {account.billing_email}')
EOF

Check Subscription & Invoice

docker compose -f docker-compose.app.yml exec -T igny8_backend python manage.py shell <<'EOF'
from igny8_core.auth.models import Subscription
from igny8_core.business.billing.models import Invoice, Payment

# Check subscription
sub = Subscription.objects.filter(account_id=2).first()
if sub:
    print(f'Subscription Status: {sub.status}')
    print(f'Plan: {sub.plan.name if sub.plan else "None"}')

# Check invoice
invoice = Invoice.objects.filter(account_id=2).first()
if invoice:
    print(f'\nInvoice: {invoice.invoice_number}')
    print(f'Status: {invoice.status}')
    print(f'Total: ${invoice.total}')
    print(f'Has billing snapshot: {"billing_snapshot" in invoice.metadata}')

# Check payment
payment = Payment.objects.filter(invoice=invoice).first()
if payment:
    print(f'\nPayment Status: {payment.status}')
    print(f'Reference: {payment.manual_reference}')
    print(f'Approved by: {payment.approved_by}')
EOF

Check Credit Transactions

docker compose -f docker-compose.app.yml exec -T igny8_backend python manage.py shell <<'EOF'
from igny8_core.business.billing.models import CreditTransaction

transactions = CreditTransaction.objects.filter(account_id=2).order_by('-created_at')
print(f'Credit Transactions: {transactions.count()}\n')
for t in transactions:
    print(f'{t.created_at.strftime("%Y-%m-%d %H:%M")} | {t.transaction_type:15} | {t.amount:6} credits | Balance: {t.balance_after}')
    print(f'  {t.description}')
EOF

📋 Payment Method Configurations

Country Method Display Name Instructions
* (Global) stripe Credit/Debit Card (Stripe) -
* (Global) paypal PayPal -
* (Global) bank_transfer Bank Transfer Bank: ABC Bank, Account: 1234567890, SWIFT: ABCPKKA
PK local_wallet JazzCash / Easypaisa JazzCash: 03001234567

🧪 Test Scenarios

Scenario 1: Free Trial User Journey

1. Register without plan_slug → Free plan assigned
2. Account status: 'trial'
3. Credits: 1000
4. Create 1 site (max_sites=1)
5. Site requires industry selection
6. SiteUserAccess auto-created
7. Use AI features with 1000 credits

Scenario 2: Paid User Journey (Happy Path)

1. Register with plan_slug='starter'
2. Fill billing form
3. Select payment_method='bank_transfer'
4. Account status: 'pending_payment', Credits: 0
5. Subscription status: 'pending_payment'
6. Invoice created (status='pending')
7. User transfers money externally
8. User submits payment confirmation with reference
9. Payment created (status='pending_approval')
10. Admin approves payment
11. Account status: 'active', Credits: 1000
12. Subscription status: 'active'
13. Invoice status: 'paid'
14. User can create 1 site and use features

Scenario 3: Rejected Payment

1-9. Same as Scenario 2
10. Admin rejects payment (reference not found)
11. Payment status: 'failed'
12. Account remains: status='pending_payment'
13. User notified (email - when implemented)
14. User can re-submit with correct reference

🔐 Admin Panel Access

Access Payment Management

URL: http://localhost:8011/admin/billing/payment/
Login: Use superuser credentials

Features:
- Filter by status (pending_approval, succeeded, failed)
- Search by manual_reference, invoice_number, account_name
- Bulk approve payments action
- Bulk reject payments action
- View payment details (reference, notes, proof)

Approve Multiple Payments

1. Go to Payments admin
2. Filter: status = "pending_approval"
3. Select multiple payments (checkboxes)
4. Action: "Approve selected manual payments"
5. Click "Go"
6. All selected payments processed atomically

📊 Database Schema Changes

New/Modified Tables

igny8_subscriptions:

  • Added: plan_id (FK to igny8_plans)
  • Removed: payment_method (now property from Account)

igny8_sites:

  • Modified: industry_id (now NOT NULL, required)

igny8_payment_method_config:

  • 14 records created for global + country-specific methods

igny8_invoices:

  • billing_period_start, billing_period_end, billing_email → properties only
  • metadata now contains billing_snapshot

igny8_payments:

  • transaction_reference removed (duplicate of manual_reference)

🐛 Troubleshooting

Issue: "Invoice not found"

Cause: Wrong invoice_id or invoice doesn't belong to user's account
Fix: Query invoices: Invoice.objects.filter(account=request.account)

Issue: "Amount mismatch"

Cause: Submitted amount doesn't match invoice.total
Fix: Ensure exact amount from invoice (including decimals)

Issue: "Payment not pending approval"

Cause: Trying to approve already processed payment
Fix: Check payment.status before approval

Issue: "Site creation fails - industry required"

Cause: Industry field is now required
Fix: Always include industry_id when creating sites

Issue: "No credits after approval"

Cause: Plan might not have included_credits
Fix: Check plan.included_credits in database


📝 Next Steps

For Frontend Development:

  1. Implement billing form step in signup flow
  2. Create PaymentMethodSelect component
  3. Build payment confirmation modal
  4. Add pending payment status banner to dashboard

For Testing:

  1. Write E2E tests for free trial flow
  2. Write E2E tests for paid signup flow
  3. Test payment approval workflow
  4. Test payment rejection workflow

For Enhancement:

  1. Add email notifications (payment submitted, approved, rejected)
  2. Implement S3 upload for payment proof
  3. Add Stripe/PayPal webhook handlers for automation
  4. Create payment analytics dashboard

Last Updated: December 8, 2025
Backend Version: Phase 2 & 3 Complete
API Base URL: http://localhost:8011/api/v1/