125 lines
6.5 KiB
PHP
125 lines
6.5 KiB
PHP
<?php
|
|
$config = require __DIR__ . '/config.php';
|
|
require __DIR__ . '/lib/PayPalClient.php';
|
|
require __DIR__ . '/lib/Storage.php';
|
|
|
|
try {
|
|
$client = new PayPalClient($config);
|
|
$storage = new Storage($config['storage_path']);
|
|
|
|
$pending = $storage->get('pending_onboarding', []);
|
|
$merchants = $storage->get('merchants', []);
|
|
$syncDebug = $storage->get('sync_debug', []);
|
|
$updated = 0;
|
|
|
|
foreach ($pending as $track => &$entry) {
|
|
if (!is_array($entry)) continue;
|
|
$school = $entry['school'] ?? null;
|
|
if (!$school) continue;
|
|
if (!empty($entry['merchant_id'])) continue; // already resolved
|
|
|
|
$merchantId = null;
|
|
|
|
// Try by tracking_id
|
|
$path = '/v1/customer/partners/' . urlencode($config['partner_merchant_id']) . '/merchant-integrations?tracking_id=' . urlencode($track);
|
|
$resp = $client->api('GET', $path);
|
|
$syncDebug[] = ['ts' => time(), 'track' => $track, 'school' => $school, 'attempt' => 'by-tracking', 'status' => $resp['status'] ?? null, 'body' => $resp['body'] ?? null];
|
|
if ($resp['status'] >= 200 && $resp['status'] < 300) {
|
|
if (!empty($resp['body']['merchant_id'])) {
|
|
$foundId = $resp['body']['merchant_id'];
|
|
// Don't accept the partner's own ID - means onboarding not completed
|
|
if (strcasecmp($foundId, $config['partner_merchant_id']) !== 0) {
|
|
$merchantId = $foundId;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try by partner_referral_id if available
|
|
$ridCandidate = $entry['partner_referral_id'] ?? ($entry['referral_token'] ?? null);
|
|
if (!$merchantId && $ridCandidate) {
|
|
$path = '/v1/customer/partners/' . urlencode($config['partner_merchant_id']) . '/merchant-integrations?onboarded=true';
|
|
$resp2 = $client->api('GET', $path);
|
|
$syncDebug[] = ['ts' => time(), 'track' => $track, 'school' => $school, 'attempt' => 'list-onboarded', 'status' => $resp2['status'] ?? null, 'body_count' => isset($resp2['body']['merchant_integrations']) ? count($resp2['body']['merchant_integrations']) : null];
|
|
if ($resp2['status'] >= 200 && $resp2['status'] < 300 && !empty($resp2['body']['merchant_integrations'])) {
|
|
foreach ($resp2['body']['merchant_integrations'] as $mi) {
|
|
$rid = $mi['partner_referral_id'] ?? ($mi['referral_id'] ?? null);
|
|
$foundId = $mi['merchant_id'] ?? null;
|
|
// Only accept if it's not the partner's own ID
|
|
if ($rid && strcasecmp($rid, $ridCandidate) === 0 && $foundId && strcasecmp($foundId, $config['partner_merchant_id']) !== 0) {
|
|
$merchantId = $foundId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Final fallback: list without onboarded filter and match by tracking_id/referral
|
|
if (!$merchantId) {
|
|
$path = '/v1/customer/partners/' . urlencode($config['partner_merchant_id']) . '/merchant-integrations?page_size=200';
|
|
$resp3 = $client->api('GET', $path);
|
|
$syncDebug[] = ['ts' => time(), 'track' => $track, 'school' => $school, 'attempt' => 'list-all', 'status' => $resp3['status'] ?? null, 'body_count' => isset($resp3['body']['merchant_integrations']) ? count($resp3['body']['merchant_integrations']) : null];
|
|
if ($resp3['status'] >= 200 && $resp3['status'] < 300 && !empty($resp3['body']['merchant_integrations'])) {
|
|
foreach ($resp3['body']['merchant_integrations'] as $mi) {
|
|
$tid = $mi['tracking_id'] ?? null;
|
|
$rid = $mi['partner_referral_id'] ?? ($mi['referral_id'] ?? null);
|
|
$foundId = $mi['merchant_id'] ?? null;
|
|
// Only accept if it's not the partner's own ID
|
|
if (((!empty($tid) && strcasecmp($tid, $track) === 0) || ($ridCandidate && $rid && strcasecmp($rid, $ridCandidate) === 0)) && $foundId && strcasecmp($foundId, $config['partner_merchant_id']) !== 0) {
|
|
$merchantId = $foundId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try reading the partner referral directly (may include status/links); capture merchant_id if present
|
|
if (!$merchantId && $ridCandidate) {
|
|
$path = '/v2/customer/partner-referrals/' . urlencode($ridCandidate);
|
|
$resp4 = $client->api('GET', $path);
|
|
$syncDebug[] = ['ts' => time(), 'track' => $track, 'school' => $school, 'attempt' => 'referral-get', 'status' => $resp4['status'] ?? null, 'body' => $resp4['body'] ?? null];
|
|
if ($resp4['status'] >= 200 && $resp4['status'] < 300 && !empty($resp4['body'])) {
|
|
// naive scan for a merchant_id field anywhere in response
|
|
$stack = [$resp4['body']];
|
|
while (!$merchantId && $stack) {
|
|
$node = array_pop($stack);
|
|
if (is_array($node)) {
|
|
if (isset($node['merchant_id']) && $node['merchant_id']) {
|
|
$merchantId = $node['merchant_id'];
|
|
break;
|
|
}
|
|
foreach ($node as $v) { if (is_array($v)) { $stack[] = $v; } }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($merchantId) {
|
|
$entry['merchant_id'] = $merchantId;
|
|
$entry['status'] = 'connected';
|
|
$entry['connected_at'] = time();
|
|
$merchants[$school] = [
|
|
'merchant_id' => $merchantId,
|
|
'tracking_id' => $track,
|
|
'connected_at' => $entry['connected_at'],
|
|
];
|
|
$updated++;
|
|
} else {
|
|
// Mark as incomplete if no merchant ID found
|
|
$entry['status'] = 'incomplete_onboarding';
|
|
$entry['last_sync_at'] = time();
|
|
$entry['note'] = 'Merchant has not completed PayPal onboarding. Only partner ID is available.';
|
|
}
|
|
}
|
|
unset($entry);
|
|
|
|
$storage->set('pending_onboarding', $pending);
|
|
$storage->set('merchants', $merchants);
|
|
$storage->set('sync_debug', $syncDebug);
|
|
|
|
header('Location: ' . rtrim($config['base_url'], '/') . '/index.php?sync=' . $updated);
|
|
exit;
|
|
} catch (Throwable $e) {
|
|
http_response_code(500);
|
|
echo 'Sync failed: ' . htmlspecialchars($e->getMessage());
|
|
}
|