397 lines
11 KiB
Markdown
397 lines
11 KiB
Markdown
# Payment Workflow Quick Start Guide
|
|
**Date:** December 8, 2025
|
|
**Backend Port:** 8011
|
|
|
|
---
|
|
|
|
## 🚀 Quick Test Commands
|
|
|
|
### 1. Test Payment Methods API
|
|
```bash
|
|
# 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
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
```bash
|
|
# User fills signup form with billing info
|
|
# Backend creates: Account, Subscription, Invoice, AccountPaymentMethod
|
|
```
|
|
|
|
### Step 2: User Sees Payment Instructions
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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:**
|
|
```json
|
|
{
|
|
"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)**
|
|
```bash
|
|
# 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:**
|
|
```json
|
|
{
|
|
"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
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
```bash
|
|
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/
|