First Commit
This commit is contained in:
1 parent
5eb9dd037d
commit
2e62c0e60b
11877 files changed
+2035312
No files matched your search
@@ -0,0 +1,239 @@
|
||||
# PayPal Merchant Onboarding Flow
|
||||
|
||||
## BEFORE FIX (The Problem) ❌
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. User clicks "Connect with PayPal" │
|
||||
│ → onboard.php creates referral │
|
||||
│ → Saves to pending_onboarding.json │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. Redirected to PayPal Onboarding │
|
||||
│ → User sees business account signup │
|
||||
│ → User CLOSES browser WITHOUT completing ❌ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Returns to return.php │
|
||||
│ → Queries PayPal API for merchant_id │
|
||||
│ → PayPal returns: "NEG5HMUKCTQNL" (PARTNER ID!) ❌ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. OLD CODE: Accepts partner ID as merchant ID ❌ │
|
||||
│ → Saves "NEG5HMUKCTQNL" to merchants.json │
|
||||
│ → WRONG! This is YOUR ID, not the merchant's! │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
STUCK FOREVER 😞
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AFTER FIX (The Solution) ✅
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. User clicks "Connect with PayPal" │
|
||||
│ → onboard.php creates referral │
|
||||
│ → Saves to pending_onboarding.json │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. Redirected to PayPal Onboarding │
|
||||
│ → User sees business account signup │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↙ ↘
|
||||
SCENARIO A SCENARIO B
|
||||
(Incomplete) (Complete)
|
||||
|
||||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||||
│ User CLOSES browser │ │ User COMPLETES all │
|
||||
│ WITHOUT finishing ❌ │ │ steps at PayPal ✅ │
|
||||
└──────────────────────────┘ └──────────────────────────┘
|
||||
↓ ↓
|
||||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||||
│ Returns to return.php │ │ Returns to return.php │
|
||||
│ PayPal returns: │ │ PayPal returns: │
|
||||
│ "NEG5HMUKCTQNL" │ │ "ABC123XYZ456" ✅ │
|
||||
│ (partner ID) │ │ (real merchant ID) │
|
||||
└──────────────────────────┘ └──────────────────────────┘
|
||||
↓ ↓
|
||||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||||
│ NEW CODE: │ │ NEW CODE: │
|
||||
│ ✅ REJECTS partner ID │ │ ✅ ACCEPTS merchant ID │
|
||||
│ ✅ Marks as incomplete │ │ ✅ Saves to merchants │
|
||||
│ ✅ Shows warning │ │ ✅ Shows success │
|
||||
└──────────────────────────┘ └──────────────────────────┘
|
||||
↓ ↓
|
||||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||||
│ Dashboard shows: │ │ Dashboard shows: │
|
||||
│ ⚠️ Incomplete │ │ ✅ Connected │
|
||||
│ "Complete PayPal │ │ "Ready to accept │
|
||||
│ signup to continue" │ │ payments" │
|
||||
└──────────────────────────┘ └──────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Structure Comparison
|
||||
|
||||
### BEFORE FIX ❌
|
||||
```json
|
||||
// pending_onboarding.json
|
||||
{
|
||||
"school_ab32258ab0": {
|
||||
"school": "m",
|
||||
"created_at": 1760884706,
|
||||
"partner_referral_id": "YzU2NGVl...",
|
||||
"referral_token": "YzU2NGVl...",
|
||||
"merchant_id": "NEG5HMUKCTQNL", ← WRONG! This is partner ID
|
||||
"status": "connected" ← FALSE! Not really connected
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AFTER FIX - Incomplete ⚠️
|
||||
```json
|
||||
// pending_onboarding.json
|
||||
{
|
||||
"school_ab32258ab0": {
|
||||
"school": "m",
|
||||
"created_at": 1760884706,
|
||||
"partner_referral_id": "YzU2NGVl...",
|
||||
"referral_token": "YzU2NGVl...",
|
||||
"status": "incomplete_onboarding", ← Honest status
|
||||
"note": "Merchant did not complete PayPal onboarding",
|
||||
"last_return_at": 1760885000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AFTER FIX - Complete ✅
|
||||
```json
|
||||
// pending_onboarding.json
|
||||
{
|
||||
"school_3387003d82": {
|
||||
"school": "b",
|
||||
"created_at": 1760797314,
|
||||
"partner_referral_id": "MTQ2Njlm...",
|
||||
"referral_token": "MTQ2Njlm...",
|
||||
"merchant_id": "796GQ4VM8SWSQ", ← CORRECT! Different ID
|
||||
"status": "connected", ← TRUE! Really connected
|
||||
"connected_at": 1760797400
|
||||
}
|
||||
}
|
||||
|
||||
// merchants.json
|
||||
{
|
||||
"b": {
|
||||
"merchant_id": "796GQ4VM8SWSQ",
|
||||
"tracking_id": "school_3387003d82",
|
||||
"connected_at": 1760797400
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Changes in Code
|
||||
|
||||
### return.php
|
||||
```php
|
||||
// OLD CODE ❌
|
||||
if (!empty($resp['body']['merchant_id'])) {
|
||||
$merchantId = $resp['body']['merchant_id']; // Accepts ANY ID
|
||||
}
|
||||
|
||||
// NEW CODE ✅
|
||||
if (!empty($resp['body']['merchant_id'])) {
|
||||
$foundId = $resp['body']['merchant_id'];
|
||||
// CRITICAL: Don't accept partner's own ID
|
||||
if (strcasecmp($foundId, $config['partner_merchant_id']) !== 0) {
|
||||
$merchantId = $foundId; // Only accept if different
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### sync_merchants.php
|
||||
```php
|
||||
// OLD CODE ❌
|
||||
if (!empty($resp['body']['merchant_id'])) {
|
||||
$merchantId = $resp['body']['merchant_id']; // Blindly accepts
|
||||
}
|
||||
|
||||
// NEW CODE ✅
|
||||
if (!empty($resp['body']['merchant_id'])) {
|
||||
$foundId = $resp['body']['merchant_id'];
|
||||
// Don't accept partner ID - means onboarding not completed
|
||||
if (strcasecmp($foundId, $config['partner_merchant_id']) !== 0) {
|
||||
$merchantId = $foundId;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Scenarios
|
||||
|
||||
### Test 1: Incomplete Onboarding ⚠️
|
||||
1. Click "Connect with PayPal"
|
||||
2. See PayPal signup page
|
||||
3. **Immediately click "Return to School Lunch App"**
|
||||
4. **Expected Result**:
|
||||
- ⚠️ "Onboarding Incomplete" warning
|
||||
- Status: `incomplete_onboarding`
|
||||
- NO merchant_id saved
|
||||
|
||||
### Test 2: Complete Onboarding ✅
|
||||
1. Click "Connect with PayPal"
|
||||
2. See PayPal signup page
|
||||
3. **Complete ALL steps** (business info, email verification, etc.)
|
||||
4. Click "Return to Application"
|
||||
5. **Expected Result**:
|
||||
- ✅ "Onboarding completed" success message
|
||||
- Status: `connected`
|
||||
- Merchant ID saved (NOT `NEG5HMUKCTQNL`)
|
||||
|
||||
### Test 3: Sync Pending ⏳
|
||||
1. Complete onboarding but merchant_id not immediately available
|
||||
2. Click "🔄 Sync Now"
|
||||
3. **Expected Result**:
|
||||
- System queries PayPal API
|
||||
- Retrieves merchant_id
|
||||
- Updates status to `connected`
|
||||
|
||||
---
|
||||
|
||||
## Success Indicators ✅
|
||||
|
||||
You'll know it's working when:
|
||||
|
||||
1. **Different Merchant IDs**: Each merchant gets unique ID (not `NEG5HMUKCTQNL`)
|
||||
2. **Clear Status**: See `connected` or `incomplete_onboarding` (not stuck)
|
||||
3. **Warning Messages**: Incomplete onboardings show warnings
|
||||
4. **Real Payments**: Can create orders with actual merchant IDs
|
||||
|
||||
---
|
||||
|
||||
## Your Real Example 🎯
|
||||
|
||||
From your `sync_debug.json`, school "b" worked correctly:
|
||||
|
||||
```json
|
||||
{
|
||||
"ts": 1760884845,
|
||||
"track": "school_3387003d82",
|
||||
"school": "b",
|
||||
"attempt": "by-tracking",
|
||||
"status": 200,
|
||||
"body": {
|
||||
"merchant_id": "796GQ4VM8SWSQ", ← SUCCESS! ✅
|
||||
"tracking_id": "school_3387003d82"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is what ALL your merchants should look like! 🎉
|
||||
Reference in new issue
Block a user