---
created: 2026-03-12
source: Main-Site
tags: [agent-archive, main-site]
---

# PHASE 3: PAYMENT SYSTEM ANALYSIS
**Date:** February 3, 2026  
**Focus:** Stripe Integration, Payment Flows, Webhook Handling

## 🎯 CURRENT STRIPE INTEGRATION ARCHITECTURE

### **🔧 STRIPE CONFIGURATION**
- **API Version**: `stripe==12.4.0`
- **Keys**: `STRIPE_SECRET_KEY`, `STRIPE_PUBLISHABLE_KEY`, `STRIPE_WEBHOOK_SECRET`
- **Mode**: Live/Production ready
- **Region**: Australia (AUD currency)

### **📁 KEY FILES**

#### **1. `app/services/stripe_service.py`**
- **`create_payment_intent()`**: Creates PaymentIntent for escrow
- **`capture_payment()`**: Releases funds from escrow
- **`create_transfer()`**: Transfers to worker's connected account
- **`validate_stripe_config()`**: Startup validation

#### **2. `app/blueprints/legal/stripe_webhooks.py`**
- **`handle_stripe_webhook()`**: Main webhook handler
- **`handle_payment_succeeded()`**: Payment → escrow
- **`handle_payment_failed()`**: Failed payment handling
- **Idempotency**: Prevents duplicate processing

#### **3. `app/blueprints/legal/routes.py`**
- **`/api/payments/create`**: Creates payment for contract
- **`/api/payments/confirm`**: Confirms payment (3D Secure)
- **`/api/payments/capture`**: Releases escrow funds

## 🔄 CURRENT PAYMENT FLOW (7% MODEL)

### **Step 1: Contract Creation**
**File**: `app/main_routes.py` (lines ~)
```python
# When application accepted → Contract created
contract = Contract(
    job_id=application.job_id,
    contractor_id=application.job.contractor_id,
    worker_id=application.worker_id,
    # ... other fields
)
```

### **Step 2: Payment Initialization**
**File**: `app/blueprints/legal/routes.py` (lines 242-261)
```python
# Calculate amounts with 7% fee
payment.calculate_amounts()  # Sets platform_fee = gross_amount * 0.07

# Create Stripe PaymentIntent
stripe_intent = stripe_service.create_payment_intent(
    amount_aud=float(payment.gross_amount),  # Includes 7% fee
    metadata={...}
)
```

### **Step 3: Contractor Pays**
- **UI**: `app/templates/payments/payment_form.html`
- **JS**: `app/static/js/stripe_payment.js`
- **Process**: Card details → Stripe Elements → PaymentIntent confirmation

### **Step 4: Escrow Holding**
**File**: `app/blueprints/legal/stripe_webhooks.py` (lines 58-78)
```python
# Webhook: payment_intent.succeeded
payment.status = 'held_escrow'  # Funds held in Stripe
```

### **Step 5: Payment Release**
**File**: `app/blueprints/legal/routes.py` (lines 621-)
```python
# After work completion + ratings
stripe_service.capture_payment(payment.stripe_payment_intent_id)
# Transfers net amount to worker (gross - 7% - Stripe fees)
```

## 💰 PAYMENT CALCULATION DETAILS

### **Current Logic (`app/models/contract.py` lines ~350-400)**
```python
# Base amount = hourly_rate × hours
base_amount = float(contract.agreed_rate) * hours

# Platform fee = 7% (3% if referral match)
platform_fee_rate = 0.07  # Default
if referral_match:
    platform_fee_rate = 0.03  # Discount
self.platform_fee = base_amount * platform_fee_rate

# GST handling (10% for GST-registered workers)
if worker.gst_registered:
    self.gst_amount = base_amount * 0.10

# Stripe fee calculation (2.9% + $0.30)
stripe_fee = (gross_with_gst * 0.029) + 0.30

# Net to worker
self.net_to_worker = gross_with_gst - self.platform_fee - stripe_fee
```

### **Example: $1,000 Job**
```
Base amount: $1,000
GST (if applicable): +$100 = $1,100
Platform fee (7%): -$70
Stripe fee (2.9% + $0.30): -$32.19
Worker receives: $997.81 ($1,100 - $70 - $32.19)
RateRight receives: $70 (platform fee)
```

## 🎯 MODIFICATIONS FOR £50+£10 MODEL

### **1. £50 Flat Fee Calculation**
**File**: `app/models/contract.py` (modify `calculate_amounts()`)

**Current:**
```python
platform_fee_rate = 0.07
self.platform_fee = base_amount * platform_fee_rate
```

**New:**
```python
# OPTION 1: Always £50
self.platform_fee = 50  # £50 flat

# OPTION 2: Tiered (£50 min, 7% over £714)
if base_amount > 714:  # £50 is 7% of £714
    self.platform_fee = base_amount * 0.07
else:
    self.platform_fee = 50
```

### **2. Payment Intent Amount Change**
**File**: `app/blueprints/legal/routes.py` (line 242)

**Current:** Contractor pays `gross_amount` (includes 7% fee)
**New:** Contractor pays:
- **Job value** (to worker)
- **£50 fee** (to RateRight)
- **GST** (if applicable)

**Calculation:**
```python
# Current
payment.gross_amount = base_amount + gst + platform_fee

# New
payment.gross_amount = base_amount + gst  # Worker gets full job value
# £50 fee charged separately (different PaymentIntent)
```

### **3. Separate £50 Charge**
**New Flow:**
1. **Application accepted** → Create contract
2. **Charge £50** to contractor (immediate, separate PaymentIntent)
3. **Contractor pays job value** to escrow (existing flow)
4. **Worker paid** job value (minus Stripe fees only)

## 🔧 NEW INSURANCE SYSTEM DESIGN

### **Database Schema Additions**
```sql
-- Insurance subscriptions
CREATE TABLE insurance_subscriptions (
    id SERIAL PRIMARY KEY,
    worker_id INTEGER REFERENCES users(id),
    stripe_subscription_id VARCHAR(255) UNIQUE,
    stripe_customer_id VARCHAR(255),
    weekly_amount DECIMAL(10,2) DEFAULT 10.00,
    status VARCHAR(20) DEFAULT 'active',  -- active, canceled, paused
    start_date TIMESTAMP,
    end_date TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Insurance claims
CREATE TABLE insurance_claims (
    id SERIAL PRIMARY KEY,
    worker_id INTEGER REFERENCES users(id),
    contract_id INTEGER REFERENCES contracts(id),
    amount_claimed DECIMAL(10,2),
    amount_paid DECIMAL(10,2),
    status VARCHAR(20) DEFAULT 'pending',  -- pending, approved, paid, rejected
    evidence TEXT,
    paid_date TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Insurance fund
CREATE TABLE insurance_fund (
    id SERIAL PRIMARY KEY,
    balance DECIMAL(10,2) DEFAULT 0.00,
    total_premiums DECIMAL(10,2) DEFAULT 0.00,
    total_claims DECIMAL(10,2) DEFAULT 0.00,
    total_recoveries DECIMAL(10,2) DEFAULT 0.00,
    updated_at TIMESTAMP DEFAULT NOW()
);
```

### **Stripe Subscription Setup**
```python
# New service: app/services/insurance_service.py
def create_insurance_subscription(worker_id):
    """Create £10/week Stripe subscription"""
    customer = stripe.Customer.create(
        email=worker.email,
        payment_method=payment_method_id
    )
    
    subscription = stripe.Subscription.create(
        customer=customer.id,
        items=[{'price': 'price_weekly_10'}],
        currency='aud',
        collection_method='charge_automatically'
    )
```

### **Claims Processing Flow**
```
1. Worker files claim (not paid by contractor)
2. Upload evidence (timesheets, messages)
3. System verifies (auto or manual)
4. If approved: Pay worker from insurance fund
5. Lawyer sends demand letter to contractor
6. If recovered: Replenish insurance fund
```

## ⚠️ PAYMENT SYSTEM RISKS

### **1. Dual PaymentIntents Complexity**
- **Current**: One PaymentIntent (job value + fee)
- **New**: Two PaymentIntents (£50 fee + job value)
- **Risk**: Double the webhook handling, sync issues

### **2. Fee Collection Timing**
- **Option A**: £50 charged when application accepted
- **Option B**: £50 charged when contract signed
- **Option C**: £50 charged before work starts
- **Risk**: Contractor accepts worker but doesn't pay £50

### **3. Insurance Fund Management**
- **Risk**: Insufficient funds for claims
- **Solution**: Build reserve before full launch
- **Backup**: Revenue covers shortfalls initially

### **4. Legal Enforcement Integration**
- **Current**: No legal partner
- **Required**: Lawyer for demand letters
- **Risk**: Recovery rate affects insurance profitability

## 🎯 IMPLEMENTATION PRIORITY

### **Phase 1: £50 Fee (Week 1)**
1. Modify `contract.py` `calculate_amounts()` for flat fee
2. Create separate £50 PaymentIntent in marketplace routes
3. Update UI to show £50 fee before accepting worker
4. Test with Stripe test mode

### **Phase 2: Insurance Subscriptions (Week 2)**
1. Create database tables for insurance
2. Build subscription management UI
3. Integrate Stripe subscriptions
4. Add "Buy insurance" to worker dashboard

### **Phase 3: Claims System (Week 3)**
1. Create claims submission portal
2. Build evidence upload system
3. Implement manual review flow
4. Create insurance fund tracking

### **Phase 4: Legal Automation (Week 4)**
1. Integrate legal partner API
2. Build automated demand letter system
3. Implement recovery tracking
4. Create reporting dashboard

## 🔧 TECHNICAL DEPENDENCIES

### **Must Have:**
- Stripe account with subscriptions enabled
- Database migration scripts
- Test environment with Stripe test keys
- Backup of current production database

### **Nice to Have:**
- Legal partner API access
- Separate bank account for insurance fund
- Monitoring for fund balance alerts
- Automated reporting system

---

**NEXT**: Phase 4 - Database Schema Analysis (Complete Table Structure)