feat: wire discord and paypal configs to panel settings

Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/6163aa0e-000d-4376-ad24-9f63a04f4d95

Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-04-21 13:28:06 +00:00 committed by GitHub
parent c1d7c27b35
commit 428bccb6ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 336 additions and 134 deletions

View file

@ -39,7 +39,7 @@ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
</ul>
<h3>Sandbox account (testing)</h3>
<p>Use PayPal sandbox credentials when testing payments. Set your sandbox <code>client_id</code> and <code>client_secret</code> in the runtime config that the payment handlers use (for this site those are in the respective files under <code>_website/api/</code> or in a central config if you moved credentials).</p>
<p>Use PayPal sandbox credentials when testing payments. Configure all PayPal fields in the panel settings page (<code>home.php?m=settings</code>) so billing endpoints read values from <code>ogp_settings</code>.</p>
<ul>
<li>Create a sandbox business account at <a href="https://developer.paypal.com">PayPal Developer</a> and obtain a sandbox client ID/secret.</li>
<li>Update the payment handler config and restart the webserver if required.</li>

View file

@ -6,6 +6,7 @@
*/
require_once(__DIR__ . '/../includes/config_loader.php');
require_once(__DIR__ . '/../includes/runtime_settings.php');
// Prevent any output before JSON
ob_start();
@ -50,10 +51,16 @@ if (!$paypal_order_id) {
log_payment('REQUEST_START', ['order_id' => $paypal_order_id]);
// PayPal API configuration
$sandbox = true;
$client_id = 'AfvY_C2zA_hTHxHq7TIhtOeub4xBdySYrt_Hjj3d_WYQwjWI9NfOAVOTeResx2rgZ_nP5tOoxQSAHw8c';
$client_secret = 'EJ216np9cAj9n7KSddez3fLVxGe-zi4oKKKl1YGqPp88XIikr4Qzbxh0XW2as-V6LgdX-upjtQAg9dC0';
$api = $sandbox ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
$paypalSettings = billing_get_paypal_settings();
$client_id = $paypalSettings['client_id'];
$client_secret = $paypalSettings['client_secret'];
$api = $paypalSettings['api_base'];
if (!billing_paypal_is_ready($paypalSettings)) {
log_payment('PAYPAL_NOT_CONFIGURED', ['enabled' => $paypalSettings['enabled'] ?? false]);
ob_clean();
echo json_encode(['error' => 'paypal_not_configured', 'request_id' => $requestId]);
exit;
}
// Get OAuth token
$ch = curl_init("$api/v1/oauth2/token");
@ -366,4 +373,3 @@ echo json_encode([
'provisioned' => $autoProvisionResult['provisioned_count'] ?? 0
]);

View file

@ -9,10 +9,12 @@ ini_set('display_errors', '0');
error_reporting(E_ALL);
require_once(__DIR__ . '/../includes/config_loader.php');
require_once(__DIR__ . '/../includes/runtime_settings.php');
// create_order for PayPal — adapted to run from _website/api
$sandbox = true; // flip to false for Live
$client_id = 'AfvY_C2zA_hTHxHq7TIhtOeub4xBdySYrt_Hjj3d_WYQwjWI9NfOAVOTeResx2rgZ_nP5tOoxQSAHw8c';
$client_secret = 'EJ216np9cAj9n7KSddez3fLVxGe-zi4oKKKl1YGqPp88XIikr4Qzbxh0XW2as-V6LgdX-upjtQAg9dC0';
$paypalSettings = billing_get_paypal_settings();
$sandbox = !empty($paypalSettings['sandbox']);
$client_id = $paypalSettings['client_id'];
$client_secret = $paypalSettings['client_secret'];
// Setup comprehensive logging
$logDir = __DIR__ . '/../logs';
@ -62,7 +64,7 @@ if (!$in) {
}
$amount_in = $in['amount'] ?? '0.00';
$currency = $in['currency'] ?? 'USD';
$currency = $in['currency'] ?? $paypalSettings['currency'];
$invoice_id = $in['invoice_id'] ?? null;
$custom_id = $in['custom_id'] ?? null;
$description = $in['description'] ?? 'Order';
@ -96,7 +98,7 @@ if ($items) {
]);
}
$api = $sandbox ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
$api = $paypalSettings['api_base'];
create_order_log('PAYPAL_API_CONFIG', [
'sandbox_mode' => $sandbox,
'api_base' => $api,
@ -104,6 +106,13 @@ create_order_log('PAYPAL_API_CONFIG', [
'has_client_secret' => !empty($client_secret)
]);
if (!billing_paypal_is_ready($paypalSettings)) {
create_order_log('PAYPAL_NOT_CONFIGURED', ['enabled' => $paypalSettings['enabled'] ?? false]);
http_response_code(503);
echo json_encode(['error' => 'paypal_not_configured', 'request_id' => $requestId]);
exit;
}
// Step 1: Get OAuth token
create_order_log('OAUTH_REQUEST_START', ['endpoint' => "$api/v1/oauth2/token"]);
@ -154,7 +163,7 @@ if (!$access) {
create_order_log('OAUTH_SUCCESS', ['token_length' => strlen($access)]);
// Update site base URL to exclude 'modules/billing'
$siteBaseUrl = 'http://gameservers.world';
$siteBaseUrl = $paypalSettings['site_base'];
create_order_log('URL_PROCESSING_BEFORE', [
'return_url' => $return_url,
@ -163,11 +172,15 @@ create_order_log('URL_PROCESSING_BEFORE', [
]);
// Ensure return_url and cancel_url are absolute URLs (relative to site root)
if (strpos($return_url, 'http') !== 0) {
$return_url = $siteBaseUrl . '/' . ltrim($return_url, '/');
if (empty($return_url)) {
$return_url = $paypalSettings['return_url'];
} elseif (strpos($return_url, 'http') !== 0) {
$return_url = billing_absolute_url($return_url, $siteBaseUrl);
}
if (strpos($cancel_url, 'http') !== 0) {
$cancel_url = $siteBaseUrl . '/' . ltrim($cancel_url, '/');
if (empty($cancel_url)) {
$cancel_url = $paypalSettings['cancel_url'];
} elseif (strpos($cancel_url, 'http') !== 0) {
$cancel_url = billing_absolute_url($cancel_url, $siteBaseUrl);
}
create_order_log('URL_PROCESSING_AFTER', [

View file

@ -13,6 +13,7 @@ if (session_status() === PHP_SESSION_NONE) {
// Load configuration
require_once(__DIR__ . '/bootstrap.php');
require_once(__DIR__ . '/includes/runtime_settings.php');
// Variables from config.inc.php (helps IDEs understand scope)
/** @var string $db_host Database host */
@ -251,8 +252,11 @@ if ($applied_coupon && $coupon_discount_percent > 0) {
$final_amount = $total_amount - $discount_amount;
// PayPal configuration
$sandbox = true;
$client_id = 'AfvY_C2zA_hTHxHq7TIhtOeub4xBdySYrt_Hjj3d_WYQwjWI9NfOAVOTeResx2rgZ_nP5tOoxQSAHw8c';
$paypal_settings = billing_get_paypal_settings();
$client_id = $paypal_settings['client_id'];
$paypal_currency = $paypal_settings['currency'];
$paypal_enabled = !empty($paypal_settings['enabled']);
$paypal_ready = billing_paypal_is_ready($paypal_settings);
// Prepare PayPal items
$paypal_items = [];
@ -264,7 +268,7 @@ foreach ($invoices as $inv) {
'description' => $inv['description'] ?? '',
'quantity' => $qty,
'unit_amount' => [
'currency_code' => 'USD',
'currency_code' => $paypal_currency,
'value' => number_format(floatval($inv['amount']) / $qty, 2, '.', '')
]
];
@ -507,8 +511,8 @@ $siteBase = $protocol . $host;
<!-- Favicon -->
<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): ?>
<script src="https://www.paypal.com/sdk/js?client-id=<?php echo htmlspecialchars($client_id); ?>&currency=USD&intent=capture"></script>
<?php if (!$cart_empty && $paypal_ready): ?>
<script src="https://www.paypal.com/sdk/js?client-id=<?php echo htmlspecialchars($client_id); ?>&currency=<?php echo urlencode($paypal_currency); ?>&intent=capture"></script>
<?php endif; ?>
</head>
<body>
@ -623,9 +627,14 @@ $siteBase = $protocol . $host;
<div class="checkout-section">
<h3>Checkout with PayPal</h3>
<p>Click the button below to complete your purchase securely through PayPal.</p>
<div id="paypal-button-container"></div>
<div id="status-message" class="status-message"></div>
<?php if (!$paypal_enabled): ?>
<div class="alert alert-error">PayPal checkout is currently disabled by the administrator.</div>
<?php elseif (!$paypal_ready): ?>
<div class="alert alert-error">PayPal checkout is not configured yet. Please contact support.</div>
<?php else: ?>
<div id="paypal-button-container"></div>
<div id="status-message" class="status-message"></div>
<?php endif; ?>
<div class="action-buttons">
<a href="/order.php" class="btn btn-secondary">Continue Shopping</a>
@ -633,6 +642,7 @@ $siteBase = $protocol . $host;
</div>
</div>
<?php if ($paypal_ready): ?>
<script>
function setStatus(msg) {
const statusDiv = document.getElementById('status-message');
@ -646,17 +656,17 @@ $siteBase = $protocol . $host;
return actions.order.create({
purchase_units: [{
amount: {
currency_code: 'USD',
currency_code: '<?php echo htmlspecialchars($paypal_currency); ?>',
value: '<?php echo number_format($final_amount, 2, '.', ''); ?>',
breakdown: {
item_total: {
currency_code: 'USD',
currency_code: '<?php echo htmlspecialchars($paypal_currency); ?>',
value: '<?php echo number_format($total_amount, 2, '.', ''); ?>'
}
<?php if ($discount_amount > 0): ?>
,
discount: {
currency_code: 'USD',
currency_code: '<?php echo htmlspecialchars($paypal_currency); ?>',
value: '<?php echo number_format($discount_amount, 2, '.', ''); ?>'
}
<?php endif; ?>
@ -708,10 +718,11 @@ $siteBase = $protocol . $host;
onCancel: function(data) {
setStatus('Payment cancelled');
window.location.href = '/payment_cancel.php';
window.location.href = '<?php echo htmlspecialchars($paypal_settings['cancel_url']); ?>';
}
}).render('#paypal-button-container');
</script>
<?php endif; ?>
<script>
// Remove invoice via AJAX and perform a partial reload of the cart container
function removeInvoice(invoiceId) {
@ -760,4 +771,3 @@ $siteBase = $protocol . $host;
<?php include(__DIR__ . '/includes/footer.php'); ?>
</body>
</html>

View file

@ -146,21 +146,8 @@ function exec_ogp_module()
//WEBHOOK Discord=======================================================================================
$webhookurl = $settings['webhookurl'];
$msg = "The ". $home_name ." server ID #". $home_id . " has just been renewed.";
$json_data = array ('content'=>"$msg");
$make_json = json_encode($json_data);
$ch = curl_init( $webhookurl );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
curl_setopt( $ch, CURLOPT_POST, 1);
curl_setopt( $ch, CURLOPT_POSTFIELDS, $make_json);
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt( $ch, CURLOPT_HEADER, 0);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec( $ch );
//If you need to debug, or find out why you can't send message uncomment line below, and execute script.
//echo $response;
ogp_send_discord_notification($settings, $msg, 'notify_server_events');
//end WEBHOOK Discord
}
@ -310,24 +297,8 @@ function exec_ogp_module()
//WEBHOOK Discord=======================================================================================
$webhookurl = "https://discord.com/api/webhooks/710275918274363412/g5Tr-EUdEnLfFryOlscxJ6FuPiSJuE6EMKRYmh9UGMiqTUxU5-y9CQrBlDJW7znr0Tol";
//$settings['webhookurl'];
$msg = "A new server, ". $home_name ." ID #". $home_id . ", has just been created.";
$json_data = array ('content'=>"$msg");
$make_json = json_encode($json_data);
$ch = curl_init( $webhookurl );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
curl_setopt( $ch, CURLOPT_POST, 1);
curl_setopt( $ch, CURLOPT_POSTFIELDS, $make_json);
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt( $ch, CURLOPT_HEADER, 0);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec( $ch );
//If you need to debug, or find out why you can't send message uncomment line below, and execute script.
//echo $response;
ogp_send_discord_notification($settings, $msg, 'notify_server_events');
//end WEBHOOK Discord
}
// END EMAIL
@ -449,4 +420,3 @@ function exec_ogp_module()

View file

@ -0,0 +1,99 @@
<?php
require_once(__DIR__ . '/panel_bridge.php');
if (!function_exists('billing_bool_setting')) {
function billing_bool_setting($value, $default = false)
{
if ($value === null || $value === '') {
return $default;
}
if (is_bool($value)) {
return $value;
}
$value = strtolower(trim((string)$value));
return in_array($value, array('1', 'true', 'yes', 'on'), true);
}
}
if (!function_exists('billing_detect_site_base')) {
function billing_detect_site_base()
{
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? trim((string)$_SERVER['HTTP_HOST']) : 'localhost';
return $scheme . '://' . $host;
}
}
if (!function_exists('billing_absolute_url')) {
function billing_absolute_url($url, $siteBase)
{
$url = trim((string)$url);
if ($url === '') {
return '';
}
if (preg_match('#^https?://#i', $url)) {
return $url;
}
return rtrim($siteBase, '/') . '/' . ltrim($url, '/');
}
}
if (!function_exists('billing_get_paypal_settings')) {
function billing_get_paypal_settings()
{
$panelSettings = billing_get_panel_settings();
$mode = strtolower(trim((string)($panelSettings['paypal_mode'] ?? 'sandbox')));
if (!in_array($mode, array('sandbox', 'live'), true)) {
$mode = 'sandbox';
}
$sandboxClientId = trim((string)($panelSettings['paypal_sandbox_client_id'] ?? ''));
$sandboxClientSecret = trim((string)($panelSettings['paypal_sandbox_client_secret'] ?? ''));
$liveClientId = trim((string)($panelSettings['paypal_live_client_id'] ?? ''));
$liveClientSecret = trim((string)($panelSettings['paypal_live_client_secret'] ?? ''));
$fallbackClientId = trim((string)($panelSettings['paypal_client_id'] ?? ''));
$fallbackClientSecret = trim((string)($panelSettings['paypal_client_secret'] ?? ''));
$clientId = $mode === 'live' ? $liveClientId : $sandboxClientId;
$clientSecret = $mode === 'live' ? $liveClientSecret : $sandboxClientSecret;
if ($clientId === '') {
$clientId = $fallbackClientId;
}
if ($clientSecret === '') {
$clientSecret = $fallbackClientSecret;
}
$currency = strtoupper(trim((string)($panelSettings['paypal_currency'] ?? 'USD')));
if ($currency === '') {
$currency = 'USD';
}
$enabled = billing_bool_setting($panelSettings['paypal_enabled'] ?? null, ($clientId !== '' && $clientSecret !== ''));
$siteBase = billing_detect_site_base();
$returnUrl = billing_absolute_url($panelSettings['paypal_return_url'] ?? '/payment_success.php', $siteBase);
$cancelUrl = billing_absolute_url($panelSettings['paypal_cancel_url'] ?? '/payment_cancel.php', $siteBase);
return array(
'enabled' => $enabled,
'mode' => $mode,
'sandbox' => $mode !== 'live',
'client_id' => $clientId,
'client_secret' => $clientSecret,
'currency' => $currency,
'webhook_id' => trim((string)($panelSettings['paypal_webhook_id'] ?? '')),
'email' => trim((string)($panelSettings['paypal_email'] ?? '')),
'return_url' => $returnUrl,
'cancel_url' => $cancelUrl,
'site_base' => $siteBase,
'api_base' => $mode === 'live' ? 'https://api-m.paypal.com' : 'https://api-m.sandbox.paypal.com',
);
}
}
if (!function_exists('billing_paypal_is_ready')) {
function billing_paypal_is_ready($settings)
{
return !empty($settings['enabled']) && !empty($settings['client_id']) && !empty($settings['client_secret']);
}
}

View file

@ -1,16 +1,21 @@
<?php
require_once(__DIR__ . '/includes/config_loader.php');
require_once(__DIR__ . '/includes/runtime_settings.php');
if (is_file(__DIR__ . '/includes/log.php')) require_once(__DIR__ . '/includes/log.php');
$paypalSettings = billing_get_paypal_settings();
$dataDir = rtrim(
(defined('SITE_DATA_DIR') ? SITE_DATA_DIR : '') ?: ($SITE_DATA_DIR ?? ''),
DIRECTORY_SEPARATOR
);
$config = [
'sandbox' => true,
'client_id' => 'AfvY_C2zA_hTHxHq7TIhtOeub4xBdySYrt_Hjj3d_WYQwjWI9NfOAVOTeResx2rgZ_nP5tOoxQSAHw8c',
'client_secret' => 'EJ216np9cAj9n7KSddez3fLVxGe-zi4oKKKl1YGqPp88XIikr4Qzbxh0XW2as-V6LgdX-upjtQAg9dC0',
'webhook_id' => '6N620673281740730',
'data_dir' => rtrim(
(defined('SITE_DATA_DIR') ? SITE_DATA_DIR : '') ?: ($SITE_DATA_DIR ?? ''),
DIRECTORY_SEPARATOR
),
'sandbox' => !empty($paypalSettings['sandbox']),
'enabled' => !empty($paypalSettings['enabled']),
'client_id' => $paypalSettings['client_id'],
'client_secret' => $paypalSettings['client_secret'],
'webhook_id' => $paypalSettings['webhook_id'],
'data_dir' => $dataDir,
'log_file' => __DIR__ . '/data/webhook.log',
];
@ -24,6 +29,12 @@ function api_base(){global $config; return $config['sandbox'] ? 'https://api-m.s
http_response_code(200);
@mkdir($config['data_dir'], 0775, true);
if (empty($config['enabled']) || empty($config['client_id']) || empty($config['client_secret']) || empty($config['webhook_id'])) {
if (function_exists('site_log_warn')) site_log_warn('paypal_webhook_not_configured', ['enabled' => $config['enabled']]);
else log_line("PAYPAL_WEBHOOK_NOT_CONFIGURED");
exit;
}
$raw = file_get_contents('php://input');
$headers = array_change_key_case(getallheaders() ?: [], CASE_UPPER);
if (function_exists('site_log_info')) site_log_info('webhook_hit', ['ip'=>($_SERVER['REMOTE_ADDR']??''),'bytes'=>strlen($raw)]);