website fixes
This commit is contained in:
parent
2efbe27a03
commit
2347205469
13 changed files with 500 additions and 418 deletions
|
|
@ -21,7 +21,7 @@ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
|||
<h1>Admin Dashboard</h1>
|
||||
<p>Welcome to the admin area. From here you can manage servers, payments, and site settings.</p>
|
||||
|
||||
<div style="display:flex;gap:12px;flex-wrap:wrap;margin-top:12px;">
|
||||
<div class="admin-flex-wrap">
|
||||
<a class="gsw-btn" href="adminserverlist.php">Manage Servers & Services</a>
|
||||
<a class="gsw-btn" href="./invoices.php">Invoice History</a>
|
||||
<a class="gsw-btn" href="admin_config.php">Edit Site Config</a>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['create_free_for']))
|
|||
$orderId = (int)$_POST['create_free_for'];
|
||||
if ($orderId > 0) {
|
||||
// load order to verify ownership/price
|
||||
$stmt = $db->prepare("SELECT user_id, price, status, qty, invoice_duration FROM ogp_billing_orders WHERE order_id = ? LIMIT 1");
|
||||
$stmt = $db->prepare("SELECT user_id, price, status, qty, invoice_duration FROM " . $table_prefix . "billing_orders WHERE order_id = ? LIMIT 1");
|
||||
if ($stmt) {
|
||||
$stmt->bind_param('i', $orderId);
|
||||
$stmt->execute();
|
||||
|
|
@ -106,15 +106,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['create_free_for']))
|
|||
$finish_date = date('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
// Check if finish_date column exists
|
||||
$finish_col_exists = false;
|
||||
$col_check = mysqli_query($db, "SHOW COLUMNS FROM ogp_billing_orders LIKE 'finish_date'");
|
||||
if ($col_check && mysqli_num_rows($col_check) > 0) $finish_col_exists = true;
|
||||
// Check if finish_date column exists (use table prefix)
|
||||
$finish_col_exists = false;
|
||||
$col_check = mysqli_query($db, "SHOW COLUMNS FROM " . $table_prefix . "billing_orders LIKE 'finish_date'");
|
||||
if ($col_check && mysqli_num_rows($col_check) > 0) $finish_col_exists = true;
|
||||
|
||||
// Perform update and log results. Use prepared statements when available and fallback to direct query on error.
|
||||
$updated_rows = 0;
|
||||
if ($finish_col_exists) {
|
||||
$upd = $db->prepare("UPDATE ogp_billing_orders SET status = 'paid', finish_date = ? WHERE order_id = ? LIMIT 1");
|
||||
$upd = $db->prepare("UPDATE " . $table_prefix . "billing_orders SET status = 'paid', finish_date = ? WHERE order_id = ? LIMIT 1");
|
||||
if ($upd) {
|
||||
$upd->bind_param('si', $finish_date, $orderId);
|
||||
$ok = $upd->execute();
|
||||
|
|
@ -124,13 +124,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['create_free_for']))
|
|||
} else {
|
||||
// fallback
|
||||
$safe_fd = mysqli_real_escape_string($db, $finish_date);
|
||||
$q = "UPDATE ogp_billing_orders SET status = 'paid', finish_date = '$safe_fd' WHERE order_id = " . intval($orderId) . " LIMIT 1";
|
||||
$q = "UPDATE " . $table_prefix . "billing_orders SET status = 'paid', finish_date = '$safe_fd' WHERE order_id = " . intval($orderId) . " LIMIT 1";
|
||||
$resq = mysqli_query($db, $q);
|
||||
if (!$resq) site_log_warn('free_create_update_failed_query', ['error'=>mysqli_error($db), 'sql'=>$q]);
|
||||
else $updated_rows = mysqli_affected_rows($db);
|
||||
}
|
||||
} else {
|
||||
$upd = $db->prepare("UPDATE ogp_billing_orders SET status = 'paid' WHERE order_id = ? LIMIT 1");
|
||||
$upd = $db->prepare("UPDATE " . $table_prefix . "billing_orders SET status = 'paid' WHERE order_id = ? LIMIT 1");
|
||||
if ($upd) {
|
||||
$upd->bind_param('i', $orderId);
|
||||
$ok = $upd->execute();
|
||||
|
|
@ -138,7 +138,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['create_free_for']))
|
|||
$updated_rows = $upd->affected_rows;
|
||||
$upd->close();
|
||||
} else {
|
||||
$q = "UPDATE ogp_billing_orders SET status = 'paid' WHERE order_id = " . intval($orderId) . " LIMIT 1";
|
||||
$q = "UPDATE " . $table_prefix . "billing_orders SET status = 'paid' WHERE order_id = " . intval($orderId) . " LIMIT 1";
|
||||
$resq = mysqli_query($db, $q);
|
||||
if (!$resq) site_log_warn('free_create_update_failed_query', ['error'=>mysqli_error($db), 'sql'=>$q]);
|
||||
else $updated_rows = mysqli_affected_rows($db);
|
||||
|
|
@ -248,20 +248,28 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_single'])) {
|
|||
$stmt->bind_param("ii", $order_id, $user_id);
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($status);
|
||||
if ($stmt->fetch() && strtolower($status) === 'renew') {
|
||||
$stmt->close();
|
||||
// Set status to 'expired' if currently 'renew'
|
||||
$update = $db->prepare("UPDATE ogp_billing_orders SET status = 'expired' WHERE order_id = ? AND user_id = ?");
|
||||
$update->bind_param("ii", $order_id, $user_id);
|
||||
$update->execute();
|
||||
$update->close();
|
||||
if ($stmt->fetch() && strtolower($status) === 'renew') {
|
||||
$stmt->close();
|
||||
// If user removes a renewal from their cart, revert the order back to 'installed'
|
||||
$update = $db->prepare("UPDATE ogp_billing_orders SET status = 'installed' WHERE order_id = ? AND user_id = ?");
|
||||
$update->bind_param("ii", $order_id, $user_id);
|
||||
$update->execute();
|
||||
// Log revert action to panel logger
|
||||
if (isset($db) && method_exists($db, 'logger')) {
|
||||
$db->logger("USER-CART: User " . intval($user_id) . " reverted renew for order " . intval($order_id));
|
||||
}
|
||||
$update->close();
|
||||
} else {
|
||||
$stmt->close();
|
||||
// Otherwise, delete the order
|
||||
$delete = $db->prepare("DELETE FROM ogp_billing_orders WHERE order_id = ? AND user_id = ?");
|
||||
$delete->bind_param("ii", $order_id, $user_id);
|
||||
$delete->execute();
|
||||
$delete->close();
|
||||
$delete->execute();
|
||||
// Log deletion to panel logger
|
||||
if (isset($db) && method_exists($db, 'logger')) {
|
||||
$db->logger("USER-CART: User " . intval($user_id) . " deleted order " . intval($order_id));
|
||||
}
|
||||
$delete->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -318,6 +326,15 @@ if ($db){
|
|||
<td>$<?php echo number_format($row['price'], 2); ?></td>
|
||||
<td><?php echo htmlspecialchars($row['qty']); ?></td>
|
||||
<?php $rowtotal = $row['price'] * $row['qty'] * $row['max_players'];?>
|
||||
<?php
|
||||
// Build invoice and line item structures used later when creating PayPal order
|
||||
if (!isset($invoice) || !is_array($invoice)) $invoice = [];
|
||||
$invoice[] = [
|
||||
'serverID' => isset($row['home_id']) ? (string)$row['home_id'] : ('order'.$row['order_id']),
|
||||
'amount' => number_format($rowtotal, 2, '.', ''),
|
||||
'order_id' => intval($row['order_id'])
|
||||
];
|
||||
?>
|
||||
<?php
|
||||
// Use the previously resolved $is_admin (computed once above)
|
||||
$is_free = ((float)$row['price'] == 0.0);
|
||||
|
|
@ -329,7 +346,7 @@ if ($db){
|
|||
<button type="submit" class="gsw-btn"><?php echo $is_admin ? 'Create (Free)' : 'Claim (Free)'; ?></button>
|
||||
</form>
|
||||
<?php if ($is_admin): ?>
|
||||
<div style="font-size:11px;color:#666;margin-top:4px;">Admin: force-create a paid record for testing.</div>
|
||||
<div class="admin-note">Admin: force-create a paid record for testing.</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php else: ?>
|
||||
|
|
@ -401,6 +418,11 @@ $invoiceId = 'INV-' . date('Ymd-His') . '-' . bin2hex(random_bytes(3));
|
|||
// A short custom reference derived from your line items (<= 127 chars for PayPal)
|
||||
$customHash = substr(strtoupper(sha1(json_encode($invoice))), 0, 16);
|
||||
$customId = "INVREF-$customHash";
|
||||
// If the cart contains a single order, set custom_id to the numeric order id so webhooks
|
||||
// can match the order directly (payment_success matches numeric custom -> order_id).
|
||||
if (is_array($invoice) && count($invoice) === 1 && !empty($invoice[0]['order_id'])) {
|
||||
$customId = (string) intval($invoice[0]['order_id']);
|
||||
}
|
||||
|
||||
// Text on the PayPal side
|
||||
$description = 'Game server order (' . count($lineItems) . ' item' . (count($lineItems)===1?'': 's') . ')';
|
||||
|
|
|
|||
|
|
@ -20,6 +20,19 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*
|
||||
*
|
||||
|
||||
Complete Status Flow:
|
||||
in-cart - User added to cart, not yet paid
|
||||
renew - Renewal order in cart
|
||||
paid - Payment received, awaiting server creation
|
||||
installed - ✅ Active/Running (server provisioned and operational)
|
||||
invoiced - Invoice generated, payment due (7 days before expiration)
|
||||
suspended - Server stopped, payment overdue
|
||||
deleted - Server permanently removed (7 days after suspension)
|
||||
expired - Order has expired
|
||||
unknown - Error/undefined state
|
||||
*/
|
||||
|
||||
chdir(realpath(dirname(__FILE__))); /* Change to the current file path */
|
||||
|
|
@ -68,7 +81,16 @@ else
|
|||
foreach($user_homes as $user_home)
|
||||
{
|
||||
|
||||
$user_id = $user_home['user_id'];
|
||||
// Developer note:
|
||||
// In future we may want to change the renewal/invoice strategy so that a
|
||||
// new order record is created for the renewal (leaving the original order
|
||||
// intact) instead of mutating the existing order's status/finish_date.
|
||||
// Creating a separate renewal order gives a clearer, immutable purchase
|
||||
// history and simplifies auditing. For now this cron job continues to
|
||||
// update the existing order (change status/finish_date) as implemented
|
||||
// below.
|
||||
|
||||
$user_id = $user_home['user_id'];
|
||||
$home_id = $user_home['home_id'];
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,21 @@ input, textarea, select, button { color: #fff; background: #11141f; border: 1px
|
|||
#gsw-site a.gsw-btn:hover,
|
||||
#gsw-site button.gsw-btn:hover{transform:translateY(-2px);color:#fff !important;text-decoration:none;}
|
||||
|
||||
/* Renew button: slightly smaller but matching gradient, used on My Account cards */
|
||||
#gsw-site .renew-btn, #gsw-site a.renew-btn, #gsw-site button.renew-btn{
|
||||
display:inline-block;
|
||||
padding:8px 14px;
|
||||
background:linear-gradient(135deg,#f59e0b 0%,#ef4444 100%) !important;
|
||||
color:#fff !important;
|
||||
text-decoration:none;
|
||||
border-radius:8px;
|
||||
font-weight:700;
|
||||
transition:transform 0.12s;
|
||||
border:none;
|
||||
cursor:pointer;
|
||||
}
|
||||
#gsw-site .renew-btn:hover, #gsw-site a.renew-btn:hover, #gsw-site button.renew-btn:hover{transform:translateY(-2px);}
|
||||
|
||||
#gsw-site .gsw-btn-secondary,
|
||||
#gsw-site a.gsw-btn-secondary{display:inline-block;padding:10px 16px;background:rgba(255,255,255,0.06);color:#fff !important;text-decoration:none;border-radius:8px;border:1px solid rgba(255,255,255,0.06);cursor:pointer;}
|
||||
#gsw-site .gsw-btn-secondary:hover,
|
||||
|
|
@ -152,3 +167,135 @@ input, textarea, select, button { color: #fff; background: #11141f; border: 1px
|
|||
.ml-8{margin-left:8px}
|
||||
.flex-row-gap{display:flex;gap:8px;align-items:center}
|
||||
|
||||
/* Account page styles */
|
||||
.account-container{max-width:1000px;margin:20px auto;padding:20px}
|
||||
.account-section{background:rgba(0,0,0,0.25);padding:20px;border-radius:8px;margin-bottom:20px}
|
||||
.account-section h2{margin:0 0 15px 0;font-size:1.3rem;color:#fff;border-bottom:2px solid rgba(255,255,255,0.1);padding-bottom:10px}
|
||||
.account-info-grid{display:grid;grid-template-columns:1fr 1fr;gap:15px;margin-bottom:15px}
|
||||
.account-info-item{padding:10px;background:rgba(255,255,255,0.03);border-radius:6px}
|
||||
.account-info-label{font-weight:600;color:rgba(255,255,255,0.7);font-size:0.9rem;margin-bottom:5px}
|
||||
.account-info-value{color:#fff;font-size:1rem}
|
||||
.account-edit-summary{cursor:pointer;color:#667eea;font-weight:600;margin-top:10px}
|
||||
|
||||
/* Form styles */
|
||||
.form-group{margin-bottom:15px}
|
||||
.form-group label{display:block;margin-bottom:5px;color:#fff;font-weight:500}
|
||||
.form-group input{width:100%;padding:10px;border:1px solid rgba(255,255,255,0.1);border-radius:6px;background:rgba(0,0,0,0.3);color:#fff}
|
||||
|
||||
/* Alert messages */
|
||||
.alert{padding:12px 16px;border-radius:8px;margin-bottom:20px;font-size:0.95rem}
|
||||
.alert-error{background-color:rgba(255,0,0,0.2);border:1px solid rgba(255,0,0,0.3);color:#ffcccc}
|
||||
.alert-success{background-color:rgba(0,255,0,0.2);border:1px solid rgba(0,255,0,0.3);color:#ccffcc}
|
||||
|
||||
/* Server item cards */
|
||||
.server-item{background:rgba(255,255,255,0.03);padding:15px;border-radius:6px;margin-bottom:10px;border-left:3px solid #667eea}
|
||||
.server-name{font-size:1.1rem;font-weight:600;color:#fff;margin-bottom:8px}
|
||||
.server-details{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-top:10px}
|
||||
.server-detail{font-size:0.9rem}
|
||||
.server-detail-label{color:rgba(255,255,255,0.6)}
|
||||
.server-detail-value{color:#fff;font-weight:500}
|
||||
|
||||
/* Invoice items */
|
||||
.invoice-item{background:rgba(255,255,255,0.03);padding:12px 15px;border-radius:6px;margin-bottom:8px;display:flex;justify-content:space-between;align-items:center}
|
||||
.invoice-id{font-weight:600;color:#fff}
|
||||
.invoice-amount{color:#10b981;font-weight:600}
|
||||
.invoice-status{padding:4px 10px;border-radius:4px;font-size:0.85rem;font-weight:600}
|
||||
.invoice-status-paid{background:rgba(16,185,129,0.2);color:#10b981}
|
||||
.invoice-status-pending{background:rgba(245,158,11,0.2);color:#f59e0b}
|
||||
.invoice-date{color:rgba(255,255,255,0.6);font-size:0.9rem}
|
||||
|
||||
/* Login placeholder for non-logged-in users */
|
||||
.login-placeholder{padding:12px;background:rgba(255,255,255,0.03);border-radius:8px;color:#fff}
|
||||
.login-placeholder a{color:#cfe6ff;text-decoration:underline}
|
||||
|
||||
/* No data state */
|
||||
.no-data{text-align:center;padding:30px;color:rgba(255,255,255,0.6)}
|
||||
|
||||
/* Service description text */
|
||||
.service-desc{color:gray;width:230px}
|
||||
.service-desc-wide{color:gray;width:280px}
|
||||
.service-textarea{resize:none;width:230px;height:132px}
|
||||
|
||||
/* Admin helpers */
|
||||
.admin-note{font-size:11px;color:#666;margin-top:4px}
|
||||
.admin-flex-wrap{display:flex;gap:12px;flex-wrap:wrap;margin-top:12px}
|
||||
|
||||
@media (max-width:768px){
|
||||
.account-info-grid{grid-template-columns:1fr}
|
||||
}
|
||||
|
||||
/* Server status and utility classes */
|
||||
#gsw-site .text-success {
|
||||
color: #10b981 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
#gsw-site .text-danger {
|
||||
color: #ef4444 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
#gsw-site .text-muted {
|
||||
color: rgba(255,255,255,0.7) !important;
|
||||
}
|
||||
|
||||
#gsw-site .text-center {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
#gsw-site .mb-20 {
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
#gsw-site .server-notes {
|
||||
padding-left: 40px !important;
|
||||
font-size: 0.9rem !important;
|
||||
color: rgba(255,255,255,0.7) !important;
|
||||
}
|
||||
|
||||
/* Status badges */
|
||||
#gsw-site .status-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#gsw-site .status-online {
|
||||
background-color: rgba(16, 185, 129, 0.2);
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
#gsw-site .status-offline {
|
||||
background-color: rgba(239, 68, 68, 0.2);
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
#gsw-site .status-maintenance {
|
||||
background-color: rgba(251, 191, 36, 0.2);
|
||||
color: #fbbf24;
|
||||
}
|
||||
|
||||
#gsw-site .status-unknown {
|
||||
background-color: rgba(156, 163, 175, 0.2);
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
/* Form radio labels in renewal page */
|
||||
#gsw-site .form-group label {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
cursor: pointer;
|
||||
padding: 12px;
|
||||
border: 2px solid #e1e8ed;
|
||||
border-radius: 8px;
|
||||
background: rgba(255,255,255,0.05);
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
#gsw-site .form-group label:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
###############################################
|
||||
# Website Database Configuration
|
||||
# This file contains the database connection
|
||||
# settings for the modules/billing website.
|
||||
#
|
||||
# These settings should match the panel's
|
||||
# database configuration in /includes/config.inc.php
|
||||
# to ensure both the website and panel access
|
||||
# the same database.
|
||||
###############################################
|
||||
$db_host="localhost";
|
||||
$db_user="localuser";
|
||||
$db_pass="Pkloyn7yvpht!";
|
||||
$db_name="panel";
|
||||
$table_prefix="ogp_";
|
||||
$db_type="mysql";
|
||||
|
||||
// Optional: base URL used by admin pages to build absolute image previews.
|
||||
// Leave empty to prefer relative paths (local folder).
|
||||
// To enable production base URL, uncomment and set it to your site, e.g.:
|
||||
// $SITE_BASE_URL = 'https://gameservers.world/';
|
||||
$SITE_BASE_URL = '';
|
||||
|
||||
// Normalize: ensure either empty or ends without trailing slash
|
||||
$SITE_BASE_URL = trim((string)$SITE_BASE_URL);
|
||||
|
||||
// Site-wide background image (relative to site root). Change to your preferred background.
|
||||
$SITE_BACKGROUND = 'images/dark.jpg';
|
||||
// Normalize
|
||||
$SITE_BACKGROUND = trim((string)$SITE_BACKGROUND);
|
||||
|
||||
// Data directory for persisted payment webhook JSON files (relative to module root)
|
||||
$SITE_DATA_DIR = realpath(__DIR__ . '/..') . DIRECTORY_SEPARATOR . 'data';
|
||||
?>
|
||||
|
|
@ -71,16 +71,12 @@ if ($is_logged_in) {
|
|||
<div class="gsw-header-right">
|
||||
<?php if ($is_logged_in): ?>
|
||||
<span class="gsw-user-info">Welcome, <?php echo $username; ?>!</span>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
// Build a safe absolute return_to under this site so logout redirects stay within this module
|
||||
$current = $_SERVER['REQUEST_URI'] ?? '/';
|
||||
$return_to_param = $current;
|
||||
?>
|
||||
<?php if ($is_logged_in): ?>
|
||||
<?php
|
||||
// Build a safe absolute return_to under this site so logout redirects stay within this module
|
||||
$current = $_SERVER['REQUEST_URI'] ?? '/';
|
||||
$return_to_param = $current;
|
||||
?>
|
||||
<a href="logout.php?return_to=<?php echo urlencode($return_to_param); ?>" class="gsw-header-btn">Logout</a>
|
||||
<?php else: ?>
|
||||
<a href="login.php" class="gsw-header-btn">Login</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -90,8 +86,8 @@ if ($is_logged_in) {
|
|||
<a href="index.php" class="gsw-nav-link">Home</a>
|
||||
<a href="serverlist.php" class="gsw-nav-link">Game Servers</a>
|
||||
<?php if ($is_logged_in): ?>
|
||||
<a href="my_account.php" class="gsw-nav-link gsw-nav-link-myaccount">My Account</a>
|
||||
<a href="my_servers.php" class="gsw-nav-link">My Servers</a>
|
||||
<!-- Make My Account a prominent header button and remove My Servers link per UX request -->
|
||||
<a href="my_account.php" class="gsw-header-btn gsw-nav-link-myaccount">My Account</a>
|
||||
<a href="cart.php" class="gsw-nav-link">Cart
|
||||
<?php
|
||||
$cart_count = 0;
|
||||
|
|
@ -102,11 +98,6 @@ if ($is_logged_in) {
|
|||
if ($cart_count > 0) echo ' <span class="cart-badge">' . intval($cart_count) . '</span>';
|
||||
?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<a href="login.php" class="gsw-nav-link gsw-nav-link-myaccount">Login</a>
|
||||
<?php endif; ?>
|
||||
<?php if (basename($_SERVER['PHP_SELF']) === 'login.php'): ?>
|
||||
<a href="register.php" class="gsw-nav-link">Register</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($is_logged_in && $is_admin): ?>
|
||||
<a href="admin.php" class="gsw-nav-link">Admin</a>
|
||||
|
|
|
|||
|
|
@ -4,186 +4,28 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>My Account - GameServers.World</title>
|
||||
<style>
|
||||
.account-container {
|
||||
max-width: 1000px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.account-section {
|
||||
background: rgba(0,0,0,0.25);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.account-section h2 {
|
||||
margin: 0 0 15px 0;
|
||||
font-size: 1.3rem;
|
||||
color: #fff;
|
||||
border-bottom: 2px solid rgba(255,255,255,0.1);
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.account-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.account-info-item {
|
||||
padding: 10px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.account-info-label {
|
||||
font-weight: 600;
|
||||
color: rgba(255,255,255,0.7);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.account-info-value {
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
border-radius: 6px;
|
||||
background: rgba(0,0,0,0.3);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.alert-error {
|
||||
background-color: rgba(255,0,0,0.2);
|
||||
border: 1px solid rgba(255,0,0,0.3);
|
||||
color: #ffcccc;
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background-color: rgba(0,255,0,0.2);
|
||||
border: 1px solid rgba(0,255,0,0.3);
|
||||
color: #ccffcc;
|
||||
}
|
||||
|
||||
.server-item {
|
||||
background: rgba(255,255,255,0.03);
|
||||
padding: 15px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 10px;
|
||||
border-left: 3px solid #667eea;
|
||||
}
|
||||
|
||||
.server-name {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.server-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.server-detail {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.server-detail-label {
|
||||
color: rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
.server-detail-value {
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.invoice-item {
|
||||
background: rgba(255,255,255,0.03);
|
||||
padding: 12px 15px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.invoice-id {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.invoice-amount {
|
||||
color: #10b981;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.invoice-status {
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.invoice-status-paid {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.invoice-status-pending {
|
||||
background: rgba(245, 158, 11, 0.2);
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
.invoice-date {
|
||||
color: rgba(255,255,255,0.6);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
color: rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.account-info-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
// Require login for this page
|
||||
require_once(__DIR__ . '/includes/login_required.php');
|
||||
// Start session to check login status
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_name("gameservers_website");
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Enable error display during debugging so runtime errors show in the page
|
||||
@ini_set('display_errors', 1);
|
||||
@ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
// Check if user is logged in
|
||||
$is_logged_in = (isset($_SESSION['website_user_id']) && !empty($_SESSION['website_user_id'])) || (isset($_SESSION['website_username']) && !empty($_SESSION['website_username']));
|
||||
|
||||
// If not logged in, show login page instead
|
||||
if (!$is_logged_in) {
|
||||
include(__DIR__ . '/login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Include database configuration
|
||||
require_once(__DIR__ . '/includes/config.inc.php');
|
||||
|
|
@ -198,6 +40,8 @@ if (!$db) {
|
|||
include(__DIR__ . '/includes/top.php');
|
||||
include(__DIR__ . '/includes/menu.php');
|
||||
|
||||
// (debug markers removed)
|
||||
|
||||
// Initialize messages
|
||||
$error_message = '';
|
||||
$success_message = '';
|
||||
|
|
@ -272,23 +116,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_info'])) {
|
|||
}
|
||||
}
|
||||
|
||||
// Fetch user's game servers from billing_orders
|
||||
$servers_query = "SELECT
|
||||
o.order_id,
|
||||
o.home_name,
|
||||
o.status,
|
||||
o.price,
|
||||
o.invoice_duration,
|
||||
o.created_at,
|
||||
bs.service_name,
|
||||
rs.remote_server_name
|
||||
FROM ogp_billing_orders o
|
||||
LEFT JOIN ogp_billing_services bs ON o.service_id = bs.service_id
|
||||
LEFT JOIN ogp_remote_servers rs ON o.remote_server_id = rs.remote_server_id
|
||||
WHERE o.user_id = $user_id
|
||||
ORDER BY o.created_at DESC";
|
||||
// Fetch user's orders from billing_orders. Keep this simple: select orders for the user and join service name.
|
||||
// Avoid joins to remote server fields that do not exist on the orders table.
|
||||
$servers_query = "SELECT
|
||||
o.order_id,
|
||||
o.home_name,
|
||||
o.status,
|
||||
o.price,
|
||||
o.invoice_duration,
|
||||
o.home_id,
|
||||
o.finish_date,
|
||||
bs.service_name
|
||||
FROM ogp_billing_orders o
|
||||
LEFT JOIN ogp_billing_services bs ON o.service_id = bs.service_id
|
||||
WHERE o.user_id = $user_id
|
||||
ORDER BY o.order_id DESC";
|
||||
$servers_result = mysqli_query($db, $servers_query);
|
||||
|
||||
// Debug: Log query execution and errors
|
||||
if (!$servers_result) {
|
||||
error_log("My Account Error - User ID: $user_id, Query failed: " . mysqli_error($db));
|
||||
} else {
|
||||
error_log("My Account Debug - User ID: $user_id, Servers Found: " . mysqli_num_rows($servers_result));
|
||||
}
|
||||
|
||||
// Fetch invoices (from data directory JSON files)
|
||||
$dataDir = (isset($SITE_DATA_DIR) && $SITE_DATA_DIR) ? $SITE_DATA_DIR : realpath(__DIR__ . '/') . DIRECTORY_SEPARATOR . 'data';
|
||||
$invoices = [];
|
||||
|
|
@ -310,8 +161,29 @@ if (is_dir($dataDir)) {
|
|||
}
|
||||
}
|
||||
|
||||
// Sort invoices by date (newest first)
|
||||
// Sort invoices by invoice/order id (newest order id first) when available,
|
||||
// otherwise fall back to timestamp (newest first).
|
||||
usort($invoices, function($a, $b) {
|
||||
$getOrderId = function($inv) {
|
||||
if (!empty($inv['invoice']) && is_numeric($inv['invoice'])) return intval($inv['invoice']);
|
||||
if (!empty($inv['custom']) && is_numeric($inv['custom'])) return intval($inv['custom']);
|
||||
return null;
|
||||
};
|
||||
|
||||
$aId = $getOrderId($a);
|
||||
$bId = $getOrderId($b);
|
||||
|
||||
if ($aId !== null || $bId !== null) {
|
||||
// If either has a numeric order id, prefer numeric comparison (desc)
|
||||
if ($aId === $bId) {
|
||||
return strtotime($b['ts'] ?? 0) - strtotime($a['ts'] ?? 0);
|
||||
}
|
||||
if ($aId === null) return 1; // b has id -> b before a
|
||||
if ($bId === null) return -1; // a has id -> a before b
|
||||
return $bId - $aId; // numeric desc
|
||||
}
|
||||
|
||||
// Fallback: newest timestamp first
|
||||
return strtotime($b['ts'] ?? 0) - strtotime($a['ts'] ?? 0);
|
||||
});
|
||||
|
||||
|
|
@ -325,7 +197,15 @@ $previous_invoices = array_filter($invoices, function($inv) {
|
|||
|
||||
?>
|
||||
|
||||
<div class="account-container">
|
||||
<!-- Debug marker: Page rendering started -->
|
||||
<div class="site-panel">
|
||||
<div class="site-panel-title">
|
||||
My Account
|
||||
<a href="logout.php" class="gsw-btn" style="float:right;">Logout</a>
|
||||
</div>
|
||||
|
||||
<!-- Debug: User ID = <?php echo $user_id; ?>, User Info: <?php echo $user_info ? 'Loaded' : 'NULL'; ?> -->
|
||||
|
||||
<?php if (!empty($error_message)): ?>
|
||||
<div class="alert alert-error"><?php echo htmlspecialchars($error_message); ?></div>
|
||||
<?php endif; ?>
|
||||
|
|
@ -359,8 +239,8 @@ $previous_invoices = array_filter($invoices, function($inv) {
|
|||
|
||||
<!-- Edit Account Information Form -->
|
||||
<details>
|
||||
<summary style="cursor: pointer; color: #667eea; font-weight: 600; margin-top: 10px;">Edit Account Information</summary>
|
||||
<form method="POST" style="margin-top: 15px;">
|
||||
<summary class="account-edit-summary">Edit Account Information</summary>
|
||||
<form method="POST" class="mt-12">
|
||||
<div class="form-group">
|
||||
<label for="fname">First Name</label>
|
||||
<input type="text" id="fname" name="fname" value="<?php echo htmlspecialchars($user_info['users_fname'] ?? ''); ?>">
|
||||
|
|
@ -404,6 +284,7 @@ $previous_invoices = array_filter($invoices, function($inv) {
|
|||
<!-- My Game Servers Section -->
|
||||
<div class="account-section">
|
||||
<h2>My Game Servers</h2>
|
||||
|
||||
<?php if ($servers_result && mysqli_num_rows($servers_result) > 0): ?>
|
||||
<?php while ($server = mysqli_fetch_assoc($servers_result)): ?>
|
||||
<div class="server-item">
|
||||
|
|
@ -414,8 +295,8 @@ $previous_invoices = array_filter($invoices, function($inv) {
|
|||
<span class="server-detail-value"><?php echo htmlspecialchars($server['service_name'] ?? 'N/A'); ?></span>
|
||||
</div>
|
||||
<div class="server-detail">
|
||||
<span class="server-detail-label">Location:</span>
|
||||
<span class="server-detail-value"><?php echo htmlspecialchars($server['remote_server_name'] ?? 'N/A'); ?></span>
|
||||
<span class="server-detail-label">Location / Home ID:</span>
|
||||
<span class="server-detail-value"><?php echo htmlspecialchars($server['remote_server_name'] ?? $server['home_id'] ?? 'N/A'); ?></span>
|
||||
</div>
|
||||
<div class="server-detail">
|
||||
<span class="server-detail-label">Status:</span>
|
||||
|
|
@ -426,16 +307,28 @@ $previous_invoices = array_filter($invoices, function($inv) {
|
|||
<span class="server-detail-value">$<?php echo number_format($server['price'] ?? 0, 2); ?>/<?php echo htmlspecialchars($server['invoice_duration'] ?? 'month'); ?></span>
|
||||
</div>
|
||||
<div class="server-detail">
|
||||
<span class="server-detail-label">Created:</span>
|
||||
<span class="server-detail-value"><?php echo $server['created_at'] ? date('M d, Y', strtotime($server['created_at'])) : 'N/A'; ?></span>
|
||||
<span class="server-detail-label">Order ID:</span>
|
||||
<span class="server-detail-value">#<?php echo htmlspecialchars($server['order_id'] ?? 'N/A'); ?></span>
|
||||
</div>
|
||||
<div class="server-detail">
|
||||
<span class="server-detail-label">Expires:</span>
|
||||
<span class="server-detail-value"><?php echo !empty($server['finish_date']) && $server['finish_date'] != '0' ? date('M d, Y', strtotime($server['finish_date'])) : 'N/A'; ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="server-actions">
|
||||
<?php
|
||||
// Show Renew action for servers that can be renewed
|
||||
$renewable_statuses = array('paid','installed','invoiced','suspended');
|
||||
if (!empty($server['status']) && in_array(strtolower($server['status']), $renewable_statuses)): ?>
|
||||
<a href="renew_server.php?order_id=<?php echo intval($server['order_id']); ?>" class="gsw-btn renew-btn">Renew</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endwhile; ?>
|
||||
<?php else: ?>
|
||||
<div class="no-data">
|
||||
<p>You don't have any game servers yet.</p>
|
||||
<a href="serverlist.php" class="btn-primary" style="display: inline-block; margin-top: 10px;">Browse Game Servers</a>
|
||||
<a href="serverlist.php" class="gsw-btn mt-10">Browse Game Servers</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,15 +39,9 @@ $query = "SELECT
|
|||
gc.game_name,
|
||||
o.order_id,
|
||||
o.status,
|
||||
o.created_at,
|
||||
o.invoice_duration,
|
||||
DATE_ADD(o.created_at, INTERVAL
|
||||
CASE
|
||||
WHEN o.invoice_duration = 'month' THEN 30
|
||||
WHEN o.invoice_duration = 'year' THEN 365
|
||||
ELSE 30
|
||||
END DAY
|
||||
) as expiration_date,
|
||||
-- use finish_date as the expiration marker (set when order is paid/created)
|
||||
o.finish_date AS expiration_date,
|
||||
bs.service_name,
|
||||
bs.price_monthly
|
||||
FROM ogp_home h
|
||||
|
|
@ -100,7 +94,7 @@ $result = mysqli_query($db, $query);
|
|||
<td><?php echo $server['price_monthly'] ? '$' . number_format($server['price_monthly'], 2) : 'N/A'; ?></td>
|
||||
<td>
|
||||
<?php if ($server['order_id']): ?>
|
||||
<a href="renew_server.php?order_id=<?php echo urlencode($server['order_id']); ?>" class="btn-primary" style="padding:8px 16px;text-decoration:none;display:inline-block;border-radius:6px;">Renew</a>
|
||||
<a href="renew_server.php?order_id=<?php echo urlencode($server['order_id']); ?>" class="gsw-btn">Renew</a>
|
||||
<?php else: ?>
|
||||
<span class="muted">N/A</span>
|
||||
<?php endif; ?>
|
||||
|
|
@ -110,9 +104,9 @@ $result = mysqli_query($db, $query);
|
|||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="panel" style="text-align:center;padding:40px;">
|
||||
<div class="panel no-data">
|
||||
<p style="font-size:1.2rem;margin-bottom:20px;">You don't have any game servers yet.</p>
|
||||
<a href="serverlist.php" class="btn-primary" style="padding:12px 24px;text-decoration:none;display:inline-block;border-radius:8px;">Browse Game Servers</a>
|
||||
<a href="serverlist.php" class="gsw-btn">Browse Game Servers</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
|
@ -122,17 +116,6 @@ $result = mysqli_query($db, $query);
|
|||
mysqli_close($db);
|
||||
?>
|
||||
|
||||
<style>
|
||||
.text-success {
|
||||
color: #10b981;
|
||||
font-weight: 600;
|
||||
}
|
||||
.text-danger {
|
||||
color: #ef4444;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
</body>
|
||||
<?php include(__DIR__ . '/includes/footer.php'); ?>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -287,8 +287,8 @@ if ($row['price_monthly'] == 0.0) {
|
|||
?>
|
||||
<?php if ($available_server && $is_logged_in): ?>
|
||||
<button type="submit" name="add_to_cart" class="gsw-btn">Add to Cart</button>
|
||||
<?php elseif ($available_server && !$is_logged_in): ?>
|
||||
<div style="padding:12px;background:rgba(255,255,255,0.03);border-radius:8px;color:#fff;">Please <a href="login.php" style="color:#cfe6ff;text-decoration:underline;">login</a> to order</div>
|
||||
<?php else: ?>
|
||||
<div class="login-placeholder">Please <a href="login.php">login</a> to order</div>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,138 @@
|
|||
<?php
|
||||
// Silent renew endpoint: mark an existing order as 'renew' and redirect back.
|
||||
// This endpoint produces no visible output — it always redirects back to the referrer.
|
||||
|
||||
// Require login and configuration
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_name("gameservers_website");
|
||||
session_start();
|
||||
}
|
||||
require_once(__DIR__ . '/includes/config.inc.php');
|
||||
require_once(__DIR__ . '/includes/login_required.php');
|
||||
require_once(__DIR__ . '/includes/log.php');
|
||||
|
||||
// Connect to DB (use mysqli like other website modules)
|
||||
$db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name);
|
||||
if (!$db) {
|
||||
// fail silently and redirect back
|
||||
$back = $_SERVER['HTTP_REFERER'] ?? 'my_account.php';
|
||||
header('Location: ' . $back);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Resolve user id from session (same logic as other pages)
|
||||
$user_id = intval($_SESSION['website_user_id'] ?? $_SESSION['user_id'] ?? 0);
|
||||
if ($user_id <= 0 && isset($_SESSION['website_username']) && !empty($_SESSION['website_username'])) {
|
||||
$safe_uname = mysqli_real_escape_string($db, $_SESSION['website_username']);
|
||||
$qr = mysqli_query($db, "SELECT user_id FROM ogp_users WHERE users_login = '$safe_uname' LIMIT 1");
|
||||
if ($qr && mysqli_num_rows($qr) === 1) {
|
||||
$rr = mysqli_fetch_assoc($qr);
|
||||
$user_id = intval($rr['user_id'] ?? 0);
|
||||
if ($user_id > 0) {
|
||||
$_SESSION['website_user_id'] = $user_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always accept order_id from GET (link-based) or POST (form)
|
||||
$order_id = intval($_REQUEST['order_id'] ?? 0);
|
||||
// Allow optional duration override via ?duration=year
|
||||
$duration = (isset($_REQUEST['duration']) && $_REQUEST['duration'] === 'year') ? 'year' : 'month';
|
||||
|
||||
$redirect_to = 'cart.php';
|
||||
|
||||
if ($order_id <= 0 || $user_id <= 0) {
|
||||
header('Location: ' . $redirect_to);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch order and verify ownership
|
||||
$stmt = $db->prepare('SELECT order_id, user_id, service_id, qty, invoice_duration, price, home_id FROM ogp_billing_orders WHERE order_id = ? LIMIT 1');
|
||||
if (!$stmt) {
|
||||
header('Location: ' . $redirect_to);
|
||||
exit;
|
||||
}
|
||||
$stmt->bind_param('i', $order_id);
|
||||
$stmt->execute();
|
||||
$res = $stmt->get_result();
|
||||
if (!$res || $res->num_rows === 0) {
|
||||
$stmt->close();
|
||||
header('Location: ' . $redirect_to);
|
||||
exit;
|
||||
}
|
||||
$order = $res->fetch_assoc();
|
||||
$stmt->close();
|
||||
|
||||
if (intval($order['user_id']) !== intval($user_id)) {
|
||||
// Not the owner — silently redirect
|
||||
header('Location: ' . $redirect_to);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Determine price for selected duration by looking up service prices
|
||||
$service_id = intval($order['service_id'] ?? 0);
|
||||
$price_val = floatval($order['price'] ?? 0.0);
|
||||
if ($service_id > 0) {
|
||||
$sstmt = $db->prepare('SELECT price_monthly, price_year FROM ogp_billing_services WHERE service_id = ? LIMIT 1');
|
||||
if ($sstmt) {
|
||||
$sstmt->bind_param('i', $service_id);
|
||||
$sstmt->execute();
|
||||
$sres = $sstmt->get_result();
|
||||
if ($sres && $sres->num_rows > 0) {
|
||||
$srow = $sres->fetch_assoc();
|
||||
if ($duration === 'year' && !empty($srow['price_year']) && floatval($srow['price_year']) > 0) {
|
||||
$price_val = floatval($srow['price_year']);
|
||||
} else {
|
||||
$price_val = floatval($srow['price_monthly']);
|
||||
}
|
||||
}
|
||||
$sstmt->close();
|
||||
}
|
||||
}
|
||||
|
||||
// Update order: set status='renew', invoice_duration, qty, price
|
||||
$new_status = 'renew';
|
||||
$qty = 1;
|
||||
$price_formatted = number_format($price_val, 2, '.', '');
|
||||
$upd = $db->prepare('UPDATE ogp_billing_orders SET status = ?, invoice_duration = ?, qty = ?, price = ? WHERE order_id = ? AND user_id = ? LIMIT 1');
|
||||
if ($upd) {
|
||||
// types: status (s), invoice_duration (s), qty (i), price (d), order_id (i), user_id (i)
|
||||
$upd->bind_param('ssiddi', $new_status, $duration, $qty, $price_formatted, $order_id, $user_id);
|
||||
$ok = $upd->execute();
|
||||
$affected = $upd->affected_rows;
|
||||
$upd->close();
|
||||
if ($ok && $affected > 0) {
|
||||
// Insert a row into ogp_logger if table exists (best-effort)
|
||||
$client_ip = $_SERVER['REMOTE_ADDR'] ?? '';
|
||||
$msg = "USER-RENEW: User {$user_id} marked order {$order_id} as renew";
|
||||
// Try insert into ogp_logger table
|
||||
$escaped_msg = mysqli_real_escape_string($db, $msg);
|
||||
$escaped_ip = mysqli_real_escape_string($db, $client_ip);
|
||||
// Determine logger table name (best-effort). Try standard name then any table that ends with 'logger'.
|
||||
$logger_table = null;
|
||||
$check = mysqli_query($db, "SHOW TABLES LIKE 'ogp_logger'");
|
||||
if ($check && mysqli_num_rows($check) > 0) {
|
||||
$logger_table = 'ogp_logger';
|
||||
} else {
|
||||
$reslt = mysqli_query($db, "SHOW TABLES LIKE '%logger'");
|
||||
if ($reslt && mysqli_num_rows($reslt) > 0) {
|
||||
$row = mysqli_fetch_row($reslt);
|
||||
$logger_table = $row[0];
|
||||
}
|
||||
}
|
||||
if ($logger_table) {
|
||||
$dt = date('Y-m-d H:i:s');
|
||||
$ins = "INSERT INTO `" . $logger_table . "` (`date`, `user_id`, `ip`, `message`) VALUES ('{$dt}', " . intval($user_id) . ", '{$escaped_ip}', '{$escaped_msg}')";
|
||||
@mysqli_query($db, $ins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done — redirect back silently
|
||||
header('Location: ' . $redirect_to);
|
||||
exit;
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
|
@ -6,65 +141,41 @@
|
|||
<title>Renew Server - GameServers.World</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
// Require login for this page
|
||||
require_once(__DIR__ . '/includes/login_required.php');
|
||||
|
||||
// Include database configuration
|
||||
require_once(__DIR__ . '/includes/config.inc.php');
|
||||
|
||||
// Create database connection
|
||||
$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
|
||||
if (!$db) {
|
||||
die("Connection failed: " . mysqli_connect_error());
|
||||
}
|
||||
|
||||
// Include top bar and menu
|
||||
include(__DIR__ . '/includes/top.php');
|
||||
include(__DIR__ . '/includes/menu.php');
|
||||
|
||||
// Get order ID from URL
|
||||
$order_id = isset($_GET['order_id']) ? intval($_GET['order_id']) : 0;
|
||||
$user_id = intval($_SESSION['website_user_id']);
|
||||
|
||||
if ($order_id === 0) {
|
||||
echo '<div class="site-panel"><p class="text-danger">Invalid order ID.</p></div>';
|
||||
include(__DIR__ . '/includes/footer.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch order details
|
||||
$query = "SELECT o.*, bs.service_name, bs.price_monthly, bs.price_year
|
||||
FROM ogp_billing_orders o
|
||||
LEFT JOIN ogp_billing_services bs ON o.service_id = bs.service_id
|
||||
WHERE o.order_id = $order_id AND o.user_id = $user_id
|
||||
LIMIT 1";
|
||||
$result = mysqli_query($db, $query);
|
||||
|
||||
if (!$result || mysqli_num_rows($result) === 0) {
|
||||
echo '<div class="site-panel"><p class="text-danger">Order not found or you do not have permission to renew this server.</p></div>';
|
||||
mysqli_close($db);
|
||||
include(__DIR__ . '/includes/footer.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$order = mysqli_fetch_assoc($result);
|
||||
|
||||
// Process renewal
|
||||
// Process renewal: mark the existing order as a 'renew' so it appears in the cart
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_renewal'])) {
|
||||
$duration = isset($_POST['duration']) ? $_POST['duration'] : 'month';
|
||||
$price = ($duration === 'year') ? $order['price_year'] : $order['price_monthly'];
|
||||
|
||||
// Create a new order for renewal
|
||||
// In a real system, this would redirect to payment gateway
|
||||
// For now, we'll just show a message
|
||||
|
||||
$message = "Renewal initiated for " . htmlspecialchars($order['service_name']) . ". ";
|
||||
$message .= "Duration: " . ($duration === 'year' ? '1 year' : '1 month') . ". ";
|
||||
$message .= "Total: $" . number_format($price, 2) . ". ";
|
||||
$message .= "In a production system, you would be redirected to payment processing.";
|
||||
|
||||
echo '<div class="site-panel"><div class="alert alert-success">' . $message . '</div></div>';
|
||||
$invoice_duration = ($duration === 'year') ? 'year' : 'month';
|
||||
$qty = 1;
|
||||
|
||||
// Determine price based on duration (fall back to monthly if missing)
|
||||
$price = ($duration === 'year' && !empty($order['price_year']) && floatval($order['price_year']) > 0) ? floatval($order['price_year']) : floatval($order['price_monthly']);
|
||||
|
||||
// Prepare update to set this order into renew state
|
||||
if ($upd = $db->prepare("UPDATE ogp_billing_orders SET status = ?, invoice_duration = ?, qty = ?, price = ? WHERE order_id = ? AND user_id = ? LIMIT 1")) {
|
||||
$new_status = 'renew';
|
||||
$orderIdInt = intval($order_id);
|
||||
$userIdInt = intval($user_id);
|
||||
$price_val = number_format($price, 2, '.', '');
|
||||
$upd->bind_param('ssiids', $new_status, $invoice_duration, $qty, $price_val, $orderIdInt, $userIdInt);
|
||||
$ok = $upd->execute();
|
||||
$affected = $upd->affected_rows;
|
||||
$upd->close();
|
||||
if ($ok && $affected > 0) {
|
||||
// Log to panel logger that the order was marked for renewal
|
||||
if (isset($db) && method_exists($db, 'logger')) {
|
||||
$db->logger("USER-RENEW: User " . intval($userIdInt) . " marked order " . intval($orderIdInt) . " as renew");
|
||||
}
|
||||
// Successfully transitioned to renew — go to cart
|
||||
header('Location: cart.php');
|
||||
exit;
|
||||
} else {
|
||||
$err = mysqli_error($db);
|
||||
echo '<div class="site-panel"><div class="alert alert-danger">Failed to mark order for renewal: ' . htmlspecialchars($err) . '</div></div>';
|
||||
}
|
||||
} else {
|
||||
$err = mysqli_error($db);
|
||||
echo '<div class="site-panel"><div class="alert alert-danger">Failed to prepare renewal update: ' . htmlspecialchars($err) . '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -73,27 +184,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_renewal'])) {
|
|||
<div class="site-panel-title">Renew Server</div>
|
||||
|
||||
<div class="panel" style="max-width:600px;margin:20px auto;">
|
||||
<h3 style="margin-bottom:20px;"><?php echo htmlspecialchars($order['service_name']); ?></h3>
|
||||
<h3><?php echo htmlspecialchars($order['service_name']); ?></h3>
|
||||
|
||||
<form method="POST" action="">
|
||||
<div class="form-group" style="margin-bottom:20px;">
|
||||
<label style="display:block;margin-bottom:10px;">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="radio" name="duration" value="month" checked>
|
||||
1 Month - $<?php echo number_format($order['price_monthly'], 2); ?>
|
||||
</label>
|
||||
<?php if ($order['price_year'] > 0): ?>
|
||||
<label style="display:block;">
|
||||
<label>
|
||||
<input type="radio" name="duration" value="year">
|
||||
1 Year - $<?php echo number_format($order['price_year'], 2); ?>
|
||||
</label>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<button type="submit" name="confirm_renewal" class="btn-primary" style="padding:12px 24px;border-radius:8px;">
|
||||
<button type="submit" name="confirm_renewal" class="gsw-btn">
|
||||
Proceed to Payment
|
||||
</button>
|
||||
|
||||
<a href="my_servers.php" style="margin-left:20px;color:#667eea;">Cancel</a>
|
||||
<a href="my_servers.php" class="account-edit-summary" style="margin-left:20px;">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -103,27 +214,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_renewal'])) {
|
|||
mysqli_close($db);
|
||||
?>
|
||||
|
||||
<style>
|
||||
.alert-success {
|
||||
background-color: #d1fae5;
|
||||
border: 1px solid #6ee7b7;
|
||||
color: #065f46;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.form-group label {
|
||||
cursor: pointer;
|
||||
padding: 12px;
|
||||
border: 2px solid #e1e8ed;
|
||||
border-radius: 8px;
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
.form-group label:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
</body>
|
||||
<?php include(__DIR__ . '/includes/footer.php'); ?>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ $result = mysqli_query($db, $query);
|
|||
<div class="site-panel">
|
||||
<div class="site-panel-title">Server Status</div>
|
||||
|
||||
<div style="margin-bottom:20px;text-align:center;">
|
||||
<p style="color:rgba(255,255,255,0.7);">Real-time status of our game server infrastructure</p>
|
||||
<div class="text-center mb-20">
|
||||
<p class="text-muted">Real-time status of our game server infrastructure</p>
|
||||
</div>
|
||||
|
||||
<?php if ($result && mysqli_num_rows($result) > 0): ?>
|
||||
|
|
@ -143,7 +143,7 @@ $result = mysqli_query($db, $query);
|
|||
</tr>
|
||||
<?php if (!empty($server['notes'])): ?>
|
||||
<tr>
|
||||
<td colspan="8" style="padding-left:40px;font-size:0.9rem;color:rgba(255,255,255,0.7);">
|
||||
<td colspan="8" class="server-notes">
|
||||
<em><?php echo htmlspecialchars($server['notes']); ?></em>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -152,12 +152,12 @@ $result = mysqli_query($db, $query);
|
|||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="panel" style="text-align:center;padding:40px;">
|
||||
<div class="panel no-data">
|
||||
<p style="font-size:1.2rem;">No server status information available.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="margin-top:30px;text-align:center;color:rgba(255,255,255,0.6);font-size:0.9rem;">
|
||||
<div class="text-center text-muted" style="margin-top:30px;font-size:0.9rem;">
|
||||
<p>Server status is updated automatically every 5 minutes.</p>
|
||||
<p style="margin-top:10px;">If you experience any issues, please contact support.</p>
|
||||
</div>
|
||||
|
|
@ -168,37 +168,6 @@ $result = mysqli_query($db, $query);
|
|||
mysqli_close($db);
|
||||
?>
|
||||
|
||||
<style>
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.status-online {
|
||||
background-color: #10b981;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-offline {
|
||||
background-color: #ef4444;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-maintenance {
|
||||
background-color: #f59e0b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-unknown {
|
||||
background-color: #6b7280;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
</body>
|
||||
<?php include(__DIR__ . '/includes/footer.php'); ?>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ include(__DIR__ . '/includes/menu.php');
|
|||
?>
|
||||
<button type="submit" class="gsw-btn">Add to Cart</button>
|
||||
<?php else: ?>
|
||||
<div style="padding:12px;background:rgba(255,255,255,0.03);border-radius:8px;color:#fff;">Please <a href="login.php" style="color:#cfe6ff;text-decoration:underline;">login</a> to order</div>
|
||||
<div class="login-placeholder">Please <a href="login.php">login</a> to order</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue