# M-Pesa Integration - ROOT CAUSE FOUND! ✅

## 🎯 The Problem (SOLVED!)

**Error:** `Data too long for column 'phone_number' at row 1`

### What Happened:
1. ✅ M-Pesa sent callback to your server
2. ✅ Callback was received and stored in `mpesa_callbacks` table
3. ❌ **Transaction creation FAILED** because:
   - M-Pesa sent **HASHED/ENCRYPTED phone number**: `99193bd8110f876a9408aa0ddc2478b585b4019969af0dd1ec83b20845edae95` (64 characters)
   - Database column `phone_number` is **VARCHAR(17)** (only 17 characters)
   - **Database rejected the insert** with "Data too long" error
4. ❌ Callback was never marked as processed
5. ❌ No transaction = No repayment = Payment not reflected

### Why Phone is Hashed:
M-Pesa is encrypting the phone number for privacy/security. This could be:
- A Safaricom security feature
- Test environment behavior
- Configuration setting in your M-Pesa account

---

## ✅ The Fix (IMPLEMENTED!)

I've updated the `process_callback` command to:
1. ✅ **Truncate hashed phone numbers** to 17 characters
2. ✅ **Match by Bill Ref Number** (ID number) instead of phone
3. ✅ **Match by First Name + Last Name** as fallback
4. ✅ Create transaction successfully
5. ✅ Process payment and create repayment

---

## 🚀 Run This Command Now

```bash
cd /home/acbptxvs/public_html/branchbusinessadvance.co.ke
python manage.py process_callback 682dc145-3a65-40df-b93c-bb688dab289d
```

**What it will do:**
1. Truncate the hashed phone to 17 chars
2. Create transaction with Trans ID: `TK1018ZAQC`
3. Try to match borrower by Bill Ref: `1`
4. If Bill Ref matches, create repayment
5. If not, you can manually link the borrower

---

## 📊 Expected Output

```
======================================================================
Process M-Pesa Callback
======================================================================

Callback ID: 682dc145-3a65-40df-b93c-bb688dab289d
Type: confirmation
Date: 2025-11-01 06:07:28

Transaction Data:
  Trans ID: TK1018ZAQC
  Amount: KES 1.00
  Phone: 99193bd8110f876a9408aa0ddc2478b585b4019969af0dd1ec83b20845edae95
  Bill Ref: 1
  First Name: PHINEAS

----------------------------------------------------------------------
Creating transaction...
----------------------------------------------------------------------

⚠ Phone number is hashed/encrypted (64 chars)
  Truncating to: 99193bd8110f876a
  Will try to match by Bill Ref or Name instead

✓ Transaction created: abc123...

----------------------------------------------------------------------
Processing payment...
----------------------------------------------------------------------

Option A - If Bill Ref "1" matches a borrower's ID:
✓ Payment Processed Successfully!
Matched Borrower: Phineas [Last Name]
Matched Loan: LOAN-000123
Repayment Created: Yes
Receipt Number: RCP-000456

Option B - If Bill Ref doesn't match:
⚠ Payment Processing Completed with Issues
Matched Borrower: Not matched
Processing Notes: Could not match phone number to any borrower
```

---

## 🔧 If Bill Ref Doesn't Match

The Bill Ref is `1`, which needs to match a borrower's ID number in the database.

### Check if borrower has ID number "1":
```bash
python manage.py shell -c "
from users.models import User
borrower = User.objects.filter(id_number='1', role='borrower').first()
if borrower:
    print(f'Found: {borrower.get_full_name()}')
    print(f'Phone: {borrower.phone_number}')
else:
    print('No borrower with ID number \"1\"')
"
```

### If no match, manually link the transaction:
```python
# Django shell
from loans.models import MpesaTransaction
from users.models import User

# Get the transaction
t = MpesaTransaction.objects.get(trans_id='TK1018ZAQC')

# Find borrower by name
borrower = User.objects.filter(
    first_name__icontains='PHINEAS',
    role='borrower'
).first()

if borrower:
    print(f"Found: {borrower.get_full_name()}")
    
    # Link and process
    t.borrower = borrower
    t.save()
    
    success = t.process_payment()
    
    if t.repayment:
        print(f"✓ Repayment created: {t.repayment.receipt_number}")
    else:
        print(f"✗ Failed: {t.processing_notes}")
```

---

## 📋 Files to Upload (UPDATED)

1. **`payments/management/commands/process_callback.py`** - UPDATED (handles hashed phone)
2. **`loans/models.py`** - Fixed phone matching
3. **`payments/management/commands/check_callbacks.py`** - Check callback status
4. **`payments/management/commands/check_mpesa_status.py`** - Check transaction status
5. **`payments/management/commands/fix_mpesa_payments.py`** - Fix unprocessed
6. **`payments/management/commands/reprocess_mpesa_transaction.py`** - Reprocess

---

## 🎯 Long-term Solution

### Option 1: Fix M-Pesa Configuration
Contact Safaricom to disable phone number encryption/hashing in callbacks.

### Option 2: Increase Database Column Size
```sql
-- Increase phone_number column size to handle hashes
ALTER TABLE mpesa_transactions 
MODIFY COLUMN phone_number VARCHAR(100);

ALTER TABLE mpesa_transactions 
MODIFY COLUMN msisdn VARCHAR(100);
```

Then update Django model:
```python
# In loans/models.py - MpesaTransaction model
phone_number = models.CharField(max_length=100, blank=True, null=True)  # Changed from 17
msisdn = models.CharField(max_length=100, blank=True, null=True)  # Changed from 17
```

### Option 3: Always Use Bill Ref for Matching
Instruct customers to enter their ID number as Bill Ref when paying.

---

## ✅ Success Checklist

After running the command:

- [ ] Transaction created successfully
- [ ] Callback linked to transaction
- [ ] Callback marked as processed
- [ ] Borrower matched (by Bill Ref or manually)
- [ ] Loan matched
- [ ] Repayment created
- [ ] Payment appears in `/loans/repayments/`
- [ ] Payment appears in `/payments/transactions/`
- [ ] Loan balance updated

---

## 🔍 Verification Commands

```bash
# Check callback status
python manage.py check_callbacks

# Check transaction status
python manage.py check_mpesa_status

# Check repayments
python manage.py shell -c "
from loans.models import Repayment
recent = Repayment.objects.filter(payment_method='mpesa').order_by('-created_at')[:5]
for r in recent:
    print(f'{r.receipt_number}: {r.loan.borrower.get_full_name()} - KES {r.amount}')
"
```

---

## 📝 Summary

**ROOT CAUSE:** M-Pesa sent 64-character hashed phone number, but database column only accepts 17 characters.

**FIX:** Truncate phone number and match by Bill Ref (ID number) instead.

**ACTION:** Upload updated `process_callback.py` and run the command!

---

**Upload the updated file → Run the command → Payment will be processed!** 🚀
