getSettings();
if( isset($panel_settings['time_zone']) && $panel_settings['time_zone'] != "" )
date_default_timezone_set($panel_settings['time_zone']);
// Date calculations
$today = time();
$invoice_date = strtotime('+ 7 days'); // Create invoice 7 days before expiration
$suspend_date = $today; // Suspend immediately when overdue
$removal_date = strtotime('- 7 days'); // Remove 7 days after suspension
$rundate = date('Y-m-d H:i:s', is_numeric($today) ? (int)$today : strtotime($today));
$db->logger("BILLING-CRON: Server lifecycle automation running at " . $rundate);
// ==================================================================================
// STEP 1: CREATE RENEWAL INVOICES FOR SERVERS EXPIRING IN 7 DAYS
// ==================================================================================
// Find all ACTIVE servers (installed) that expire within 7 days and don't have an unpaid invoice
$upcoming_expirations = $db->resultQuery("
SELECT o.*, u.users_email, u.users_fname, u.users_lname
FROM " . $table_prefix . "billing_orders o
LEFT JOIN " . $table_prefix . "users u ON o.user_id = u.user_id
WHERE o.status = 'installed'
AND o.end_date IS NOT NULL
AND UNIX_TIMESTAMP(o.end_date) < {$invoice_date}
AND UNIX_TIMESTAMP(o.end_date) > {$today}
AND NOT EXISTS (
SELECT 1 FROM " . $table_prefix . "billing_invoices i
WHERE i.order_id = o.order_id AND i.status = 'unpaid'
)
");
if (is_array($upcoming_expirations)) {
foreach ((array)$upcoming_expirations as $order) {
$user_id = $order['user_id'];
$order_id = $order['order_id'];
$home_id = $order['home_id'];
$customer_name = trim(($order['users_fname'] ?? '') . ' ' . ($order['users_lname'] ?? ''));
$customer_email = $order['users_email'] ?? '';
// Create renewal invoice
$invoice_desc = "Renewal for " . $order['home_name'];
$due_date = date('Y-m-d H:i:s', strtotime($order['end_date']));
$db->query("INSERT INTO " . $table_prefix . "billing_invoices
(order_id, user_id, customer_name, customer_email, amount, currency, status,
invoice_date, due_date, description, invoice_duration, qty)
VALUES (
{$order_id},
{$user_id},
'" . $db->realEscapeSingle($customer_name) . "',
'" . $db->realEscapeSingle($customer_email) . "',
" . floatval($order['price']) . ",
'USD',
'unpaid',
NOW(),
'" . $db->realEscapeSingle($due_date) . "',
'" . $db->realEscapeSingle($invoice_desc) . "',
'" . $db->realEscapeSingle($order['invoice_duration']) . "',
" . intval($order['qty']) . "
)");
// Mark order status as 'renew' to indicate renewal invoice was created
$db->query("UPDATE " . $table_prefix . "billing_orders
SET status='renew'
WHERE order_id={$order_id}");
// Send renewal notice email
$settings = $db->getSettings();
$subject = "Renewal Invoice for " . $order['home_name'] . " - " . $panel_settings['panel_name'];
$message = "Your server '" . $order['home_name'] . "' (ID: {$home_id}) will expire on " .
date('F j, Y', strtotime($order['end_date'])) .
".
A renewal invoice has been created. Please log in to your account and pay the invoice to continue your service." .
"
Amount Due: $" . number_format($order['price'], 2) .
"
Due Date: " . date('F j, Y', strtotime($order['end_date'])) .
"
Thank you for your business!
";
$mail = mymail($customer_email, $subject, $message, $settings);
$db->logger("BILLING-CRON: Created renewal invoice for order {$order_id}, home {$home_id}");
if (!$mail) {
$db->logger("BILLING-CRON: Email FAILED - Renewal invoice for order {$order_id}");
}
}
}
// ==================================================================================
// STEP 2: SUSPEND SERVERS THAT ARE EXPIRED AND HAVE UNPAID INVOICES
// ==================================================================================
// Find servers that:
// - Are currently installed or renew (active)
// - Have passed their end_date
// - Have at least one unpaid invoice
$servers_to_suspend = $db->resultQuery("
SELECT DISTINCT o.*, u.users_email
FROM " . $table_prefix . "billing_orders o
LEFT JOIN " . $table_prefix . "users u ON o.user_id = u.user_id
INNER JOIN " . $table_prefix . "billing_invoices i ON o.order_id = i.order_id
WHERE o.status IN ('installed', 'renew')
AND o.end_date IS NOT NULL
AND UNIX_TIMESTAMP(o.end_date) < {$suspend_date}
AND i.status = 'unpaid'
");
if (is_array($servers_to_suspend)) {
foreach ((array)$servers_to_suspend as $order) {
$user_id = $order['user_id'];
$home_id = $order['home_id'];
$order_id = $order['order_id'];
// Get home and server info
$home_info = $db->getGameHomeWithoutMods($home_id);
if (!$home_info) {
$db->logger("BILLING-CRON: WARNING - Home {$home_id} not found for order {$order_id}, marking suspended anyway");
$db->query("UPDATE " . $table_prefix . "billing_orders SET status='suspended' WHERE order_id={$order_id}");
continue;
}
$server_info = $db->getRemoteServerById($home_info['remote_server_id']);
$remote = new OGPRemoteLibrary($server_info['agent_ip'], $server_info['agent_port'],
$server_info['encryption_key'], $server_info['timeout']);
// Disable FTP
$ftp_login = isset($home_info['ftp_login']) ? $home_info['ftp_login'] : $home_id;
$remote->ftp_mgr("userdel", $ftp_login);
$db->changeFtpStatus('disabled', $home_id);
// Stop the server
$server_xml = read_server_config(SERVER_CONFIG_LOCATION . "/" . $home_info['home_cfg_file']);
$control_type = isset($server_xml->control_protocol_type) ? $server_xml->control_protocol_type : "";
$addresses = $db->getHomeIpPorts($home_id);
foreach ((array)$addresses as $address) {
$remote->remote_stop_server($home_id, $address['ip'], $address['port'],
$server_xml->control_protocol, $home_info['control_password'],
$control_type, $home_info['home_path']);
}
// Unassign from user
$db->unassignHomeFrom("user", $user_id, $home_id);
// Update order status
$db->query("UPDATE " . $table_prefix . "billing_orders SET status='suspended' WHERE order_id={$order_id}");
$db->logger("BILLING-CRON: SUSPENDED server {$home_id} for order {$order_id} due to unpaid invoice");
// Send suspension email
$settings = $db->getSettings();
$subject = "Server Suspended - " . $order['home_name'] . " - " . $panel_settings['panel_name'];
$message = "Your server '" . $order['home_name'] . "' (ID: {$home_id}) has been suspended due to non-payment." .
"
Your server has been stopped and will be permanently deleted in 7 days if payment is not received." .
"
Please log in to your account and pay your outstanding invoice to restore your server." .
"
Thank you.";
$mail = mymail($order['users_email'], $subject, $message, $settings);
if (!$mail) {
$db->logger("BILLING-CRON: Email FAILED - Suspension notice for order {$order_id}");
}
}
}
// ==================================================================================
// STEP 3: DELETE SERVERS THAT HAVE BEEN SUSPENDED FOR 7+ DAYS
// ==================================================================================
// Find servers that:
// - Are currently suspended
// - Have been suspended for at least 7 days (end_date + 7 days has passed)
// - Still have unpaid invoices
$servers_to_delete = $db->resultQuery("
SELECT DISTINCT o.*, u.users_email
FROM " . $table_prefix . "billing_orders o
LEFT JOIN " . $table_prefix . "users u ON o.user_id = u.user_id
INNER JOIN " . $table_prefix . "billing_invoices i ON o.order_id = i.order_id
WHERE o.status = 'suspended'
AND o.end_date IS NOT NULL
AND UNIX_TIMESTAMP(o.end_date) < {$removal_date}
AND i.status = 'unpaid'
");
if (is_array($servers_to_delete)) {
foreach ((array)$servers_to_delete as $order) {
$user_id = $order['user_id'];
$home_id = $order['home_id'];
$order_id = $order['order_id'];
// Get home and server info
$home_info = $db->getGameHomeWithoutMods($home_id);
if ($home_info) {
$server_info = $db->getRemoteServerById($home_info['remote_server_id']);
$remote = new OGPRemoteLibrary($server_info['agent_ip'], $server_info['agent_port'],
$server_info['encryption_key'], $server_info['timeout']);
// Remove the game home from db
$db->deleteGameHome($home_id);
// Remove the game home files from remote server
$remote->remove_home($home_info['home_path']);
// Drop database and user if they exist (both user_#### and server_#### formats)
@$db->query("DROP USER 'user_" . $home_id . "'@'%'");
@$db->query("DROP USER 'user_" . $home_id . "'@'localhost'");
@$db->query("DROP USER 'server_" . $home_id . "'@'%'");
@$db->query("DROP USER 'server_" . $home_id . "'@'localhost'");
@$db->query("DROP DATABASE IF EXISTS user_" . $home_id);
@$db->query("DROP DATABASE IF EXISTS server_" . $home_id);
}
// Update order status and clear home_id
$db->query("UPDATE " . $table_prefix . "billing_orders
SET status='deleted', home_id='0'
WHERE order_id={$order_id}");
// Mark all unpaid invoices for this order as deleted
$db->query("UPDATE " . $table_prefix . "billing_invoices
SET status='deleted'
WHERE order_id={$order_id} AND status='unpaid'");
$db->logger("BILLING-CRON: DELETED server {$home_id} for order {$order_id} after 7 days suspended");
// Send deletion email
$settings = $db->getSettings();
$subject = "Server Permanently Deleted - " . $order['home_name'] . " - " . $panel_settings['panel_name'];
$message = "Your server '" . $order['home_name'] . "' (ID: {$home_id}) has been permanently deleted." .
"
The server was suspended 7 days ago due to non-payment and has now been removed." .
"
If this was an error and you contact us immediately, we may be able to restore your server from backups." .
"
Thank you for being a customer. We hope to serve you again in the future.";
$mail = mymail($order['users_email'], $subject, $message, $settings);
if (!$mail) {
$db->logger("BILLING-CRON: Email FAILED - Deletion notice for order {$order_id}");
}
}
}
$db->logger("BILLING-CRON: Server lifecycle automation completed");
?>
//THESE SERVERS HAVE REACHED THE DATE FOR INVOICE, END_DATE - 7 (OR WHAT IS IN SETTINGS)
//SET STATUS 'invoiced' MEANING INVOICE SHOULD BE CREATED
//LOOP THROUGH ALL SERVERS WITH STATUS = 'paid' OR 'installed' (ACTIVE) -----------------------------------------------------------
$user_homes = $db->resultQuery( "SELECT *
FROM " . $table_prefix . "billing_orders
WHERE status IN ('paid', 'installed') AND end_date <" . $invoice_date);
if (!is_array($user_homes))
{
}
else
{
foreach ((array)$user_homes as $user_home)
{
// 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/end_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/end_date) as implemented
// below.
$user_id = $user_home['user_id'];
$home_id = $user_home['home_id'];
// Reset the STATUS 'invoiced' so cart.php will create an invoice
$db->query( "UPDATE " . $table_prefix . "billing_orders
SET status='invoiced'
WHERE order_id=".$db->realEscapeSingle($user_home['order_id']));
// SEND EMAIL
$settings = $db->getSettings();
$subject = "You have an INVOICE at ". $panel_settings['panel_name'];
$email = $db->resultQuery(" SELECT DISTINCT users_email
FROM " . $table_prefix . "users, " . $table_prefix . "billing_orders
WHERE " . $table_prefix . "users.user_id = $user_id")[0]["users_email"];
$message = "Your server with ID ". $home_id . " will expire soon. Please log in and VIEW INVOICES on the Dashboard to renew your server.
~
Thanks!
";
$mail = mymail($email, $subject, $message, $settings);
//logger
$db->logger( "AUTO-CLEAN: INVOICE created for server " . $home_id);
if (!$mail)
$db->logger( "AUTO-CLEAN: Email FAILED - Server Invoiced " . $home_id);
// END EMAIL
}
}
//THESE ARE THE SERVERS THAT HAVE NOT BEEN PAID AND THE END_DATE IS TODAY
//THESE SERVERS GET SUSPENDED
//LOOP THROUGH ALL ORDERS WITH STATUS 'invoiced' OR 'in-cart' OR 'unknown' (INACTIVE OR INVOICED)
$user_homes = $db->resultQuery( "SELECT *
FROM " . $table_prefix . "billing_orders
WHERE status IN ('invoiced', 'in-cart', 'unknown') AND end_date < ".$today);
if (!is_array($user_homes))
{
}
else
{
foreach ((array)$user_homes as $user_home)
{
$user_id = $user_home['user_id'];
$home_id = $user_home['home_id'];
$home_info = $db->getGameHomeWithoutMods($home_id);
$server_info = $db->getRemoteServerById($home_info['remote_server_id']);
$remote = new OGPRemoteLibrary($server_info['agent_ip'], $server_info['agent_port'], $server_info['encryption_key'],$server_info['timeout']);
$ftp_login = isset($home_info['ftp_login']) ? $home_info['ftp_login'] : $home_id;
$remote->ftp_mgr("userdel", $ftp_login);
$db->changeFtpStatus('disabled',$home_id);
$server_xml = read_server_config(SERVER_CONFIG_LOCATION."/".$home_info['home_cfg_file']);
if(isset($server_xml->control_protocol_type))$control_type = $server_xml->control_protocol_type; else $control_type = "";
$addresses = $db->getHomeIpPorts($home_id);
foreach ((array)$addresses as $address)
{
$remote->remote_stop_server($home_id,$address['ip'],$address['port'],$server_xml->control_protocol,$home_info['control_password'],$control_type,$home_info['home_path']);
}
$db->unassignHomeFrom("user", $user_id, $home_id);
// Reset the invoice end date to 'suspended'
// User can still RENEW server
$db->query( "UPDATE " . $table_prefix . "billing_orders
SET status='suspended'
WHERE order_id=".$db->realEscapeSingle($user_home['order_id']));
//logger
$db->logger( "AUTO-CLEAN: SUSPENDED server " . $home_id);
// SEND EMAIL
$settings = $db->getSettings();
$subject = "GameServer Suspended at ". $panel_settings['panel_name'];
$email = $db->resultQuery(" SELECT DISTINCT users_email
FROM " . $table_prefix . "users, " . $table_prefix . "billing_orders
WHERE " . $table_prefix . "users.user_id = $user_id")[0]["users_email"];
$message = "Your server with ID ". $home_id . " has expired and has been suspended. Please log in and VIEW INVOICES on the Dashboard to renew your server.
~
Thanks!
";
$mail = mymail($email, $subject, $message, $settings);
if (!$mail)
$db->logger( "AUTO-CLEAN: Email FAILED - Server Suspended " . $home_id);
// END EMAIL
}
}
// end date = 'suspended' (suspended) and its been suspended for $removal_date days
//set removed servers as 'deleted'
$user_homes = $db->resultQuery( "SELECT *
FROM " . $table_prefix . "billing_orders
WHERE status = 'suspended' AND end_date < ".$removal_date );
if (!is_array($user_homes))
{
}
else
{
foreach ((array)$user_homes as $user_home)
{
$user_id = $user_home['user_id'];
$home_id = $user_home['home_id'];
$home_info = $db->getGameHomeWithoutMods($home_id);
$server_info = $db->getRemoteServerById($home_info['remote_server_id']);
$remote = new OGPRemoteLibrary($server_info['agent_ip'], $server_info['agent_port'], $server_info['encryption_key'],$server_info['timeout']);
// Remove the game home from db
$db->deleteGameHome($home_id);
// Remove the game home files from remote server
$remote->remove_home($home_info['home_path']);
// Reset the invoice end date
$db->query( "UPDATE " . $table_prefix . "billing_orders
SET status='deleted'
WHERE order_id=".$db->realEscapeSingle($user_home['order_id']));
// Set order as not installed
$db->query( "UPDATE " . $table_prefix . "billing_orders
SET home_id=0
WHERE order_id=".$db->realEscapeSingle($user_home['order_id']));
// Mark all unpaid invoices for this order as deleted
$db->query("UPDATE " . $table_prefix . "billing_invoices
SET status='deleted'
WHERE order_id=".$db->realEscapeSingle($user_home['order_id'])." AND status='unpaid'");
// remove userid and table from database (both user_#### and server_#### formats)
@$db->query( "DROP USER 'user_" .$home_id ."'@'%'");
@$db->query( "DROP USER 'user_" .$home_id ."'@'localhost'");
@$db->query( "DROP USER 'server_" .$home_id ."'@'%'");
@$db->query( "DROP USER 'server_" .$home_id ."'@'localhost'");
@$db->query( "DROP DATABASE IF EXISTS user_" .$home_id);
@$db->query( "DROP DATABASE IF EXISTS server_" .$home_id);
//logger
$db->logger( "AUTO-CLEAN: DELETED server " . $home_id);
// SEND EMAIL
$settings = $db->getSettings();
$settings = $db->getSettings();
$subject = "GameServer DELETED at ". $panel_settings['panel_name'];
$email = $db->resultQuery(" SELECT DISTINCT users_email
FROM " . $table_prefix . "users, " . $table_prefix . "billing_orders
WHERE " . $table_prefix . "users.user_id = $user_id")[0]["users_email"];
$message = "Your server with ID ". $home_id . " has been deleted
You did not renew the service and it was PERMANENTLY REMOVED today. If this was an error, if you contact us immediately we may be able to restore your server.
Thanks for being a customer and we hope we can provide a server for you again.
";
$mail = mymail($email, $subject, $message, $settings);
if (!$mail)
$db->logger( "AUTO-CLEAN: Email FAILED - Server Deleted " . $home_id);
// END EMAIL
}
}
?>