feat: add PayPal sandbox/live credentials, webhook endpoint, and admin diagnostics

- config.inc.php: new sandbox/live credential structure with paypal_mode, separate
  sandbox/live client_id, client_secret, webhook_id, and webhook_path
- config.example.php: updated to match new structure
- config_loader.php: adds defaults and backward compat mapping from old
  $paypal_sandbox/$paypal_client_id variables; adds gsp_paypal_* helper functions
- PayPalGateway.php: fromConfig() uses gsp_paypal_* helpers with fallback
- cart.php: uses gsp_paypal_get_client_id()/gsp_paypal_is_sandbox() helpers
- webhook.php: updated to use gsp_paypal_* helpers for credentials/API base
- paypal/webhook.php: new full-featured webhook receiver with signature
  verification, idempotency log, event processing, provisioning trigger
- admin_config.php: expanded to separate sandbox/live fields, computed webhook URL,
  diagnostics panel showing credential status and recent webhook events
- module.php: bumped to v3.3/db_version 3, adds billing_paypal_webhook_events table

Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/f974e469-8562-41df-ba37-bc340f5a154c

Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-06 16:14:47 +00:00 committed by GitHub
parent 0f4c4b3634
commit 41a812fdd6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 1351 additions and 109 deletions

View file

@ -253,8 +253,8 @@ if ($applied_coupon && $coupon_discount_percent > 0) {
$final_amount = $total_amount - $discount_amount;
// PayPal configuration (from config)
$sandbox = $paypal_sandbox ?? true;
$client_id = $paypal_client_id ?? '';
$client_id = function_exists('gsp_paypal_get_client_id') ? gsp_paypal_get_client_id() : ($paypal_client_id ?? '');
$sandbox = function_exists('gsp_paypal_is_sandbox') ? gsp_paypal_is_sandbox() : ($paypal_sandbox ?? true);
// Prepare PayPal items
$paypal_items = [];
@ -510,7 +510,7 @@ $siteBase = $protocol . $host;
<link rel="icon" href="images/logo-sm.png" type="image/png">
<link rel="apple-touch-icon" href="images/logo-sm.png">
<?php if (!$cart_empty && !empty($client_id)): ?>
<script src="https://www.paypal.com/sdk/js?client-id=<?php echo htmlspecialchars($client_id); ?>&currency=USD&intent=capture"></script>
<script src="https://www.paypal.com/sdk/js?client-id=<?php echo htmlspecialchars($client_id, ENT_QUOTES, 'UTF-8'); ?>&currency=USD&intent=capture<?php echo $sandbox ? '&debug=false' : ''; ?>"></script>
<?php endif; ?>
</head>
<body>
@ -659,7 +659,7 @@ $siteBase = $protocol . $host;
}
if ($cart_is_admin):
?>
<br><small><em>Admin: set <code>$paypal_client_id</code> in <a href="/admin_config.php" style="color:inherit;text-decoration:underline;">Site Config</a>.</em></small>
<br><small><em>Admin: configure PayPal credentials in <a href="/admin_config.php" style="color:inherit;text-decoration:underline;">Site Config</a>.</em></small>
<?php endif; ?>
</div>
<?php else: ?>