Add new license renewal workflow and enhanced templates

Features:

Added new license renewal workflow to track historical orders and update associated_orders column for licenses.
Introduced improved handling for WooCommerce order IDs during license renewal.
Added new templates for license management, including renewal pages and license product display suggestions for empty carts.
Improvements:

Enhanced wc_slm_create_new_license to manage expiration dates, logging, and associated orders seamlessly.
Refactored license renewal logic to ensure existing orders are appended to the associated_orders column.
Improved database schema management for adding missing columns like associated_orders, ensuring backward compatibility and smoother upgrades.
Introduced structured retrieval of associated orders with the SLM_Utility::slm_get_associated_orders function to return well-formatted data.
Fixes:

Addressed metadata dependency by replacing _slm_lic_key usage with database lookups for better accuracy and reliability.
Fixed database version handling logic to ensure schema updates are properly applied during version upgrades.
Templates:

Added license cart template with suggested license products display for empty cart scenarios.
Included robust template structure to handle renewal messages and new license purchases dynamically.
Notes:

The new renewal workflow improves traceability by appending historical orders to the license's associated_orders.
Templates are designed to integrate seamlessly with WooCommerce workflows, providing a consistent user experience.
This commit is contained in:
Michel 2024-11-25 15:03:33 -05:00
parent 1ab8114235
commit 3d6a5b3d10
20 changed files with 2084 additions and 1281 deletions

View file

@ -177,6 +177,7 @@ function slm_admin_tools_menu()
</div> </div>
</div> </div>

<div class="postbox"> <div class="postbox">
<h3 class="hndle"><label for="title"><?php esc_html_e('Backup Database', 'slm-plus'); ?></label></h3> <h3 class="hndle"><label for="title"><?php esc_html_e('Backup Database', 'slm-plus'); ?></label></h3>
<div class="inside"> <div class="inside">

View file

@ -267,18 +267,21 @@ function slm_general_settings()
<?php esc_html_e('Enable WooCommerce downloads expiration. Downloads will expire together with corresponding license.', 'slm-plus'); ?> <?php esc_html_e('Enable WooCommerce downloads expiration. Downloads will expire together with corresponding license.', 'slm-plus'); ?>
</td> </td>
</tr> </tr>
</table>


<!-- <h3><?php // esc_html_e('WP eStores', 'slm-plus'); ?> </h3> <tr>
<table class="form-table"> <th scope="row"><?php esc_html_e('License Cart Page', 'slm-plus'); ?></th>
<tr valign="top">
<th scope="row"> <?php //_e('WP eStores', 'slm-plus'); ?></th>
<td> <td>
<input name="slm_wpestores" type="checkbox" <?php //if ($options['slm_wpestores'] != '') echo ' checked="checked"'; ?> value="1" /> <form method="post" action="">
<?php //_e('Enable WordPress eStore Plugin Support.', 'slm-plus'); ?> <?php wp_nonce_field('slm_create_license_cart', 'slm_create_license_cart_nonce'); ?>
<button type="submit" name="slm_create_license_cart" class="button button-primary">
<?php esc_html_e('Create License Cart Page', 'slm-plus'); ?>
</button>
<p class="description"><?php esc_html_e('Click this button to create the License Cart page and assign the custom template.', 'slm-plus'); ?></p>
</form>
</td> </td>
</tr> </tr>
</table> -->
</table>
</div> </div>
</div> </div>


@ -342,3 +345,79 @@ function slm_general_settings()
</div> </div>
<?php <?php
} }


add_action('admin_init', 'slm_handle_create_license_cart_page');

function slm_handle_create_license_cart_page() {
// Verify the nonce for security
if (!isset($_POST['slm_create_license_cart_nonce']) || !wp_verify_nonce($_POST['slm_create_license_cart_nonce'], 'slm_create_license_cart')) {
return;
}

// Check if the user has permissions to manage pages
if (!current_user_can('edit_pages')) {
add_settings_error(
'slm_license_cart_error',
'slm_no_permission',
__('You do not have sufficient permissions to create the License Cart page.', 'slm-plus'),
'error'
);
return;
}

// Use WP_Query to check if the page already exists
$query = new WP_Query(array(
'post_type' => 'page',
'name' => 'license-cart', // Check for the slug
'post_status' => 'publish',
'posts_per_page' => 1,
));

if ($query->have_posts()) {
add_settings_error(
'slm_license_cart_error',
'slm_license_cart_exists',
__('The License Cart page already exists.', 'slm-plus'),
'error'
);
return;
}

// Create the License Cart page
$page_id = wp_insert_post(array(
'post_title' => 'License Cart',
'post_content' => '',
'post_status' => 'publish',
'post_name' => 'license-cart', // Set the slug
'post_type' => 'page',
'meta_input' => array('_wp_page_template' => 'page-license-cart.php'), // Assign the custom template
));

// Check if the page was created successfully
if ($page_id && !is_wp_error($page_id)) {
// Hide the page from menus and navigation
update_post_meta($page_id, '_menu_item_visibility', 'hidden');
add_settings_error(
'slm_license_cart_success',
'slm_license_cart_created',
__('The License Cart page was successfully created.', 'slm-plus'),
'updated'
);
} else {
add_settings_error(
'slm_license_cart_error',
'slm_license_cart_failed',
__('Failed to create the License Cart page. Please try again.', 'slm-plus'),
'error'
);
}
}


add_action('admin_notices', 'slm_license_cart_admin_notices');

function slm_license_cart_admin_notices() {
settings_errors('slm_license_cart_error');
settings_errors('slm_license_cart_success');
}

View file

@ -19,20 +19,104 @@ $lic_log_tbl = SLM_TBL_LIC_LOG;
$lic_emails_table = SLM_TBL_EMAILS; $lic_emails_table = SLM_TBL_EMAILS;
$lic_status_table = SLM_TBL_LICENSE_STATUS; // New Status Table $lic_status_table = SLM_TBL_LICENSE_STATUS; // New Status Table


// Check the current database version
$used_db_version = get_option('slm_db_version', SLM_DB_VERSION);

// Set charset and collation for database tables // Set charset and collation for database tables
$charset_collate = $wpdb->get_charset_collate(); $charset_collate = $wpdb->get_charset_collate();


$used_db_version = get_option('slm_db_version', '5.0.0');

// Check the current database version
$new_db_version = SLM_DB_VERSION;

// Table definitions
$lic_key_table = SLM_TBL_LICENSE_KEYS;

// Ensure backward compatibility updates are applied
if (version_compare($used_db_version, $new_db_version, '<')) {
error_log("SLM: Starting database updates from version $used_db_version to $new_db_version.");

// Check if the 'associated_orders' column exists
$column_exists = $wpdb->get_results("SHOW COLUMNS FROM $lic_key_table LIKE 'associated_orders'");

if (empty($column_exists)) {
error_log("SLM: Adding missing column 'associated_orders' to $lic_key_table.");

// Add missing columns to the license keys table
$lk_tbl_sql_mod = "
ALTER TABLE $lic_key_table
ADD COLUMN associated_orders TEXT DEFAULT NULL;
";

$result = $wpdb->query($lk_tbl_sql_mod);

if ($result === false) {
error_log("SLM: Error adding 'associated_orders' column - " . $wpdb->last_error);
} else {
error_log("SLM: 'associated_orders' column added successfully.");
}
} else {
error_log("SLM: Column 'associated_orders' already exists in $lic_key_table.");
}

// Add other missing columns (if required)
$other_columns = array(
'item_reference' => "VARCHAR(255) NOT NULL",
'slm_billing_length' => "VARCHAR(255) NOT NULL",
'slm_billing_interval' => "ENUM('days', 'months', 'years', 'onetime') NOT NULL DEFAULT 'days'",
'wc_order_id' => "INT DEFAULT NULL",
'payment_status' => "ENUM('pending', 'completed', 'failed') DEFAULT 'pending'",
'renewal_attempts' => "INT DEFAULT 0",
'lic_status' => "ENUM('pending', 'active', 'expired', 'suspended', 'blocked', 'trial') NOT NULL DEFAULT 'pending'"
);

foreach ($other_columns as $column => $definition) {
$column_exists = $wpdb->get_results("SHOW COLUMNS FROM $lic_key_table LIKE '$column'");
if (empty($column_exists)) {
// Add missing column
$alter_query = "ALTER TABLE $lic_key_table ADD COLUMN $column $definition;";
error_log("SLM: Adding missing column '$column' to $lic_key_table.");
$result = $wpdb->query($alter_query);

if ($result === false) {
error_log("SLM: Error adding column '$column' - " . $wpdb->last_error);
} else {
error_log("SLM: Column '$column' added successfully.");
}
} else {
// Check if the column definition needs to be updated (for example, updating lic_status ENUM values)
$column_info = $wpdb->get_row("SHOW COLUMNS FROM $lic_key_table LIKE '$column'");
if ($column === 'lic_status' && strpos($column_info->Type, "'trial'") === false) {
// Update lic_status to include the new ENUM values
$alter_query = "ALTER TABLE $lic_key_table MODIFY COLUMN $column $definition;";
error_log("SLM: Updating column '$column' in $lic_key_table.");
$result = $wpdb->query($alter_query);

if ($result === false) {
error_log("SLM: Error updating column '$column' - " . $wpdb->last_error);
} else {
error_log("SLM: Column '$column' updated successfully.");
}
} else {
error_log("SLM: Column '$column' already exists and does not need updates.");
}
}
}

// Update the database version
update_option("slm_db_version", $new_db_version);
error_log("SLM database updated from version $used_db_version to $new_db_version.");
} else {
error_log("SLM: No updates needed for backward compatibility. Current version: $used_db_version.");
}


// Create license statuses table if it doesn't exist // Create license statuses table if it doesn't exist
$status_table_sql = "CREATE TABLE IF NOT EXISTS " . $lic_status_table . " ( $status_table_sql = "CREATE TABLE IF NOT EXISTS " . $lic_status_table . " (
id INT NOT NULL AUTO_INCREMENT, id INT(11) NOT NULL AUTO_INCREMENT,
status_key VARCHAR(255) NOT NULL, status_key VARCHAR(255) NOT NULL,
status_label VARCHAR(255) NOT NULL, status_label VARCHAR(255) NOT NULL,
PRIMARY KEY (id) PRIMARY KEY (id),
)" . $charset_collate . ";"; UNIQUE KEY unique_status_key (status_key)
dbDelta($status_table_sql); ) " . $charset_collate . ";";


// Insert default statuses if table is empty // Insert default statuses if table is empty
$status_count = $wpdb->get_var("SELECT COUNT(*) FROM $lic_status_table"); $status_count = $wpdb->get_var("SELECT COUNT(*) FROM $lic_status_table");
@ -41,6 +125,7 @@ if ($status_count == 0) {
array('status_key' => 'pending', 'status_label' => __('Pending', 'slm-plus')), array('status_key' => 'pending', 'status_label' => __('Pending', 'slm-plus')),
array('status_key' => 'active', 'status_label' => __('Active', 'slm-plus')), array('status_key' => 'active', 'status_label' => __('Active', 'slm-plus')),
array('status_key' => 'blocked', 'status_label' => __('Blocked', 'slm-plus')), array('status_key' => 'blocked', 'status_label' => __('Blocked', 'slm-plus')),
array('status_key' => 'trial', 'status_label' => __('Trial', 'slm-plus')),
array('status_key' => 'expired', 'status_label' => __('Expired', 'slm-plus')) array('status_key' => 'expired', 'status_label' => __('Expired', 'slm-plus'))
); );


@ -51,63 +136,42 @@ if ($status_count == 0) {


// Create or update the license keys table structure // Create or update the license keys table structure
$lk_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_key_table . " ( $lk_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_key_table . " (
id int(12) NOT NULL AUTO_INCREMENT, id INT(12) NOT NULL AUTO_INCREMENT,
license_key varchar(255) NOT NULL, license_key VARCHAR(255) NOT NULL,
max_allowed_domains int(40) NOT NULL, item_reference VARCHAR(255) NOT NULL,
max_allowed_devices int(40) NOT NULL, product_ref VARCHAR(255) NOT NULL DEFAULT '',
lic_status varchar(255) NOT NULL DEFAULT 'pending', /* Store status_key here */ subscr_id VARCHAR(128) NOT NULL DEFAULT '',
txn_id VARCHAR(64) NOT NULL DEFAULT '',
purchase_id_ VARCHAR(255) NOT NULL DEFAULT '',
wc_order_id INT DEFAULT NULL,
associated_orders TEXT DEFAULT NULL,
first_name VARCHAR(32) NOT NULL DEFAULT '',
last_name VARCHAR(32) NOT NULL DEFAULT '',
email VARCHAR(64) NOT NULL,
company_name VARCHAR(100) NOT NULL DEFAULT '',
lic_status ENUM('pending', 'active', 'expired', 'suspended', 'blocked', 'trial') NOT NULL DEFAULT 'pending',
lic_type ENUM('none', 'subscription', 'lifetime') NOT NULL DEFAULT 'subscription', lic_type ENUM('none', 'subscription', 'lifetime') NOT NULL DEFAULT 'subscription',
first_name varchar(32) NOT NULL DEFAULT '', max_allowed_domains INT NOT NULL,
last_name varchar(32) NOT NULL DEFAULT '', max_allowed_devices INT NOT NULL,
email varchar(64) NOT NULL, manual_reset_count VARCHAR(128) NOT NULL DEFAULT '',
item_reference varchar(255) NOT NULL, current_ver VARCHAR(255) NOT NULL DEFAULT '',
company_name varchar(100) NOT NULL DEFAULT '', until VARCHAR(255) NOT NULL DEFAULT '',
txn_id varchar(64) NOT NULL DEFAULT '', slm_billing_length VARCHAR(255) NOT NULL,
manual_reset_count varchar(128) NOT NULL DEFAULT '',
purchase_id_ varchar(255) NOT NULL DEFAULT '',
date_created date NOT NULL DEFAULT '0000-00-00',
date_activated date NOT NULL DEFAULT '0000-00-00',
date_renewed date NOT NULL DEFAULT '0000-00-00',
date_expiry date NOT NULL DEFAULT '0000-00-00',
reminder_sent varchar(255) NOT NULL DEFAULT '0',
reminder_sent_date date NOT NULL DEFAULT '0000-00-00',
product_ref varchar(255) NOT NULL DEFAULT '',
until varchar(255) NOT NULL DEFAULT '',
current_ver varchar(255) NOT NULL DEFAULT '',
subscr_id varchar(128) NOT NULL DEFAULT '',
slm_billing_length varchar(255) NOT NULL,
slm_billing_interval ENUM('days', 'months', 'years', 'onetime') NOT NULL DEFAULT 'days', slm_billing_interval ENUM('days', 'months', 'years', 'onetime') NOT NULL DEFAULT 'days',
payment_status ENUM('pending', 'completed', 'failed') DEFAULT 'pending',
renewal_attempts INT DEFAULT 0,
date_created DATE NOT NULL DEFAULT '0000-00-00',
date_activated DATE NOT NULL DEFAULT '0000-00-00',
date_renewed DATE NOT NULL DEFAULT '0000-00-00',
date_expiry DATE NOT NULL DEFAULT '0000-00-00',
reminder_sent_date DATE NOT NULL DEFAULT '0000-00-00',
reminder_sent VARCHAR(255) NOT NULL DEFAULT '0',
PRIMARY KEY (id) PRIMARY KEY (id)
)" . $charset_collate . ";"; ) " . $charset_collate . ";";



dbDelta($lk_tbl_sql); dbDelta($lk_tbl_sql);


// Handle backward compatibility for version 6.1.5 or earlier
if (version_compare($used_db_version, '5.1.1', '<=')) {
// Update $lic_key_table if necessary
$lk_tbl_sql = "
ALTER TABLE $lic_key_table
ADD COLUMN IF NOT EXISTS item_reference varchar(255) NOT NULL,
ADD COLUMN IF NOT EXISTS slm_billing_length varchar(255) NOT NULL,
ADD COLUMN IF NOT EXISTS slm_billing_interval ENUM('days', 'months', 'years', 'onetime') NOT NULL DEFAULT 'days';
";
dbDelta($lk_tbl_sql);

// Remove column 'registered_devices' from $lic_domain_table if it exists
$domain_table_sql = "
ALTER TABLE $lic_domain_table
DROP COLUMN IF EXISTS registered_devices;
";
$wpdb->query($domain_table_sql);

// Remove column 'registered_domain' from $lic_devices_table if it exists
$devices_table_sql = "
ALTER TABLE $lic_devices_table
DROP COLUMN IF EXISTS registered_domain;
";
$wpdb->query($devices_table_sql);
}

// Create domains table if not exists // Create domains table if not exists
$ld_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_domain_table . " ( $ld_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_domain_table . " (
id INT NOT NULL AUTO_INCREMENT, id INT NOT NULL AUTO_INCREMENT,
@ -201,5 +265,3 @@ if (!file_exists($backup_dir_path)) {
wp_mkdir_p($backup_dir_path); wp_mkdir_p($backup_dir_path);
} }


// Update the database version
update_option("slm_db_version", SLM_DB_VERSION);

View file

@ -35,19 +35,37 @@


class SLM_API_Listener class SLM_API_Listener
{ {
function __construct() function __construct() {
{
if (isset($_REQUEST['slm_action']) && isset($_REQUEST['secret_key'])) { if (isset($_REQUEST['slm_action']) && isset($_REQUEST['secret_key'])) {
do_action('slm_api_listener_init'); do_action('slm_api_listener_init');
$this->creation_api_listener(); $slm_action = sanitize_text_field($_REQUEST['slm_action']);
$this->activation_api_listener(); switch ($slm_action) {
$this->deactivation_api_listener(); case 'renew_license':
$this->check_api_listener(); $this->renew_api_listener();
$this->check_api_info(); break;
$this->update_api_listener(); case 'slm_create_new':
$this->creation_api_listener();
break;
case 'slm_activate':
$this->activation_api_listener();
break;
case 'slm_deactivate':
$this->deactivation_api_listener();
break;
case 'slm_update':
$this->update_api_listener();
break;
case 'slm_check':
$this->check_api_listener();
break;
case 'slm_info':
$this->check_api_info();
break;
}
} }
} }

function creation_api_listener() function creation_api_listener()
{ {
if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_create_new') { if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_create_new') {
@ -660,4 +678,182 @@ class SLM_API_Listener
} }
} }
} }

function wc_slm_handle_license_renewal($order_id, $license_key)
{
// Log the renewal action for debugging
SLM_Helper_Class::write_log("Processing license renewal for Order ID: $order_id, License Key: $license_key");

// Retrieve the license data
$license_data = SLM_Utility::get_licence_by_key($license_key);
if (!$license_data) {
SLM_Helper_Class::write_log("License key $license_key not found.");
return; // Stop if the license is not found
}

global $wpdb;
$license_table = SLM_TBL_LICENSE_KEYS;

// Calculate the new expiration date
$renewal_period = intval($license_data['slm_billing_length']);
$renewal_term = sanitize_text_field($license_data['slm_billing_interval']);
$new_expiry_date = date('Y-m-d', strtotime('+' . $renewal_period . ' ' . $renewal_term));

// Update the license expiry date in the database
$update_result = $wpdb->update(
$license_table,
['date_expiry' => $new_expiry_date, 'lic_status' => 'active'],
['license_key' => $license_key]
);

if ($update_result !== false) {
SLM_Helper_Class::write_log("License $license_key renewed successfully. New expiry date: $new_expiry_date.");
} else {
SLM_Helper_Class::write_log("Failed to renew license $license_key.");
}

// Add order note for renewal confirmation
$order = wc_get_order($order_id);
if ($order) {
$order->add_order_note(sprintf(
__('License Key %s renewed. New expiry date: %s', 'slm-plus'),
$license_key,
$new_expiry_date
));
$order->save();
}

// Optional: Notify the user about the renewal
wc_slm_notify_user_about_renewal($order, $license_key);
}


function renew_api_listener() {
if (isset($_POST['slm_action']) && trim($_POST['slm_action']) === 'renew_license') {
global $wpdb;

// Verify the secret key for security
SLM_API_Utility::verify_secret_key();

// Get and sanitize the license key and WooCommerce order ID
$license_key = sanitize_text_field($_POST['license_key']);
$wc_order_id = intval($_POST['wc_order_id']);

// Check if license key and order ID are provided
if (empty($license_key) || empty($wc_order_id)) {
SLM_API_Utility::output_api_response([
'result' => 'error',
'message' => 'License key or WooCommerce order ID is missing.',
'error_code' => SLM_Error_Codes::MISSING_PARAMETERS,
'status_code' => 400,
]);
return;
}

// Fetch the WooCommerce order
$order = wc_get_order($wc_order_id);
if (!$order) {
SLM_API_Utility::output_api_response([
'result' => 'error',
'message' => 'Invalid WooCommerce order ID.',
'error_code' => SLM_Error_Codes::ORDER_NOT_FOUND,
'status_code' => 404,
]);
return;
}

// Fetch license details from the database
$license = SLM_Utility::get_license_by_key($license_key);
if (!$license) {
SLM_API_Utility::output_api_response([
'result' => 'error',
'message' => 'License not found.',
'error_code' => SLM_Error_Codes::LICENSE_INVALID,
'status_code' => 404,
]);
return;
}

// Verify the order ID matches the one associated with the license (if applicable)
if (!empty($license->wc_order_id) && $license->wc_order_id != $wc_order_id) {
SLM_API_Utility::output_api_response([
'result' => 'error',
'message' => 'The provided order ID does not match the one associated with this license.',
'error_code' => SLM_Error_Codes::ORDER_ID_MISMATCH,
'status_code' => 400,
]);
return;
}

// Check the WooCommerce order status
if ($order->get_status() !== 'completed') {
SLM_API_Utility::output_api_response([
'result' => 'error',
'message' => 'The WooCommerce order has not been completed.',
'error_code' => SLM_Error_Codes::ORDER_NOT_COMPLETED,
'status_code' => 400,
]);
return;
}

// Handle license renewal process
$this->handle_license_renewal($wc_order_id, $license_key);

// Return a success response
SLM_API_Utility::output_api_response([
'result' => 'success',
'message' => 'License renewed successfully.',
'license_key' => $license_key,
'renewal_date' => current_time('mysql'),
'status_code' => 200,
]);
}
}

private function handle_license_renewal($order_id, $license_key) {
// Log the renewal action for debugging
SLM_Helper_Class::write_log("Processing license renewal for Order ID: $order_id, License Key: $license_key");

// Retrieve the license data
$license_data = SLM_Utility::get_license_by_key($license_key);
if (!$license_data) {
SLM_Helper_Class::write_log("License key $license_key not found.");
return; // Stop if the license is not found
}

global $wpdb;
$license_table = SLM_TBL_LICENSE_KEYS;

// Calculate the new expiration date
$renewal_period = intval($license_data->slm_billing_length);
$renewal_term = sanitize_text_field($license_data->slm_billing_interval);
$new_expiry_date = date('Y-m-d', strtotime('+' . $renewal_period . ' ' . $renewal_term));

// Update the license expiry date in the database
$update_result = $wpdb->update(
$license_table,
['date_expiry' => $new_expiry_date, 'lic_status' => 'active'],
['license_key' => $license_key]
);

if ($update_result !== false) {
SLM_Helper_Class::write_log("License $license_key renewed successfully. New expiry date: $new_expiry_date.");
} else {
SLM_Helper_Class::write_log("Failed to renew license $license_key.");
}

// Add order note for renewal confirmation
$order = wc_get_order($order_id);
if ($order) {
$order->add_order_note(sprintf(
__('License Key %s renewed. New expiry date: %s', 'slm-plus'),
$license_key,
$new_expiry_date
));
$order->save();
}

// Notify the user about the renewal
wc_slm_notify_user_about_renewal($order, $license_key);
}
} }

View file

@ -35,6 +35,10 @@ class SLM_Error_Codes {
// License key updates // License key updates
const KEY_UPDATE_FAILED = 220; // Failed to update the license key const KEY_UPDATE_FAILED = 220; // Failed to update the license key
const KEY_UPDATE_SUCCESS = 240; // License key successfully updated const KEY_UPDATE_SUCCESS = 240; // License key successfully updated
const LICENSE_RENEWED = 241; // License key successfully renewed
const LICENSE_NOT_EXPIRED = 242; // License key successfully renewed
const ORDER_NOT_FOUND = 243; // License key successfully renewed
const PRODUCT_NOT_FOUND = 244; // License key successfully renewed


// License activation and validation // License activation and validation
const LICENSE_ACTIVATED = 380; // License key successfully activated const LICENSE_ACTIVATED = 380; // License key successfully activated
@ -45,6 +49,7 @@ class SLM_Error_Codes {
const LICENSE_IN_USE = 40; // License key is currently in use const LICENSE_IN_USE = 40; // License key is currently in use
const LICENSE_INVALID = 60; // License key is invalid const LICENSE_INVALID = 60; // License key is invalid
const LICENSE_VALID = 65; // License key is valid const LICENSE_VALID = 65; // License key is valid
const INVALID_SECRET_KEY = 67; // License key is valid


// Miscellaneous errors // Miscellaneous errors
const MISSING_KEY_DELETE_FAILED = 280; // Missing license key for deletion failed const MISSING_KEY_DELETE_FAILED = 280; // Missing license key for deletion failed
@ -54,4 +59,9 @@ class SLM_Error_Codes {


// Verification errors // Verification errors
const VERIFY_KEY_INVALID = 90; // Verification secret key is invalid const VERIFY_KEY_INVALID = 90; // Verification secret key is invalid
const MISSING_PARAMETERS = 91; // Verification secret key is invalid
const INVALID_NONCE = 92; // Verification secret key is invalid
const UPDATE_FAILED = 93;
const ORDER_ID_MISMATCH = 94;
const ORDER_NOT_COMPLETED = 95;
} }

View file

@ -203,11 +203,10 @@ function wc_log($msg)
if (SLM_Helper_Class::slm_get_option('slm_woo') == 1 && is_plugin_active('woocommerce/woocommerce.php')) { if (SLM_Helper_Class::slm_get_option('slm_woo') == 1 && is_plugin_active('woocommerce/woocommerce.php')) {
require_once(SLM_WOO . 'includes/wc_licenses_class.php'); require_once(SLM_WOO . 'includes/wc_licenses_class.php');
require_once(SLM_WOO . 'includes/slm-meta-boxes.php'); require_once(SLM_WOO . 'includes/slm-meta-boxes.php');

require_once SLM_WOO . 'includes/register-template.php'; require_once SLM_WOO . 'includes/register-template.php';
require_once SLM_WOO . 'includes/purchase.php'; require_once SLM_WOO . 'includes/purchase.php';
require_once SLM_WOO . 'includes/create-license-orders.php'; require_once SLM_WOO . 'includes/create-license-orders.php';

require_once SLM_WOO . 'includes/hooks/license-checkout-hooks.php';
// Build WooCommerce tabs // Build WooCommerce tabs
SLM_Utility::slm_woo_build_tab(); SLM_Utility::slm_woo_build_tab();
} }

View file

@ -112,23 +112,24 @@ class SLM_API_Utility


public static function verify_secret_key() public static function verify_secret_key()
{ {
// Get the stored secret key from plugin options $slm_options = get_option('slm_plugin_options');
$slm_options = get_option('slm_plugin_options'); $right_secret_key = $slm_options['lic_verification_secret'] ?? '';
$right_secret_key = $slm_options['lic_verification_secret'] ?? ''; $received_secret_key = sanitize_text_field($_REQUEST['secret_key'] ?? '');

$slm_action = sanitize_text_field($_REQUEST['slm_action'] ?? '');
// Sanitize and retrieve the received secret key
$received_secret_key = sanitize_text_field($_REQUEST['secret_key'] ?? '');


// Case-sensitive comparison for the secret keys // Case-sensitive comparison for the secret keys
if ($received_secret_key !== $right_secret_key) { if ($received_secret_key !== $right_secret_key) {
// Prepare the error response with case-sensitivity note // Prepare the error response with case-sensitivity note
$args = array( $args = array(
'result' => 'error', 'result' => 'error',
'message' => 'Verification API secret key is invalid. Note: The key comparison is case-sensitive.', 'message' => 'Verification API secret key is invalid. Note: The key is case-sensitive.',
'slm_action' => $slm_action,
'received_secret_key' => $received_secret_key,
'error_code' => SLM_Error_Codes::VERIFY_KEY_INVALID 'error_code' => SLM_Error_Codes::VERIFY_KEY_INVALID
); );
// Output the API response with the error // Output the API response with the error
self::output_api_response($args); self::output_api_response($args);
SLM_Helper_Class::write_log('Verification API secret key is invalid. Note: The key is case-sensitive. ' . $slm_action);
} }
} }


@ -191,6 +192,14 @@ class SLM_Utility
/** /**
* Saves a backup of the plugin's database tables in a secure folder. * Saves a backup of the plugin's database tables in a secure folder.
*/ */
public static function renew_license($license_key, $order_id) {
global $wpdb;
$wpdb->update(SLM_TBL_LICENSE_KEYS, [
'wc_order_id' => $order_id,
'payment_status' => 'pending'
], ['license_key' => $license_key]);
}
public static function slm_save_backup_to_uploads() public static function slm_save_backup_to_uploads()
{ {
global $wpdb; global $wpdb;
@ -659,7 +668,165 @@ class SLM_Utility
} }
} }


/**
* Get license key by WooCommerce Order ID.
*
* @param int $order_id WooCommerce order ID.
* @return string|null License key associated with the order ID, or null if not found.
*/
public static function slm_get_license_by_order_id($order_id) {
global $wpdb;
$lic_key_table = SLM_TBL_LICENSE_KEYS;


// Query to fetch the license key by order ID
$query = $wpdb->prepare("SELECT license_key FROM $lic_key_table WHERE wc_order_id = %d", $order_id);
$license_key = $wpdb->get_var($query);

return $license_key ? sanitize_text_field($license_key) : null;
}



/**
* Get associated orders for a license.
*
* @param mixed $identifier The license key (string) or license ID (integer).
* @return array|null List of associated orders or null if none found.
*/
public static function slm_get_associated_orders($identifier) {
global $wpdb;
$lic_key_table = SLM_TBL_LICENSE_KEYS;
// Ensure identifier is valid
if (empty($identifier)) {
SLM_Helper_Class::write_log('Invalid identifier passed to slm_get_associated_orders: ' . print_r($identifier, true));
return [];
}
// Prepare the query based on identifier type
if (is_numeric($identifier)) {
$query = $wpdb->prepare("SELECT associated_orders FROM $lic_key_table WHERE id = %d", $identifier);
} else {
$query = $wpdb->prepare("SELECT associated_orders FROM $lic_key_table WHERE license_key = %s", $identifier);
}
// Log the query
SLM_Helper_Class::write_log('SQL Query: ' . $query);
// Execute the query
$result = $wpdb->get_var($query);
// Debug the raw result
SLM_Helper_Class::write_log('Raw associated_orders value: ' . print_r($result, true));
// Process the result if not empty
if (!empty($result)) {
$orders = maybe_unserialize($result);
SLM_Helper_Class::write_log('Unserialized associated_orders value: ' . print_r($orders, true));
if (is_array($orders)) {
return array_values(array_unique(array_map('intval', $orders)));
}
}
// Return empty array if no valid data found
return [];
}

/**
* Add an order to the associated orders of a license.
*
* @param mixed $identifier The license key (string) or license ID (integer).
* @param int $order_id The WooCommerce order ID to associate with the license.
* @return bool True if the operation was successful, false otherwise.
*/
public static function slm_add_associated_order($identifier, $order_id) {
global $wpdb;
$lic_key_table = SLM_TBL_LICENSE_KEYS;
// Validate $order_id
if (!is_numeric($order_id) || $order_id <= 0) {
error_log("SLM: Invalid order ID provided: $order_id");
return false;
}
// Fetch current license data
if (is_numeric($identifier)) {
// Identifier is a license ID
$license_data = $wpdb->get_row(
$wpdb->prepare("SELECT associated_orders, wc_order_id FROM $lic_key_table WHERE id = %d", $identifier),
ARRAY_A
);
} else {
// Identifier is a license key
$license_data = $wpdb->get_row(
$wpdb->prepare("SELECT associated_orders, wc_order_id FROM $lic_key_table WHERE license_key = %s", $identifier),
ARRAY_A
);
}
if (!$license_data) {
error_log("SLM: License not found for identifier: $identifier");
return false;
}
// Extract current associated orders and wc_order_id
$associated_orders = maybe_unserialize($license_data['associated_orders']);
$current_wc_order_id = $license_data['wc_order_id'];
// Ensure $associated_orders is a valid array
if (!is_array($associated_orders)) {
$associated_orders = [];
}
// Add the old wc_order_id to the associated_orders array if it's valid
if (!empty($current_wc_order_id) && !in_array($current_wc_order_id, $associated_orders, true)) {
$associated_orders[] = $current_wc_order_id;
}
// Add the new order_id to the associated_orders array if not already present
if (!in_array($order_id, $associated_orders, true)) {
$associated_orders[] = $order_id;
}
// Serialize the updated orders for storage
$updated_orders = maybe_serialize($associated_orders);
// Prepare the query to update the database
if (is_numeric($identifier)) {
// Update based on license ID
$query = $wpdb->prepare(
"UPDATE $lic_key_table SET associated_orders = %s, wc_order_id = %d WHERE id = %d",
$updated_orders,
$order_id,
$identifier
);
} else {
// Update based on license key
$query = $wpdb->prepare(
"UPDATE $lic_key_table SET associated_orders = %s, wc_order_id = %d WHERE license_key = %s",
$updated_orders,
$order_id,
$identifier
);
}
// Execute the query
$result = $wpdb->query($query);
// Handle and log errors
if ($result === false) {
error_log("SLM: Failed to update associated orders for identifier: $identifier. Error: " . $wpdb->last_error);
return false;
}
// Log success
error_log("SLM: Successfully updated associated orders for identifier: $identifier with Order ID: $order_id");
return true;
}





View file

@ -1 +0,0 @@
[11/14/2024 3:53 PM] - -------- Log File Reset --------

View file

@ -1,361 +1,105 @@
[11/14/2024 3:53 PM] - -------- Log File Reset -------- [11/20/2024 8:35 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-45C7-DC53-B080-2988-8305-5E46-1A87-3764).
[11/14/2024 4:25 PM] - SUCCESS : Registered domain with row id (34) deleted. [11/20/2024 8:35 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-45C7-DC53-B080-2988-8305-5E46-1A87-3764).
[11/14/2024 4:54 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/20/2024 8:35 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-45C7-DC53-B080-2988-8305-5E46-1A87-3764).
[11/14/2024 4:54 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/20/2024 8:37 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 4:55 PM] - SUCCESS : No license key found for row id (79). Deletion aborted. [11/20/2024 8:37 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 4:56 PM] - SUCCESS : API Response - Result: success Message: License key activated. [11/20/2024 9:05 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key comparison is case-sensitive.
[11/14/2024 4:56 PM] - SUCCESS : API Response - Result: success Message: License key activated for device. [11/20/2024 9:05 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key comparison is case-sensitive.
[11/14/2024 4:57 PM] - SUCCESS : Registered domain with row id (35) deleted. [11/20/2024 9:06 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key comparison is case-sensitive.
[11/14/2024 4:57 PM] - SUCCESS : 1 entries deleted from devices table for license key (SLM-EE57-76EF-2405-522E-90F4-FD95-1244-67C9). [11/20/2024 9:10 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 4:57 PM] - SUCCESS : 3 entries deleted from log table for license key (SLM-EE57-76EF-2405-522E-90F4-FD95-1244-67C9). [11/20/2024 9:11 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 4:57 PM] - SUCCESS : entries deleted from emails table for license key (SLM-EE57-76EF-2405-522E-90F4-FD95-1244-67C9). [11/20/2024 9:11 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 4:58 PM] - SUCCESS : No license key found for row id (80). Deletion aborted. [11/20/2024 9:11 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:36 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/20/2024 9:12 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:36 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/20/2024 9:14 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:36 PM] - SUCCESS : API Response - Result: success Message: License key activated for device. [11/20/2024 9:16 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:36 PM] - SUCCESS : API Response - Result: success Message: License key activated. [11/20/2024 9:16 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:37 PM] - SUCCESS : Registered domain with row id (36) deleted. [11/20/2024 9:16 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:37 PM] - SUCCESS : 1 entries deleted from devices table for license key (SLM-5778-E08F-C6C1-A077-28AE-64C3-EC83-AF8B). [11/20/2024 9:18 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:37 PM] - SUCCESS : 3 entries deleted from log table for license key (SLM-5778-E08F-C6C1-A077-28AE-64C3-EC83-AF8B). [11/20/2024 9:18 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:37 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-5778-E08F-C6C1-A077-28AE-64C3-EC83-AF8B). [11/20/2024 9:22 PM] - SUCCESS : API Response - Result: error Message: Cannot update license, license key not found or invalid action.
[11/14/2024 8:43 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/20/2024 9:25 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key is case-sensitive.
[11/14/2024 8:43 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/20/2024 9:27 PM] - SUCCESS : API Response - Result: error Message: renew_license
[11/14/2024 8:43 PM] - SUCCESS : No license key found for row id (81). Deletion aborted. [11/20/2024 9:28 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key is case-sensitive.
[11/14/2024 8:43 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-517E-526A-1BE3-B441-45C9-210E-6510-1216). [11/20/2024 9:29 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key is case-sensitive.
[11/14/2024 8:43 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-517E-526A-1BE3-B441-45C9-210E-6510-1216). [11/20/2024 9:29 PM] - SUCCESS : API Response - Result: error Message: Verification API secret key is invalid. Note: The key is case-sensitive.
[11/14/2024 8:43 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-517E-526A-1BE3-B441-45C9-210E-6510-1216). [11/20/2024 9:31 PM] - SUCCESS : API Response - Result: success Message: License renewed successfully.
[11/14/2024 8:47 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/20/2024 9:32 PM] - SUCCESS : API Response - Result: error Message: Only expired licenses can be renewed.
[11/14/2024 8:47 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/20/2024 9:32 PM] - SUCCESS : API Response - Result: error Message: Only expired licenses can be renewed.
[11/14/2024 8:47 PM] - SUCCESS : No license key found for row id (82). Deletion aborted. [11/20/2024 9:33 PM] - SUCCESS : API Response - Result: success Message: License renewed successfully.
[11/14/2024 8:48 PM] - SUCCESS : No license key found for row id (82). Deletion aborted. [11/20/2024 9:38 PM] - SUCCESS : API Response - Result: success Message: License renewed successfully.
[11/14/2024 8:48 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-B92A-33AD-70DD-1A9C-380D-9DEE-9A1A-FECE). [11/20/2024 9:40 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 8:48 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-B92A-33AD-70DD-1A9C-380D-9DEE-9A1A-FECE). [11/20/2024 9:40 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 8:48 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-B92A-33AD-70DD-1A9C-380D-9DEE-9A1A-FECE). [11/20/2024 9:51 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 8:48 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/20/2024 9:51 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 8:48 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/21/2024 3:37 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 8:49 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-EC44-E7FB-4A4F-B3AC-5043-DE79-5152-5C00). [11/21/2024 3:37 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 8:49 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-EC44-E7FB-4A4F-B3AC-5043-DE79-5152-5C00). [11/21/2024 3:37 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 8:49 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-EC44-E7FB-4A4F-B3AC-5043-DE79-5152-5C00). [11/21/2024 3:37 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 8:52 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-7689-9262-3105-A985-A7B1-2956-6975-91D4).
[11/14/2024 8:52 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-7689-9262-3105-A985-A7B1-2956-6975-91D4).
[11/14/2024 8:57 PM] - SUCCESS : No license key found for row id (84). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-7689-9262-3105-A985-A7B1-2956-6975-91D4).
[11/14/2024 8:57 PM] - SUCCESS : No license key found for row id (84). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-411A-7780-54D4-EAB5-78CC-D18E-402E-8ECA).
[11/14/2024 8:57 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-BA9D-1485-9B26-FC09-A65D-7982-AF9A-85A0). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-411A-7780-54D4-EAB5-78CC-D18E-402E-8ECA).
[11/14/2024 8:57 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-BA9D-1485-9B26-FC09-A65D-7982-AF9A-85A0). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-411A-7780-54D4-EAB5-78CC-D18E-402E-8ECA).
[11/14/2024 8:57 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-BA9D-1485-9B26-FC09-A65D-7982-AF9A-85A0). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6E1D-FAB4-CB46-AD2F-3494-5F82-B573-94B4).
[11/14/2024 9:00 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-6E1D-FAB4-CB46-AD2F-3494-5F82-B573-94B4).
[11/14/2024 9:00 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6E1D-FAB4-CB46-AD2F-3494-5F82-B573-94B4).
[11/14/2024 9:00 PM] - SUCCESS : No license key found for row id (85). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-33F1-68F0-1488-1457-48D0-6E6A-7EA4-223B).
[11/14/2024 9:00 PM] - SUCCESS : No license key found for row id (85). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-33F1-68F0-1488-1457-48D0-6E6A-7EA4-223B).
[11/14/2024 9:00 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6605-9268-E33C-AD4A-9DB2-997C-BB20-7D7C). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-33F1-68F0-1488-1457-48D0-6E6A-7EA4-223B).
[11/14/2024 9:00 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-6605-9268-E33C-AD4A-9DB2-997C-BB20-7D7C). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-B004-1CE7-5B61-20FC-EE1E-CF0A-9FE3-584C).
[11/14/2024 9:00 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6605-9268-E33C-AD4A-9DB2-997C-BB20-7D7C). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-B004-1CE7-5B61-20FC-EE1E-CF0A-9FE3-584C).
[11/14/2024 9:07 PM] - SUCCESS : No license key found for row id (86). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-B004-1CE7-5B61-20FC-EE1E-CF0A-9FE3-584C).
[11/14/2024 9:08 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-4885-B342-5F38-6647-F289-D118-AABA-5E36).
[11/14/2024 9:08 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-4885-B342-5F38-6647-F289-D118-AABA-5E36).
[11/14/2024 9:09 PM] - SUCCESS : No license key found for row id (86). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-4885-B342-5F38-6647-F289-D118-AABA-5E36).
[11/14/2024 9:09 PM] - SUCCESS : No license key found for row id (86). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-56C6-64BE-9253-8BA7-C322-03FD-15FB-5981).
[11/14/2024 9:13 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-56C6-64BE-9253-8BA7-C322-03FD-15FB-5981).
[11/14/2024 9:13 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-56C6-64BE-9253-8BA7-C322-03FD-15FB-5981).
[11/14/2024 9:15 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6BF4-92F7-587C-11E6-FACA-5589-A7FB-7326).
[11/14/2024 9:15 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-6BF4-92F7-587C-11E6-FACA-5589-A7FB-7326).
[11/14/2024 9:16 PM] - SUCCESS : No license key found for row id (86). Deletion aborted. [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6BF4-92F7-587C-11E6-FACA-5589-A7FB-7326).
[11/14/2024 9:16 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-BFD7-241E-790D-BF31-312D-96B0-EBDD-E19C). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-9709-FDAE-51F7-4EF3-77AE-CBE3-ECD5-08FC).
[11/14/2024 9:16 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-BFD7-241E-790D-BF31-312D-96B0-EBDD-E19C). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-9709-FDAE-51F7-4EF3-77AE-CBE3-ECD5-08FC).
[11/14/2024 9:16 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-BFD7-241E-790D-BF31-312D-96B0-EBDD-E19C). [11/21/2024 1:34 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-9709-FDAE-51F7-4EF3-77AE-CBE3-ECD5-08FC).
[11/14/2024 9:16 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-8771-12E4-AB7C-1521-037F-3A91-D537-0F64). [11/21/2024 2:58 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 9:16 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-8771-12E4-AB7C-1521-037F-3A91-D537-0F64). [11/21/2024 2:58 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 9:16 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-8771-12E4-AB7C-1521-037F-3A91-D537-0F64). [11/21/2024 3:00 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/14/2024 9:16 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-84C6-93BE-3840-E581-12FC-AB2F-8ACC-1A0C). [11/21/2024 3:00 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/14/2024 9:16 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-84C6-93BE-3840-E581-12FC-AB2F-8ACC-1A0C). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLMEEB1-DBD2-EC5B-9773-D33F-4009-54D7-CAD2).
[11/14/2024 9:16 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-84C6-93BE-3840-E581-12FC-AB2F-8ACC-1A0C). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLMEEB1-DBD2-EC5B-9773-D33F-4009-54D7-CAD2).
[11/14/2024 9:16 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLMEEB1-DBD2-EC5B-9773-D33F-4009-54D7-CAD2).
[11/14/2024 9:16 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM704D-7CB6-45A4-7171-A8FD-A4B7-1D86-35B5).
[11/14/2024 9:17 PM] - SUCCESS : No license key found for row id (87). Deletion aborted. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM704D-7CB6-45A4-7171-A8FD-A4B7-1D86-35B5).
[11/14/2024 9:19 PM] - SUCCESS : No license key found for row id (87). Deletion aborted. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM704D-7CB6-45A4-7171-A8FD-A4B7-1D86-35B5).
[11/14/2024 9:21 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-4554-A7F9-4A30-9A6C-A9FB-2702-1384-0988). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLMCBA2-D7A4-9333-B6E4-A53A-DF7C-0784-2239).
[11/14/2024 9:21 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-4554-A7F9-4A30-9A6C-A9FB-2702-1384-0988). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLMCBA2-D7A4-9333-B6E4-A53A-DF7C-0784-2239).
[11/14/2024 9:21 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-4554-A7F9-4A30-9A6C-A9FB-2702-1384-0988). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLMCBA2-D7A4-9333-B6E4-A53A-DF7C-0784-2239).
[11/14/2024 9:22 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLMCA3A-A720-6316-4875-1ECB-AFC7-6186-3EA7).
[11/14/2024 9:22 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLMCA3A-A720-6316-4875-1ECB-AFC7-6186-3EA7).
[11/14/2024 9:30 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-CADC-9C52-0BDC-7429-F7A6-C58D-5AC7-1A2C). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLMCA3A-A720-6316-4875-1ECB-AFC7-6186-3EA7).
[11/14/2024 9:30 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-CADC-9C52-0BDC-7429-F7A6-C58D-5AC7-1A2C). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM97AB-F0EF-00FC-A1F1-5DC9-3F47-35BC-C766).
[11/14/2024 9:30 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-CADC-9C52-0BDC-7429-F7A6-C58D-5AC7-1A2C). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM97AB-F0EF-00FC-A1F1-5DC9-3F47-35BC-C766).
[11/14/2024 9:31 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM97AB-F0EF-00FC-A1F1-5DC9-3F47-35BC-C766).
[11/14/2024 9:31 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-5E7C-F888-7ACA-AA3B-DAC4-D8CE-5B23-4278).
[11/14/2024 9:32 PM] - SUCCESS : No license key found for row id (91). Deletion aborted. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-5E7C-F888-7ACA-AA3B-DAC4-D8CE-5B23-4278).
[11/14/2024 9:32 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-3BB9-9D7F-4F1F-DE50-FF7A-46E4-B81E-3FF0). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-5E7C-F888-7ACA-AA3B-DAC4-D8CE-5B23-4278).
[11/14/2024 9:32 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-3BB9-9D7F-4F1F-DE50-FF7A-46E4-B81E-3FF0). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-2444-3820-3FBD-F382-9CA8-8676-B76F-D3E2).
[11/14/2024 9:32 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-3BB9-9D7F-4F1F-DE50-FF7A-46E4-B81E-3FF0). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-2444-3820-3FBD-F382-9CA8-8676-B76F-D3E2).
[11/14/2024 9:37 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-2444-3820-3FBD-F382-9CA8-8676-B76F-D3E2).
[11/14/2024 9:37 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM0914-3985-B056-0769-55D0-FB88-0181-F6EA).
[11/15/2024 9:10 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-D44E-1DE7-3F8E-29C2-67C2-69CD-CD8E-EEFA). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM0914-3985-B056-0769-55D0-FB88-0181-F6EA).
[11/15/2024 9:10 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-D44E-1DE7-3F8E-29C2-67C2-69CD-CD8E-EEFA). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM0914-3985-B056-0769-55D0-FB88-0181-F6EA).
[11/15/2024 9:10 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-D44E-1DE7-3F8E-29C2-67C2-69CD-CD8E-EEFA). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-9785-89CF-4246-B8C8-8928-4EFC-B9AC-7F28).
[11/15/2024 9:10 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-1155-CB30-585F-C72C-3F02-7BF0-9B9D-F705). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-9785-89CF-4246-B8C8-8928-4EFC-B9AC-7F28).
[11/15/2024 9:10 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-1155-CB30-585F-C72C-3F02-7BF0-9B9D-F705). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-9785-89CF-4246-B8C8-8928-4EFC-B9AC-7F28).
[11/15/2024 9:10 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-1155-CB30-585F-C72C-3F02-7BF0-9B9D-F705). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-3BBF-F7AE-01CA-0875-A6A4-D3E4-3C64-1EEA).
[11/15/2024 9:24 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-3BBF-F7AE-01CA-0875-A6A4-D3E4-3C64-1EEA).
[11/15/2024 9:24 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-3BBF-F7AE-01CA-0875-A6A4-D3E4-3C64-1EEA).
[11/15/2024 9:24 PM] - SUCCESS : No license key found for row id (93). Deletion aborted. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-1CBB-F3E5-2190-E281-CCE1-D7C6-CD4F-EF63).
[11/15/2024 9:24 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-4401-2724-A27F-3E82-4654-0E83-738D-1641). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-1CBB-F3E5-2190-E281-CCE1-D7C6-CD4F-EF63).
[11/15/2024 9:24 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-4401-2724-A27F-3E82-4654-0E83-738D-1641). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-1CBB-F3E5-2190-E281-CCE1-D7C6-CD4F-EF63).
[11/15/2024 9:24 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-4401-2724-A27F-3E82-4654-0E83-738D-1641). [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-0BB4-BC87-09B3-DE7F-5BEF-A2DD-8350-4A75).
[11/15/2024 9:25 PM] - SUCCESS : API - license creation (slm_create_new) request received. [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from log table for license key (SLM-0BB4-BC87-09B3-DE7F-5BEF-A2DD-8350-4A75).
[11/15/2024 9:25 PM] - SUCCESS : API Response - Result: success Message: License successfully created [11/22/2024 3:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-0BB4-BC87-09B3-DE7F-5BEF-A2DD-8350-4A75).
[11/15/2024 9:25 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-4504-4439-ECED-1884-8425-CE8B-5500-E2CD).
[11/15/2024 9:25 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-4504-4439-ECED-1884-8425-CE8B-5500-E2CD).
[11/15/2024 9:25 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-4504-4439-ECED-1884-8425-CE8B-5500-E2CD).
[11/15/2024 9:27 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/15/2024 9:27 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/15/2024 9:27 PM] - SUCCESS : No license key found for row id (96). Deletion aborted.
[11/15/2024 9:27 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-309E-344F-2809-F0B8-5687-1C23-92D5-CAC1).
[11/15/2024 9:27 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-309E-344F-2809-F0B8-5687-1C23-92D5-CAC1).
[11/15/2024 9:27 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-309E-344F-2809-F0B8-5687-1C23-92D5-CAC1).
[11/15/2024 9:28 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/15/2024 9:28 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/15/2024 9:28 PM] - SUCCESS : No license key found for row id (97). Deletion aborted.
[11/15/2024 9:28 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-D8C9-95A1-49DE-FDB7-0FD0-E1C1-7418-9044).
[11/15/2024 9:28 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-D8C9-95A1-49DE-FDB7-0FD0-E1C1-7418-9044).
[11/15/2024 9:28 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-D8C9-95A1-49DE-FDB7-0FD0-E1C1-7418-9044).
[11/15/2024 9:29 PM] - SUCCESS : No license key found for row id (98). Deletion aborted.
[11/15/2024 9:29 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/15/2024 9:29 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/15/2024 9:30 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/15/2024 9:30 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/15/2024 9:32 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/15/2024 9:32 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/15/2024 9:32 PM] - SUCCESS : No license key found for row id (98). Deletion aborted.
[11/15/2024 9:32 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-7105-479C-85D4-56A7-3A08-AD0A-2723-3C36).
[11/15/2024 9:32 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-7105-479C-85D4-56A7-3A08-AD0A-2723-3C36).
[11/15/2024 9:32 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-7105-479C-85D4-56A7-3A08-AD0A-2723-3C36).
[11/15/2024 9:32 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-C7A8-30C6-2A87-D6C0-7D5A-EC8A-9562-02CF).
[11/15/2024 9:32 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-C7A8-30C6-2A87-D6C0-7D5A-EC8A-9562-02CF).
[11/15/2024 9:32 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-C7A8-30C6-2A87-D6C0-7D5A-EC8A-9562-02CF).
[11/15/2024 9:32 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6988-E35E-574D-5263-B449-E53E-3D9C-BCBC).
[11/15/2024 9:32 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-6988-E35E-574D-5263-B449-E53E-3D9C-BCBC).
[11/15/2024 9:32 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6988-E35E-574D-5263-B449-E53E-3D9C-BCBC).
[11/15/2024 9:33 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/15/2024 9:33 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/15/2024 9:33 PM] - SUCCESS : No license key found for row id (99). Deletion aborted.
[11/15/2024 9:33 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-E724-EC26-610E-EB10-D4B4-6BA1-FB1B-886D).
[11/15/2024 9:33 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-E724-EC26-610E-EB10-D4B4-6BA1-FB1B-886D).
[11/15/2024 9:33 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-E724-EC26-610E-EB10-D4B4-6BA1-FB1B-886D).
[11/16/2024 12:42 PM] - SUCCESS : No license key found for row id (102). Deletion aborted.
[11/16/2024 12:42 PM] - SUCCESS : No license key found for row id (102). Deletion aborted.
[11/16/2024 12:43 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:43 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:43 PM] - SUCCESS : No license key found for row id (102). Deletion aborted.
[11/16/2024 12:43 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-85A2-0795-DFC0-9E8E-414A-72C5-D8FC-5805).
[11/16/2024 12:43 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-85A2-0795-DFC0-9E8E-414A-72C5-D8FC-5805).
[11/16/2024 12:43 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-85A2-0795-DFC0-9E8E-414A-72C5-D8FC-5805).
[11/16/2024 12:44 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:44 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:44 PM] - SUCCESS : No license key found for row id (103). Deletion aborted.
[11/16/2024 12:44 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-E592-0B4C-C5CC-0444-565B-AE5B-9ECC-09E0).
[11/16/2024 12:44 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-E592-0B4C-C5CC-0444-565B-AE5B-9ECC-09E0).
[11/16/2024 12:44 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-E592-0B4C-C5CC-0444-565B-AE5B-9ECC-09E0).
[11/16/2024 12:45 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:45 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:45 PM] - SUCCESS : No license key found for row id (104). Deletion aborted.
[11/16/2024 12:45 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-7B4A-7FD5-05C4-69C4-8994-256D-DBE9-EDBA).
[11/16/2024 12:45 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-7B4A-7FD5-05C4-69C4-8994-256D-DBE9-EDBA).
[11/16/2024 12:45 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-7B4A-7FD5-05C4-69C4-8994-256D-DBE9-EDBA).
[11/16/2024 12:46 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:46 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:46 PM] - SUCCESS : No license key found for row id (105). Deletion aborted.
[11/16/2024 12:46 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-04CF-8A76-721C-CFF9-A998-D0C3-1B7C-2F5B).
[11/16/2024 12:46 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-04CF-8A76-721C-CFF9-A998-D0C3-1B7C-2F5B).
[11/16/2024 12:46 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-04CF-8A76-721C-CFF9-A998-D0C3-1B7C-2F5B).
[11/16/2024 12:47 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:47 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:47 PM] - SUCCESS : No license key found for row id (106). Deletion aborted.
[11/16/2024 12:47 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-E699-C8A8-761E-8E1A-860D-FB63-A4E9-1871).
[11/16/2024 12:47 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-E699-C8A8-761E-8E1A-860D-FB63-A4E9-1871).
[11/16/2024 12:47 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-E699-C8A8-761E-8E1A-860D-FB63-A4E9-1871).
[11/16/2024 12:48 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:48 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:48 PM] - SUCCESS : No license key found for row id (107). Deletion aborted.
[11/16/2024 12:48 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-9990-C635-DD8D-C077-092B-8B2F-2C80-19C0).
[11/16/2024 12:48 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-9990-C635-DD8D-C077-092B-8B2F-2C80-19C0).
[11/16/2024 12:48 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-9990-C635-DD8D-C077-092B-8B2F-2C80-19C0).
[11/16/2024 12:51 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:51 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:51 PM] - SUCCESS : No license key found for row id (108). Deletion aborted.
[11/16/2024 12:51 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-3AC5-D1F8-C29A-D502-F744-D6A2-2978-9F27).
[11/16/2024 12:51 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-3AC5-D1F8-C29A-D502-F744-D6A2-2978-9F27).
[11/16/2024 12:51 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-3AC5-D1F8-C29A-D502-F744-D6A2-2978-9F27).
[11/16/2024 12:56 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:56 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:56 PM] - SUCCESS : No license key found for row id (109). Deletion aborted.
[11/16/2024 12:56 PM] - SUCCESS : No license key found for row id (109). Deletion aborted.
[11/16/2024 12:56 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-2440-E86B-D53C-EA9C-05F1-DC1F-8AB0-99DD).
[11/16/2024 12:56 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-2440-E86B-D53C-EA9C-05F1-DC1F-8AB0-99DD).
[11/16/2024 12:56 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-2440-E86B-D53C-EA9C-05F1-DC1F-8AB0-99DD).
[11/16/2024 12:57 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:57 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:57 PM] - SUCCESS : No license key found for row id (110). Deletion aborted.
[11/16/2024 12:57 PM] - SUCCESS : No license key found for row id (110). Deletion aborted.
[11/16/2024 12:57 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6530-1BB5-9EFB-499B-0E2F-5E30-1D91-CA84).
[11/16/2024 12:57 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-6530-1BB5-9EFB-499B-0E2F-5E30-1D91-CA84).
[11/16/2024 12:57 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6530-1BB5-9EFB-499B-0E2F-5E30-1D91-CA84).
[11/16/2024 12:59 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 12:59 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 12:59 PM] - SUCCESS : No license key found for row id (111). Deletion aborted.
[11/16/2024 12:59 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-7E96-7D67-6081-002F-970F-3B4D-E0D4-D241).
[11/16/2024 12:59 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-7E96-7D67-6081-002F-970F-3B4D-E0D4-D241).
[11/16/2024 12:59 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-7E96-7D67-6081-002F-970F-3B4D-E0D4-D241).
[11/16/2024 1:00 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 1:00 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 1:00 PM] - SUCCESS : No license key found for row id (112). Deletion aborted.
[11/16/2024 1:00 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-A3A7-9E51-FE88-B3CF-2D32-03F9-754A-0C52).
[11/16/2024 1:00 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-A3A7-9E51-FE88-B3CF-2D32-03F9-754A-0C52).
[11/16/2024 1:00 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-A3A7-9E51-FE88-B3CF-2D32-03F9-754A-0C52).
[11/16/2024 1:12 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 1:12 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 1:23 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 1:23 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 1:23 PM] - SUCCESS : No license key found for row id (113). Deletion aborted.
[11/16/2024 1:23 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-0334-18CC-D8D3-4934-0BE8-3CDE-5027-8650).
[11/16/2024 1:23 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-0334-18CC-D8D3-4934-0BE8-3CDE-5027-8650).
[11/16/2024 1:23 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-0334-18CC-D8D3-4934-0BE8-3CDE-5027-8650).
[11/16/2024 1:23 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-5677-AF06-907B-08A5-B32E-9913-AFFB-F4F8).
[11/16/2024 1:23 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-5677-AF06-907B-08A5-B32E-9913-AFFB-F4F8).
[11/16/2024 1:23 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-5677-AF06-907B-08A5-B32E-9913-AFFB-F4F8).
[11/16/2024 1:23 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 1:23 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 1:25 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 1:25 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 1:25 PM] - SUCCESS : No license key found for row id (114). Deletion aborted.
[11/16/2024 1:25 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-CB2B-6D87-E702-594A-809F-6CC9-50D7-31A5).
[11/16/2024 1:25 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-CB2B-6D87-E702-594A-809F-6CC9-50D7-31A5).
[11/16/2024 1:25 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-CB2B-6D87-E702-594A-809F-6CC9-50D7-31A5).
[11/16/2024 1:25 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-3D21-3109-BC19-98F3-9EE8-8891-E33F-0F2A).
[11/16/2024 1:25 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-3D21-3109-BC19-98F3-9EE8-8891-E33F-0F2A).
[11/16/2024 1:25 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-3D21-3109-BC19-98F3-9EE8-8891-E33F-0F2A).
[11/16/2024 2:37 PM] - SUCCESS : No license key found for row id (117). Deletion aborted.
[11/16/2024 2:37 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 2:37 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 2:38 PM] - SUCCESS : No license key found for row id (117). Deletion aborted.
[11/16/2024 2:38 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-4AA8-C044-3F7D-A2D7-0C96-B028-3C0B-8DC6).
[11/16/2024 2:38 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-4AA8-C044-3F7D-A2D7-0C96-B028-3C0B-8DC6).
[11/16/2024 2:38 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-4AA8-C044-3F7D-A2D7-0C96-B028-3C0B-8DC6).
[11/16/2024 2:52 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 2:52 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 2:52 PM] - SUCCESS : No license key found for row id (118). Deletion aborted.
[11/16/2024 2:52 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-2F2D-0A50-589A-2218-FA9D-57CF-CDF1-AFDB).
[11/16/2024 2:52 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-2F2D-0A50-589A-2218-FA9D-57CF-CDF1-AFDB).
[11/16/2024 2:52 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-2F2D-0A50-589A-2218-FA9D-57CF-CDF1-AFDB).
[11/16/2024 2:53 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 2:53 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 2:53 PM] - SUCCESS : No license key found for row id (119). Deletion aborted.
[11/16/2024 2:53 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-5E7A-1E46-65B8-E0A9-20C8-3DCA-405D-0286).
[11/16/2024 2:53 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-5E7A-1E46-65B8-E0A9-20C8-3DCA-405D-0286).
[11/16/2024 2:53 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-5E7A-1E46-65B8-E0A9-20C8-3DCA-405D-0286).
[11/16/2024 2:54 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 2:54 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 2:55 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 2:55 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 2:59 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 2:59 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 3:00 PM] - SUCCESS : No license key found for row id (120). Deletion aborted.
[11/16/2024 3:01 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-CB3E-34BD-01A2-C01B-C6DA-FA9C-52D9-84E3).
[11/16/2024 3:01 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-CB3E-34BD-01A2-C01B-C6DA-FA9C-52D9-84E3).
[11/16/2024 3:01 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-CB3E-34BD-01A2-C01B-C6DA-FA9C-52D9-84E3).
[11/16/2024 3:02 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-16C2-D95B-90F5-E9B4-5B77-C4D7-17D2-EB74).
[11/16/2024 3:02 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-16C2-D95B-90F5-E9B4-5B77-C4D7-17D2-EB74).
[11/16/2024 3:02 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-16C2-D95B-90F5-E9B4-5B77-C4D7-17D2-EB74).
[11/16/2024 3:02 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-8265-D551-F989-EB4B-B5EF-F2AC-9CC2-E64F).
[11/16/2024 3:02 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-8265-D551-F989-EB4B-B5EF-F2AC-9CC2-E64F).
[11/16/2024 3:02 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-8265-D551-F989-EB4B-B5EF-F2AC-9CC2-E64F).
[11/16/2024 3:02 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 3:02 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 3:02 PM] - SUCCESS : No license key found for row id (122). Deletion aborted.
[11/16/2024 3:02 PM] - SUCCESS : No license key found for row id (121). Deletion aborted.
[11/16/2024 3:03 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-55AC-E91A-F0FA-61C8-9DF3-1A1F-38C8-82D1).
[11/16/2024 3:03 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-55AC-E91A-F0FA-61C8-9DF3-1A1F-38C8-82D1).
[11/16/2024 3:03 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-55AC-E91A-F0FA-61C8-9DF3-1A1F-38C8-82D1).
[11/16/2024 3:03 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 3:03 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 3:07 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 3:07 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 3:07 PM] - SUCCESS : No license key found for row id (124). Deletion aborted.
[11/16/2024 3:07 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-E488-1E7D-F14C-43D9-F1ED-B23D-EA38-60A9).
[11/16/2024 3:07 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-E488-1E7D-F14C-43D9-F1ED-B23D-EA38-60A9).
[11/16/2024 3:07 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-E488-1E7D-F14C-43D9-F1ED-B23D-EA38-60A9).
[11/16/2024 3:07 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-E4AC-924C-78A2-189D-2633-E4A6-39EE-1E99).
[11/16/2024 3:07 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-E4AC-924C-78A2-189D-2633-E4A6-39EE-1E99).
[11/16/2024 3:07 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-E4AC-924C-78A2-189D-2633-E4A6-39EE-1E99).
[11/16/2024 3:08 PM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/16/2024 3:08 PM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/16/2024 3:08 PM] - SUCCESS : No license key found for row id (125). Deletion aborted.
[11/16/2024 3:08 PM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-BD7C-BACD-412E-D268-61AC-DBF0-A557-B7AE).
[11/16/2024 3:08 PM] - SUCCESS : 1 entries deleted from log table for license key (SLM-BD7C-BACD-412E-D268-61AC-DBF0-A557-B7AE).
[11/16/2024 3:08 PM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-BD7C-BACD-412E-D268-61AC-DBF0-A557-B7AE).
[11/19/2024 1:32 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:32 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:33 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-D799-8DDC-3172-AF54-3A4C-C881-7A9E-C353).
[11/19/2024 1:33 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-D799-8DDC-3172-AF54-3A4C-C881-7A9E-C353).
[11/19/2024 1:33 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-D799-8DDC-3172-AF54-3A4C-C881-7A9E-C353).
[11/19/2024 1:33 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:33 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:36 AM] - SUCCESS : No license key found for row id (128). Deletion aborted.
[11/19/2024 1:36 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6540-30EF-63A5-EF6E-3C37-A465-8846-192B).
[11/19/2024 1:36 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-6540-30EF-63A5-EF6E-3C37-A465-8846-192B).
[11/19/2024 1:36 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6540-30EF-63A5-EF6E-3C37-A465-8846-192B).
[11/19/2024 1:43 AM] - SUCCESS : No license key found for row id (129). Deletion aborted.
[11/19/2024 1:43 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:43 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:43 AM] - SUCCESS : No license key found for row id (129). Deletion aborted.
[11/19/2024 1:44 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-AE29-5021-38EE-5C99-9982-72B2-14E2-64A1).
[11/19/2024 1:44 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-AE29-5021-38EE-5C99-9982-72B2-14E2-64A1).
[11/19/2024 1:44 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-AE29-5021-38EE-5C99-9982-72B2-14E2-64A1).
[11/19/2024 1:46 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:46 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:46 AM] - SUCCESS : No license key found for row id (130). Deletion aborted.
[11/19/2024 1:47 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-1CD0-1BA9-C29C-C09B-DCFF-19F6-E85C-7859).
[11/19/2024 1:47 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-1CD0-1BA9-C29C-C09B-DCFF-19F6-E85C-7859).
[11/19/2024 1:47 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-1CD0-1BA9-C29C-C09B-DCFF-19F6-E85C-7859).
[11/19/2024 1:50 AM] - SUCCESS : No license key found for row id (131). Deletion aborted.
[11/19/2024 1:50 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:50 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:51 AM] - SUCCESS : No license key found for row id (131). Deletion aborted.
[11/19/2024 1:52 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6954-42D7-18A2-D4EA-E6B0-341E-1CB8-A6B1).
[11/19/2024 1:52 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-6954-42D7-18A2-D4EA-E6B0-341E-1CB8-A6B1).
[11/19/2024 1:52 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6954-42D7-18A2-D4EA-E6B0-341E-1CB8-A6B1).
[11/19/2024 1:52 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:52 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:55 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 1:55 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 1:56 AM] - SUCCESS : No license key found for row id (132). Deletion aborted.
[11/19/2024 2:03 AM] - SUCCESS : No license key found for row id (132). Deletion aborted.
[11/19/2024 2:03 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-DFF3-16D6-C4D4-9AA1-65C6-3B48-F90F-ACA0).
[11/19/2024 2:03 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-DFF3-16D6-C4D4-9AA1-65C6-3B48-F90F-ACA0).
[11/19/2024 2:03 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-DFF3-16D6-C4D4-9AA1-65C6-3B48-F90F-ACA0).
[11/19/2024 2:03 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-57B7-0FAD-96D5-08A6-FD2E-6349-309C-E0CF).
[11/19/2024 2:03 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-57B7-0FAD-96D5-08A6-FD2E-6349-309C-E0CF).
[11/19/2024 2:03 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-57B7-0FAD-96D5-08A6-FD2E-6349-309C-E0CF).
[11/19/2024 2:03 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 2:03 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 2:06 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 2:06 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 2:26 AM] - SUCCESS : No license key found for row id (133). Deletion aborted.
[11/19/2024 2:27 AM] - SUCCESS : No license key found for row id (133). Deletion aborted.
[11/19/2024 2:28 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-6A1C-C6DC-F906-1A0A-81FD-F747-1F0A-8576).
[11/19/2024 2:28 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-6A1C-C6DC-F906-1A0A-81FD-F747-1F0A-8576).
[11/19/2024 2:28 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-6A1C-C6DC-F906-1A0A-81FD-F747-1F0A-8576).
[11/19/2024 2:28 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-89E4-8139-76B7-1003-C7C0-4BC4-6212-BD35).
[11/19/2024 2:28 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-89E4-8139-76B7-1003-C7C0-4BC4-6212-BD35).
[11/19/2024 2:28 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-89E4-8139-76B7-1003-C7C0-4BC4-6212-BD35).
[11/19/2024 2:29 AM] - SUCCESS : No license key found for row id (135). Deletion aborted.
[11/19/2024 2:32 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 2:32 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 2:32 AM] - SUCCESS : API - license creation (slm_create_new) request received.
[11/19/2024 2:32 AM] - SUCCESS : API Response - Result: success Message: License successfully created
[11/19/2024 2:33 AM] - SUCCESS : No license key found for row id (135). Deletion aborted.
[11/19/2024 2:33 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-C186-4990-98C2-901D-A226-3965-5D65-F806).
[11/19/2024 2:33 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-C186-4990-98C2-901D-A226-3965-5D65-F806).
[11/19/2024 2:33 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-C186-4990-98C2-901D-A226-3965-5D65-F806).
[11/19/2024 2:33 AM] - SUCCESS : 0 entries deleted from devices table for license key (SLM-DAB0-BF76-E594-2E3B-99CF-4EAA-AA48-502E).
[11/19/2024 2:33 AM] - SUCCESS : 1 entries deleted from log table for license key (SLM-DAB0-BF76-E594-2E3B-99CF-4EAA-AA48-502E).
[11/19/2024 2:33 AM] - SUCCESS : 0 entries deleted from emails table for license key (SLM-DAB0-BF76-E594-2E3B-99CF-4EAA-AA48-502E).

View file

@ -1,7 +1,7 @@
<?php <?php
/* /*
Plugin Name: SLM Plus Plugin Name: SLM Plus
Version: 6.1.9 Version: 6.3.2
Plugin URI: https://github.com/michelve/software-license-manager/ Plugin URI: https://github.com/michelve/software-license-manager/
Author: Michel Velis Author: Michel Velis
Author URI: https://github.com/michelve/ Author URI: https://github.com/michelve/
@ -33,9 +33,9 @@ add_action('plugins_loaded', 'slmplus_load_textdomain');
global $wpdb, $slm_debug_logger; global $wpdb, $slm_debug_logger;


// Define constants for plugin paths, URLs, and database tables // Define constants for plugin paths, URLs, and database tables
define('SLM_VERSION', '6.1.9'); define('SLM_VERSION', '6.3.2');
define('SLM_DB_VERSION', '5.1.2'); define('SLM_DB_VERSION', '5.8.7');
define('SLM_REWRITE_VERSION', '3.0.8'); define('SLM_REWRITE_VERSION', '3.1.2');
define('SLM_FOLDER', dirname(plugin_basename(__FILE__))); define('SLM_FOLDER', dirname(plugin_basename(__FILE__)));
define('SLM_URL', plugins_url('', __FILE__)); define('SLM_URL', plugins_url('', __FILE__));
define('SLM_ASSETS_URL', SLM_URL . '/public/assets/'); define('SLM_ASSETS_URL', SLM_URL . '/public/assets/');
@ -69,9 +69,7 @@ if (file_exists(SLM_LIB . 'slm-plugin-core.php')) {
function slm_settings_link($links) function slm_settings_link($links)
{ {
$settings_link = '<a href="' . esc_url(admin_url('admin.php?page=slm_settings')) . '">' . __('Settings', 'slm-plus') . '</a>'; $settings_link = '<a href="' . esc_url(admin_url('admin.php?page=slm_settings')) . '">' . __('Settings', 'slm-plus') . '</a>';
// $github_link = '<a href="' . esc_url('https://github.com/michelve/software-license-manager') . '" target="_blank">' . __('GitHub') . '</a>';
$links[] = $settings_link; $links[] = $settings_link;
//$links[] = $github_link;
return $links; return $links;
} }
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'slm_settings_link'); add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'slm_settings_link');

View file

@ -0,0 +1,134 @@
<?php
/**
* Template Name: License Cart
* Template Post Type: page
*/

if (!defined('ABSPATH')) {
exit;
}

// Include WordPress header
get_header();

/**
* Retrieve and set the renewal license key.
*
* @return string|null The renewal license key, if available.
*/
function get_renew_license_key() {
// Check if the license key is passed via the URL
if (isset($_GET['renew_license_key']) && !empty($_GET['renew_license_key'])) {
$renew_license_key = sanitize_text_field($_GET['renew_license_key']);
if (class_exists('WooCommerce') && WC()->session) {
WC()->session->set('renew_license_key', $renew_license_key);
}
SLM_Helper_Class::write_log("Renewal license key set from URL: {$renew_license_key}");
return $renew_license_key;
}

// Retrieve license key from session
if (class_exists('WooCommerce') && WC()->session) {
$renew_license_key = WC()->session->get('renew_license_key');
if (!empty($renew_license_key)) {
SLM_Helper_Class::write_log("Renewal license key retrieved from session: {$renew_license_key}");
return $renew_license_key;
}
}

SLM_Helper_Class::write_log("No renewal license key found in URL or session.");
return null;
}

// Determine if it's a renewal
$renew_license_key = get_renew_license_key();
$is_renewal = !empty($renew_license_key);

?>

<div class="license-checkout-container">
<h1><?php esc_html_e('License Checkout', 'slm-plus'); ?></h1>

<?php if (class_exists('WooCommerce') && WC()->cart && WC()->cart->is_empty()) : ?>
<!-- Show empty cart message -->
<div class="woocommerce-info">
<?php echo esc_html__('Your cart is currently empty.', 'slm-plus'); ?>
</div>

<!-- Show license product suggestions -->
<div class="license-product-suggestions">
<h2><?php esc_html_e('Recommended License Products', 'slm-plus'); ?></h2>
<ul class="products">
<?php
// Query for license products
$args = array(
'post_type' => 'product',
'posts_per_page' => 5, // Number of products to display
'tax_query' => array(
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => 'slm_license',
),
),
);

$license_products = new WP_Query($args);

if ($license_products->have_posts()) :
while ($license_products->have_posts()) : $license_products->the_post();
global $product;

// Ensure the product is valid and contains license data
if ($product && $product->is_type('slm_license')) :
?>
<li class="product">
<a href="<?php the_permalink(); ?>">
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('woocommerce_gallery_thumbnail'); // Use smaller WooCommerce thumbnail size ?>
<?php endif; ?>
<h3><?php the_title(); ?></h3>
<span class="price"><?php echo $product->get_price_html(); ?></span>
</a>
<a href="<?php echo esc_url('?add-to-cart=' . $product->get_id()); ?>" class="button add-to-cart">
<?php esc_html_e('Add to Cart', 'slm-plus'); ?>
</a>
</li>
<?php
endif;
endwhile;
wp_reset_postdata();
else :
?>
<p><?php esc_html_e('No license products available at the moment.', 'slm-plus'); ?></p>
<?php endif; ?>
</ul>


</div>
<?php else : ?>
<?php if ($is_renewal) : ?>
<!-- Show renewal message -->
<div class="renewal-info woocommerce-info">
<p>
<?php echo esc_html__('You are renewing the license key:', 'slm-plus'); ?>
<strong><?php echo esc_html($renew_license_key); ?></strong>
</p>
<p><?php echo esc_html__('Please proceed to complete your renewal.', 'slm-plus'); ?></p>
</div>
<?php else : ?>
<!-- Show new license purchase message -->
<div class="new-license-info woocommerce-info">
<?php echo esc_html__('You are purchasing a new license.', 'slm-plus'); ?>
</div>
<?php endif; ?>
<?php endif; ?>

<div class="woocommerce-cart">
<?php echo do_shortcode('[woocommerce_checkout]'); ?>
</div>
</div>

<?php
// Include WordPress footer
get_footer();

View file

@ -185,9 +185,6 @@ function slm_generate_licenses_callback()
$license_key = sanitize_text_field($api_response['key']); $license_key = sanitize_text_field($api_response['key']);
$success_count++; $success_count++;


$item->add_meta_data('License Key', $license_key, true);
$item->add_meta_data('License Type', $slm_lic_type, true);

$order->add_order_note( $order->add_order_note(
// Translators: %s is the generated license key // Translators: %s is the generated license key
sprintf(__('License Key generated: %s', 'slm-plus'), $license_key) sprintf(__('License Key generated: %s', 'slm-plus'), $license_key)
@ -210,6 +207,18 @@ function slm_generate_licenses_callback()
$product_id = $item->get_product_id(); $product_id = $item->get_product_id();
$product_name = $item->get_name(); $product_name = $item->get_name();


// Fetch the license key directly using the order ID
$existing_license_key = SLM_Utility::slm_get_license_by_order_id($order_id);

if ($existing_license_key) {
// Add the current order to associated orders for the existing license
SLM_Utility::slm_add_associated_order($existing_license_key, $order_id);

$skipped_orders[] = $order_id;
$skipped_reasons[$order_id] = 'Already has a license';
continue;
}

if ($item->meta_exists('_slm_lic_key')) { if ($item->meta_exists('_slm_lic_key')) {
$skipped_orders[] = $order_id; $skipped_orders[] = $order_id;
$skipped_reasons[$order_id] = 'Already has a license'; $skipped_reasons[$order_id] = 'Already has a license';
@ -235,6 +244,7 @@ function slm_generate_licenses_callback()
$success_count++; $success_count++;
$generated_licenses[] = ['license_key' => $license_key, 'order_id' => $order_id]; $generated_licenses[] = ['license_key' => $license_key, 'order_id' => $order_id];


$item->add_meta_data('_slm_lic_key', $license_key, true);
$item->add_meta_data('License Key', $license_key, true); $item->add_meta_data('License Key', $license_key, true);
$item->add_meta_data('License Type', $slm_lic_type, true); $item->add_meta_data('License Type', $slm_lic_type, true);



View file

@ -0,0 +1,444 @@
<?php
/**
* SLM Plus License Checkout Hooks
*
* Handles WooCommerce hooks for processing license renewals and custom checkout.
*/

if (!defined('ABSPATH')) {
exit;
}

function slm_debug_log($message) {
if (defined('WP_DEBUG') && WP_DEBUG) {
SLM_Helper_Class::write_log($message);
}
}


/**
* Save the renewal license key during checkout.
*/
/**
* Save the renewal license key during checkout.
*/
add_action('woocommerce_checkout_update_order_meta', 'slm_save_renewal_key_to_order');
function slm_save_renewal_key_to_order($order_id) {
$renew_license_key = isset($_POST['billing_license_renewal']) ? sanitize_text_field($_POST['billing_license_renewal']) : '';
if (!empty($renew_license_key)) {
update_post_meta($order_id, '_renew_license_key', $renew_license_key);
slm_debug_log("Renewal License Key saved to Order ID {$order_id}: {$renew_license_key}");
}
}

/**
* Display the renewal key on the admin order page.
*/
add_action('woocommerce_admin_order_data_after_billing_address', 'slm_display_renewal_key_in_admin');
function slm_display_renewal_key_in_admin($order) {
$renew_license_key = get_post_meta($order->get_id(), '_renew_license_key', true);
if (!empty($renew_license_key)) {
echo '<p><strong>' . esc_html__('Renewal License Key:', 'slm-plus') . '</strong> ' . esc_html($renew_license_key) . '</p>';
}
}

/**
* Add the renewal key to WooCommerce email notifications.
*/
add_action('woocommerce_email_order_meta', 'slm_add_renewal_key_to_email', 10, 3);
function slm_add_renewal_key_to_email($order, $sent_to_admin, $plain_text) {
$renew_license_key = get_post_meta($order->get_id(), '_renew_license_key', true);

if (!empty($renew_license_key)) {
echo '<p><strong>' . esc_html__('Renewal License Key:', 'slm-plus') . '</strong> ' . esc_html($renew_license_key) . '</p>';
}
}




/**
* Remove the "Additional Information" section on the custom checkout page.
*/
add_action('template_redirect', 'slm_remove_additional_info_on_custom_checkout');
function slm_remove_additional_info_on_custom_checkout() {
// Check if the current page is your custom checkout page
if (is_page_template('license-checkout.php')) {
add_filter('woocommerce_enable_order_notes_field', '__return_false');
}
}

/**
* Handle license renewal during order processing.
*/
add_action('woocommerce_order_status_completed', 'slm_process_license_renewal', 10, 1);
function slm_process_license_renewal($order_id) {
$renew_license_key = get_post_meta($order_id, '_renew_license_key', true);

if (!empty($renew_license_key)) {
// Log the renewal process
SLM_Helper_Class::write_log("Processing renewal for License Key {$renew_license_key} on Order ID {$order_id}");

// Call the renewal function from purchase.php
wc_slm_renew_license(wc_get_order($order_id));
} else {
// Log and fallback to new license creation
SLM_Helper_Class::write_log("No renewal key found. Proceeding with new license creation for Order ID {$order_id}");
wc_slm_create_new_license(wc_get_order($order_id));
}
}


add_action('woocommerce_add_to_cart', 'slm_clear_old_renew_license_key', 5);
function slm_clear_old_renew_license_key() {
if (WC()->session->get('renew_license_key')) {
WC()->session->__unset('renew_license_key');
slm_debug_log("Cleared old renewal license key from session.");
}
}


add_action('woocommerce_before_cart_item_quantity_zero', 'slm_clear_renew_license_key_on_cart_change', 10);
function slm_clear_renew_license_key_on_cart_change($cart_item_key) {
$cart = WC()->cart->get_cart();

if (isset($cart[$cart_item_key]['renew_license_key'])) {
unset(WC()->cart->cart_contents[$cart_item_key]['renew_license_key']);
SLM_Helper_Class::write_log("License key removed from cart item: {$cart_item_key}");
}
}

add_filter('woocommerce_cart_item_display', 'slm_reset_license_key_on_cart_change', 10, 3);
function slm_reset_license_key_on_cart_change($cart_item_html, $cart_item, $cart_item_key) {
if (isset($cart_item['renew_license_key'])) {
$current_license = $cart_item['renew_license_key'];

// Check if license key is mismatched or invalid
if (!slm_is_valid_license($current_license)) {
WC()->cart->cart_contents[$cart_item_key]['renew_license_key'] = null;
SLM_Helper_Class::write_log("Invalid or mismatched license key cleared from cart.");
}
}

return $cart_item_html;
}

function slm_is_valid_license($license_key) {
global $wpdb;
$lic_key_table = $wpdb->prefix . 'lic_key_tbl';
$license = $wpdb->get_var($wpdb->prepare("SELECT license_key FROM $lic_key_table WHERE license_key = %s", $license_key));
return !empty($license);
}

/**
* Restrict cart to one license product.
*/
add_filter('woocommerce_add_to_cart_validation', 'slm_restrict_cart_quantity', 10, 5);
function slm_restrict_cart_quantity($passed, $product_id, $quantity, $variation_id = '', $cart_item_data = []) {
// Ensure WooCommerce is initialized
if (!WC()->cart) {
return $passed;
}

// Get the product being added
$product = wc_get_product($product_id);

// Check if the product is a license product
if ($product && $product->is_type('slm_license')) {
// Loop through existing cart items
foreach (WC()->cart->get_cart() as $cart_item) {
if ($cart_item['data']->is_type('slm_license')) {
// Add notice only once
if (!wc_has_notice(__('You can only add one license product (either new or renewal) to your cart at a time.', 'slm-plus'))) {
wc_add_notice(__('You can only add one license product (either new or renewal) to your cart at a time.', 'slm-plus'), 'error');
}
return false;
}
}
}

return $passed;
}

/**
* Validate cart before checkout to ensure only one license product.
*/
add_action('woocommerce_check_cart_items', 'slm_validate_cart_before_checkout');
function slm_validate_cart_before_checkout() {
if (!WC()->cart) {
return;
}

$license_count = 0;

// Count license products in the cart
foreach (WC()->cart->get_cart() as $cart_item) {
if ($cart_item['data']->is_type('slm_license')) {
$license_count++;
}
}

// If more than one license product is in the cart, display an error and block checkout
if ($license_count > 1) {
if (!wc_has_notice(__('You can only have one license product (new or renewal) in your cart.', 'slm-plus'))) {
wc_add_notice(__('You can only have one license product (new or renewal) in your cart.', 'slm-plus'), 'error');
}
}
}

/**
* Automatically remove extra license products if multiple are added to the cart.
*/
add_action('woocommerce_before_calculate_totals', 'slm_remove_extra_license_products', 10, 1);
function slm_remove_extra_license_products($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}

$license_product_key = null;

// Loop through the cart to find license products
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];

if ($product && $product->is_type('slm_license')) {
// Keep the first license product, remove the rest
if ($license_product_key === null) {
$license_product_key = $cart_item_key;
} else {
$cart->remove_cart_item($cart_item_key);
wc_add_notice(__('Only one license product is allowed in the cart. Extra items have been removed.', 'slm-plus'), 'notice');
}
}
}
}



add_filter('woocommerce_cart_item_quantity', 'slm_limit_cart_quantity', 10, 3);

function slm_limit_cart_quantity($product_quantity, $cart_item_key, $cart_item) {
if ($cart_item['data']->is_type('slm_license')) {
$product_quantity = sprintf(
'<input type="number" name="cart[%s][qty]" value="1" readonly="readonly" class="input-text qty text" />',
$cart_item_key
);
}

return $product_quantity;
}



add_filter('woocommerce_cart_item_quantity', 'slm_disable_quantity_change', 10, 3);

function slm_disable_quantity_change($quantity, $cart_item_key, $cart_item) {
if ($cart_item['data']->is_type('slm_license')) {
// Display quantity as non-editable text
return '<span>' . esc_html($cart_item['quantity']) . '</span>';
}

return $quantity;
}

/**
* Handle license product restrictions in cart.
*/
add_action('woocommerce_check_cart_items', 'slm_remove_existing_license_product');
function slm_remove_existing_license_product() {
$license_product_key = null;

foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
if ($product->is_type('slm_license')) {
if ($license_product_key === null) {
$license_product_key = $cart_item_key;
} else {
WC()->cart->remove_cart_item($cart_item_key);
slm_debug_log("Removed additional license product from the cart.");
}
}
}
}




add_filter('woocommerce_add_cart_item_data', 'slm_add_renew_license_key_to_cart', 10, 2);

function slm_add_renew_license_key_to_cart($cart_item_data, $product_id) {
if (isset($_POST['renew_license_key']) && !empty($_POST['renew_license_key'])) {
$renew_license_key = sanitize_text_field($_POST['renew_license_key']);
$cart_item_data['renew_license_key'] = $renew_license_key;

// Save to session for later use
WC()->session->set('renew_license_key', $renew_license_key);
slm_debug_log("Renewal License Key added to cart item data and session: {$renew_license_key}");
}

return $cart_item_data;
}



add_filter('woocommerce_get_cart_item_from_session', 'slm_get_renew_license_key_from_session', 10, 2);

function slm_get_renew_license_key_from_session($cart_item, $values) {
if (isset($values['renew_license_key'])) {
$cart_item['renew_license_key'] = $values['renew_license_key'];
slm_debug_log("Renewal License Key retrieved from session for cart item: {$values['renew_license_key']}");
}

return $cart_item;
}


add_action('woocommerce_check_cart_items', 'slm_validate_license_cart');

function slm_validate_license_cart() {
$license_count = 0;

foreach (WC()->cart->get_cart() as $cart_item) {
if ($cart_item['data']->is_type('slm_license')) {
$license_count++;
}
}

if ($license_count > 1) {
wc_add_notice(__('You can only have one license (new or renewal) in your cart.', 'slm-plus'), 'error');
}
}


/**
* Redirect to custom cart page for license products.
*/
add_filter('woocommerce_add_to_cart_redirect', 'slm_redirect_to_custom_cart_page');
function slm_redirect_to_custom_cart_page($url) {
if (isset($_POST['add-to-cart']) && !empty($_POST['add-to-cart'])) {
$product_id = intval($_POST['add-to-cart']);
$product = wc_get_product($product_id);

if ($product && $product->is_type('slm_license')) {
$custom_cart_url = home_url('/license-cart');
if (isset($_POST['renew_license_key']) && !empty($_POST['renew_license_key'])) {
$renew_license_key = sanitize_text_field($_POST['renew_license_key']);
$custom_cart_url = add_query_arg('renew_license_key', $renew_license_key, $custom_cart_url);
}
return $custom_cart_url;
}
}
return $url;
}


/**
* Customize WooCommerce checkout fields.
*/
/**
* Customize WooCommerce checkout fields.
*/
add_filter('woocommerce_checkout_fields', 'slm_customize_checkout_fields');
function slm_customize_checkout_fields($fields) {
// Retrieve the renewal license key from the session
$renew_license_key = WC()->session->get('renew_license_key');
SLM_Helper_Class::write_log("Renew license key retrieved in customize_checkout_fields: {$renew_license_key}");

// Add the renewal license field if the key is set
if (!empty($renew_license_key)) {
$fields['billing']['billing_license_renewal'] = array(
'type' => 'text',
'label' => esc_html__('This order includes a license renewal for:', 'slm-plus'),
'placeholder' => '',
'class' => array('form-row-wide'),
'custom_attributes' => array('readonly' => 'readonly'),
'priority' => 29, // Position it above "Company Name"
);

// Force the value of the field to the session key
add_filter('woocommerce_checkout_get_value', function ($value, $input) use ($renew_license_key) {
if ($input === 'billing_license_renewal') {
SLM_Helper_Class::write_log("Forcing value for billing_license_renewal: {$renew_license_key}");
return $renew_license_key;
}
return $value;
}, 10, 2);
}

return $fields;
}


// Set renew license key in session during redirect.
add_action('init', function () {
if (isset($_GET['renew_license']) && isset($_GET['product_id'])) {
// Ensure WooCommerce session exists
if (class_exists('WooCommerce') && WC()->session) {
$renew_license_key = sanitize_text_field($_GET['renew_license']);
WC()->session->set('renew_license_key', $renew_license_key);
SLM_Helper_Class::write_log("Renew license key set in session during redirect: {$renew_license_key}");
} else {
SLM_Helper_Class::write_log("WooCommerce session not initialized. Cannot set renew license key.");
}
}
});

// Clear the renew license key from session on specific conditions.
add_action('wp_loaded', function () {
if (class_exists('WooCommerce') && WC()->session) {
// Example: Clear session key after completing the process or on specific conditions
if (isset($_GET['clear_renew_key'])) { // Example condition
$renew_license_key = WC()->session->get('renew_license_key');
WC()->session->__unset('renew_license_key');
SLM_Helper_Class::write_log("Renew license key cleared from session: {$renew_license_key}");
}
} else {
SLM_Helper_Class::write_log("WooCommerce session not available. Cannot clear renew license key.");
}
});

/**
* Display a notice on the checkout page for license renewal.
*/
add_action('woocommerce_before_checkout_form', function () {
$renew_license_key = WC()->session->get('renew_license_key');
});




/**
* Clear renewal license session data when the cart is empty.
*/
add_action('woocommerce_cart_updated', 'slm_clear_session_if_cart_empty');
function slm_clear_session_if_cart_empty() {
// Ensure WooCommerce session is initialized
if (class_exists('WooCommerce') && WC()->session) {
// Check if the cart is empty
if (WC()->cart->is_empty()) {
// Clear the renew license key from the session
if (WC()->session->get('renew_license_key')) {
$renew_license_key = WC()->session->get('renew_license_key');
WC()->session->__unset('renew_license_key');
SLM_Helper_Class::write_log("Cart is empty. Cleared renew license key from session: {$renew_license_key}");
}

// Optionally, clear WooCommerce cookies
WC()->session->destroy_session();
SLM_Helper_Class::write_log("Cart is empty. WooCommerce session and cookies cleared.");
}
}
}

add_action('woocommerce_before_cart', function () {
if (WC()->cart->is_empty()) {
wc_add_notice(__('Your cart is empty. Session data has been cleared.', 'slm-plus'), 'notice');
}
});

add_action('woocommerce_cart_is_empty', function () {
if (WC()->session && WC()->session->get('renew_license_key')) {
WC()->session->__unset('renew_license_key');
SLM_Helper_Class::write_log("Cleared renew_license_key as cart is empty.");
}
});

View file

@ -0,0 +1,49 @@
<?php
/**
*
* Handles Page Creation
*/

if (!defined('ABSPATH')) {
exit;
}

/**
* Create License Cart page on plugin activation if it doesn't exist.
*/
function slm_create_license_cart_page() {
// Check if the License Cart page already exists
$query = new WP_Query(array(
'post_type' => 'page',
'name' => 'license-cart', // Check for the slug
'post_status' => 'publish',
'posts_per_page' => 1,
));

if (!$query->have_posts()) {
// Create the License Cart page
$page_id = wp_insert_post(array(
'post_title' => 'License Cart',
'post_content' => '', // Empty content for now
'post_status' => 'publish',
'post_type' => 'page',
'post_name' => 'license-cart', // Set the slug
'meta_input' => array('_wp_page_template' => 'page-license-cart.php'), // Assign the custom template
));

if ($page_id && !is_wp_error($page_id)) {
// Optionally, hide the page from menus/navigation
update_post_meta($page_id, '_menu_item_visibility', 'hidden');
error_log(__('License Cart page created successfully with ID: ', 'slm-plus') . $page_id);
} else {
error_log(__('Failed to create License Cart page.', 'slm-plus'));
}
} else {
error_log(__('License Cart page already exists.', 'slm-plus'));
}
}

/**
* Hook into plugin activation to create the License Cart page.
*/
register_activation_hook(__FILE__, 'slm_create_license_cart_page');

View file

@ -5,7 +5,6 @@
* @package SLM Plus * @package SLM Plus
* @author Michel Velis * @author Michel Velis
* @license GPL-2.0+ * @license GPL-2.0+
* @link http://epikly.com
* @since 4.5.5 * @since 4.5.5
*/ */


@ -14,630 +13,261 @@ if (!defined('ABSPATH')) {
exit; exit;
} }


global $post, $woocommerce, $product; add_action('woocommerce_order_details_after_order_table', 'slm_display_licenses_in_order_details', 10, 1);
add_action('woocommerce_order_status_completed', 'wc_slm_process_order_completion', 10);


// Retrieve plugin options
$slm_options = get_option('slm_plugin_options');
$affect_downloads = isset($slm_options['slm_woo_affect_downloads']) && $slm_options['slm_woo_affect_downloads'] == '1';


// Hooks for WooCommerce Integration function wc_slm_process_order_completion($order_id) {
// Add license management for orders that are marked as completed global $wpdb;
add_action('woocommerce_order_status_completed', 'slm_order_completed', 81);


// Set downloadable product permissions expiration based on license expiration if the option is enabled if (empty($order_id) || !is_numeric($order_id)) {
if ($affect_downloads) { return SLM_Helper_Class::write_log("Invalid order ID provided: $order_id");
add_action('woocommerce_order_status_completed', 'wc_slm_access_expiration', 82);
}

// Add additional license management after order completion
add_action('woocommerce_order_status_completed', 'wc_slm_on_complete_purchase', 10);

// Display license key information more nicely in the order item meta table
add_action('woocommerce_after_order_itemmeta', 'slm_display_nice_item_meta', 10, 3);

/**
* Display order meta data in Order items table in a user-friendly way.
*
* @param int $item_id The item ID.
* @param WC_Order_Item $item The item object.
* @param WC_Product $product The product object.
*
* @since 4.5.5
*/
function slm_display_nice_item_meta($item_id, $item, $product)
{
// Fetch the metadata associated with the license key
if ($meta_data = wc_get_order_item_meta($item_id, '_slm_lic_key', false)) {
?>
<div class="view">
<table cellspacing="0" class="display_meta">
<?php
$admin_link = esc_url(get_admin_url() . 'admin.php?page=slm_manage_license&edit_record=');
foreach ($meta_data as $meta) :
$lic_key = sanitize_text_field($meta);
$lic_id = wc_slm_get_license_id($lic_key);
if (!empty($lic_id)) {
$cur_link = sprintf(
'<a href="%s" target="_blank">%s</a>',
esc_url($admin_link . $lic_id),
esc_html($lic_key)
);
} else {
$cur_link = sprintf(
'%s - %s',
esc_html($lic_key),
esc_html__('License no longer exists', 'slm-plus')
);
}
?>
<tr>
<th><?php echo esc_html__('License Key:', 'slm-plus'); ?></th>
<td><?php echo esc_url($cur_link); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<?php
} }
}


$order = wc_get_order($order_id);
if (!$order) {
return SLM_Helper_Class::write_log("Order not found for ID: $order_id");
}


function wc_slm_on_complete_purchase($order_id) // Check if license creation/renewal has already been processed
{ $license_processed = get_post_meta($order_id, '_slm_license_processed', true);
// Write to the log that the function is being called, useful for debugging. if (!empty($license_processed)) {
//SLM_Helper_Class::write_log('Loading wc_slm_on_complete_purchase for Order ID: ' . intval($order_id)); SLM_Helper_Class::write_log("License creation/renewal already processed for Order ID: {$order_id}");
return;
}


// Check if the essential constants are defined before proceeding. // Handle renewal or new license creation
if (defined('SLM_SITE_HOME_URL') && defined('WOO_SLM_API_SECRET') && SLM_SITE_HOME_URL !== '' && WOO_SLM_API_SECRET !== '') { $renew_license_key = get_post_meta($order_id, '_renew_license_key', true);
// Sanitize the order ID and create license keys.
//SLM_Helper_Class::write_log('startign to create lic for order: ' . intval($order_id));


wc_slm_create_license_keys(absint($order_id)); if (!empty($renew_license_key)) {
// Log and renew license
SLM_Helper_Class::write_log("Processing renewal for License Key: {$renew_license_key}");
wc_slm_renew_license($order);
} else { } else {
//SLM_Helper_Class::write_log('Error, not constants for Order ID: ' . intval($order_id)); // Log and create a new license
SLM_Helper_Class::write_log("Creating a new license for Order ID: {$order_id}");
wc_slm_create_new_license($order);
} }

// Mark the process as completed to prevent duplication
update_post_meta($order_id, '_slm_license_processed', true);
} }


function wc_slm_create_license_keys($order_id)
{
// Write initial log for debugging purposes
//SLM_Helper_Class::write_log('inside wc_slm_create_license_keys for Order ID: ' . intval($order_id));


// Get the order and relevant user details function wc_slm_renew_license($order) {
$order = wc_get_order($order_id); global $wpdb;
if (!$order) {
//SLM_Helper_Class::write_log('Order ID ' . $order_id . ' not found.'); // Retrieve the renew_license_key from order meta
return; // Stop if the order does not exist $renew_license_key = get_post_meta($order->get_id(), '_renew_license_key', true);

if (empty($renew_license_key)) {
return SLM_Helper_Class::write_log("No renew_license_key found for Order ID: " . $order->get_id());
} }


$purchase_id_ = $order->get_id(); // Define the license key table
//SLM_Helper_Class::write_log('Purchase ID: ' . $purchase_id_); $lic_key_table = $wpdb->prefix . 'lic_key_tbl';


global $user_id; // Fetch the license data
$user_id = $order->get_user_id(); $license_data = $wpdb->get_row(
//SLM_Helper_Class::write_log('User ID: ' . $user_id); $wpdb->prepare(

"SELECT * FROM $lic_key_table WHERE license_key = %s LIMIT 1",
if (!$user_id) { $renew_license_key
//SLM_Helper_Class::write_log('User ID not found for Order ID: ' . $order_id); ),
return; // Stop if user ID cannot be found ARRAY_A
}

// Get user details
$user_meta = get_user_meta($user_id);
$payment_meta = array(
'user_info' => array(
'first_name' => isset($user_meta['billing_first_name'][0]) ? sanitize_text_field($user_meta['billing_first_name'][0]) : '',
'last_name' => isset($user_meta['billing_last_name'][0]) ? sanitize_text_field($user_meta['billing_last_name'][0]) : '',
'email' => isset($user_meta['billing_email'][0]) ? sanitize_email($user_meta['billing_email'][0]) : '',
'company' => isset($user_meta['billing_company'][0]) ? sanitize_text_field($user_meta['billing_company'][0]) : ''
)
); );


if (!$license_data) {
return SLM_Helper_Class::write_log("License not found for renewal. Order ID: " . $order->get_id());
}


// Initialize licenses array if ($license_data['lic_status'] === 'blocked') {
$licenses = array(); return SLM_Helper_Class::write_log("Blocked license cannot be renewed. License Key: {$renew_license_key}");
$items = $order->get_items(); }


foreach ($items as $item_key => $values) { // Calculate the new expiration date
$current_expiry_date = $license_data['date_expiry'];
$new_expiration_date = date(
'Y-m-d',
strtotime($current_expiry_date . ' +' . $license_data['slm_billing_length'] . ' ' . $license_data['slm_billing_interval'])
);


$product_id = $values->get_product_id(); // Loop through the order items to get the product ID
$product = $values->get_product(); $product_id = null;
if ($product->is_type('slm_license')) { foreach ($order->get_items() as $item) {
$download_quantity = absint($values->get_quantity()); $product_id = $item->get_product_id(); // Get the product ID
$order_item_lic_keys = $values->get_meta('_slm_lic_key', false); SLM_Helper_Class::write_log("Processing renewal for Product ID: {$product_id}, Order ID: " . $order->get_id());
$lic_to_add = $download_quantity - count($order_item_lic_keys); break; // Only one product ID is needed for a single license renewal
}


// Generate license keys only if necessary // Update the license data
for ($i = 1; $i <= $lic_to_add; $i++) { $updated = $wpdb->update(
$expiration = ''; $lic_key_table,
$renewal_period = wc_slm_get_licensing_renewal_period($product_id); [
$renewal_term = wc_slm_get_licensing_renewal_period_term($product_id); 'date_expiry' => $new_expiration_date,
'lic_status' => 'active',
'date_renewed' => current_time('mysql'),
'wc_order_id' => $order->get_id(),
'txn_id' => $order->get_id(),
'item_reference' => $product_id,
'purchase_id_' => $order->get_id(),
],
['license_key' => $renew_license_key],
['%s', '%s', '%s', '%d', '%d', '%s', '%d'], // Added placeholders for product ID
['%s']
);


// Set expiration date // Debugging: Check if update was successful
if ($renewal_term === 'onetime') { if ($updated === false) {
$expiration = '0000-00-00'; SLM_Helper_Class::write_log("Failed to renew license. License Key: {$renew_license_key}, Order ID: " . $order->get_id());
} else { } else {
$expiration = date('Y-m-d', strtotime('+' . $renewal_period . ' ' . sanitize_text_field($renewal_term))); SLM_Helper_Class::write_log("License renewed successfully. License Key: {$renew_license_key}, Product ID: {$product_id}, Order ID: " . $order->get_id() . ", New Expiration Date: $new_expiration_date.");
}


// Log renewal details // Add the order to the associated orders
//SLM_Helper_Class::write_log('Renewal Period: ' . $renewal_period); $associated_updated = SLM_Utility::slm_add_associated_order($renew_license_key, $order->get_id());
//SLM_Helper_Class::write_log('Expiration Date: ' . $expiration);
//SLM_Helper_Class::write_log('Renewal Term: ' . $renewal_term);

if ($associated_updated) {
// Collect product details SLM_Helper_Class::write_log("Order ID: {$order->get_id()} successfully added to associated orders for License Key: {$renew_license_key}");
$item_data = $values->get_data(); } else {
$product_name = $item_data['name']; SLM_Helper_Class::write_log("Failed to add Order ID: {$order->get_id()} to associated orders for License Key: {$renew_license_key}");
$_license_current_version = get_post_meta($product_id, '_license_current_version', true);
$_license_until_version = get_post_meta($product_id, '_license_until_version', true);
$amount_of_licenses_devices = wc_slm_get_devices_allowed($product_id);
$license_type = get_post_meta($product_id, '_license_type', true);
$lic_item_ref = get_post_meta($product_id, '_license_item_reference', true);
$transaction_id = wc_get_payment_transaction_id($order_id);
$sites_allowed = wc_slm_get_sites_allowed($product_id);

// Prepare API parameters for license creation
$api_params = array(
'slm_action' => 'slm_create_new',
'secret_key' => KEY_API,
'first_name' => $payment_meta['user_info']['first_name'],
'last_name' => $payment_meta['user_info']['last_name'],
'email' => $payment_meta['user_info']['email'],
'company_name' => $payment_meta['user_info']['company'],
'purchase_id_' => $purchase_id_,
'product_ref' => $product_id,
'txn_id' => $transaction_id,
'max_allowed_domains' => $sites_allowed,
'max_allowed_devices' => $amount_of_licenses_devices,
'date_created' => current_time('Y-m-d'),
'date_expiry' => $expiration,
'slm_billing_length' => $renewal_period,
'slm_billing_interval' => $renewal_term,
'until' => $_license_until_version,
'current_ver' => $_license_current_version,
'subscr_id' => $order->get_customer_id(),
'lic_type' => $license_type,
'item_reference' => $lic_item_ref,
);

// Send the request to create a license key
$url = esc_url_raw(SLM_SITE_HOME_URL) . '?' . http_build_query($api_params);

//SLM_Helper_Class::write_log('URL: ' . $url);

$response = wp_safe_remote_get($url, array('timeout' => 20, 'sslverify' => false));
$license_key = wc_slm_get_license_key($response);

// If a license key is generated, save it
if ($license_key) {
$licenses[] = array(
'item' => sanitize_text_field($product_name),
'key' => sanitize_text_field($license_key),
'expires' => $expiration,
'type' => sanitize_text_field($license_type),
'item_ref' => $lic_item_ref,
'slm_billing_length' => $renewal_period,
'slm_billing_interval' => $renewal_term,
'status' => 'pending',
'version' => $_license_current_version,
'until' => $_license_until_version
);

$item_id = $values->get_id();

// Update order meta with license details
$order = wc_get_order($order_id);
if ($order) {
$order->update_meta_data('License Key', sanitize_text_field($license_key));
$order->update_meta_data('License Type', sanitize_text_field($license_type)); // Save the license type
$order->save(); // Save changes to the order
}

// Update order item meta with license details
$order_item = new WC_Order_Item_Product($item_id);
if ($order_item) {
$order_item->update_meta_data('License Key', sanitize_text_field($license_key));
$order_item->update_meta_data('License Type', sanitize_text_field($license_type));
$order_item->update_meta_data('Current Ver.', sanitize_text_field($_license_current_version));
$order_item->update_meta_data('Until Ver.', sanitize_text_field($_license_until_version));
$order_item->update_meta_data('Max Devices', sanitize_text_field($amount_of_licenses_devices));
$order_item->update_meta_data('Max Domains', sanitize_text_field($sites_allowed));
$order_item->save(); // Save changes to the order item
}
}
}
} }
} }
} }


function wc_slm_get_license_key($response) function slm_display_licenses_in_order_details($order) {
{
// Check for error in the response
if (is_wp_error($response)) {
return false;
}

// Retrieve response body
$response_body = wp_remote_retrieve_body($response);

if (empty($response_body)) {
return false; // If response body is empty, return false
}

// Decode JSON while handling potential errors
$decoded_data = json_decode($response_body, true);

if (json_last_error() !== JSON_ERROR_NONE) {
// Handle JSON decoding error appropriately, e.g., log the error
//SLM_Helper_Class::write_log('Failed to decode JSON response: ' . json_last_error_msg());
return false;
}

// Remove invalid control characters from response data (control chars except line feeds, tabs, etc.)
$cleaned_data = preg_replace('/[\x00-\x1F\x7F]/', '', json_encode($decoded_data, JSON_UNESCAPED_UNICODE));

if ($cleaned_data === false) {
// If the cleaning fails, return false
//SLM_Helper_Class::write_log('Failed to clean the JSON response body.');
return false;
}

// Decode cleaned JSON back to PHP associative array
$license_data = json_decode($cleaned_data);

if (!isset($license_data->key)) {
return false; // Key is not set
}

// Return the license key
return $license_data->key;
}

function wc_slm_get_license_id($license)
{
global $wpdb; global $wpdb;


// Prepare the SQL statement to prevent SQL injection // Fetch the WooCommerce order ID
$table_name = $wpdb->prefix . 'lic_key_tbl'; $order_id = $order->get_id();
$query = $wpdb->prepare(
"SELECT ID FROM {$table_name} WHERE license_key = %s ORDER BY id DESC LIMIT 1", // Fetch license keys for this order from the license table
$license $lic_key_table = $wpdb->prefix . 'lic_key_tbl';
$licenses = $wpdb->get_results(
$wpdb->prepare("SELECT license_key, lic_status FROM $lic_key_table WHERE wc_order_id = %d", $order_id),
ARRAY_A
); );


// Fetch the result as an object // If no licenses exist, return
$license_id = $wpdb->get_var($query); if (empty($licenses)) {

// Return the license ID if found, otherwise return false
return $license_id ? intval($license_id) : false;
}

function wc_slm_access_expiration($order_id, $lic_expiry = '')
{
global $wpdb;

// Fetch the WooCommerce order object
$order = wc_get_order($order_id);
if (!$order) {
return; // If the order doesn't exist, return early
}

// Loop through each item in the order
foreach ($order->get_items() as $item_key => $item_details) {
$product_id = $item_details->get_product_id();
$product = wc_get_product($product_id);

// Check if the product is of type 'slm_license'
if ($product && $product->is_type('slm_license')) {

// Get the existing license key attached to the order item
$order_item_lic_key = $item_details->get_meta('_slm_lic_key', true);
if (!empty($order_item_lic_key)) {

// Fetch license data using a custom helper function
$licence = get_licence_by_key($order_item_lic_key);
if (!empty($licence)) {
// Retrieve and format the license expiry date
$lic_expiry = $licence['date_expiry'];
if ($lic_expiry === '0000-00-00') {
$lic_expiry = 'NULL';
} else {
$lic_expiry = $wpdb->prepare('%s', $lic_expiry);
}

// Prepare the SQL query using placeholders
$table_name = $wpdb->prefix . 'woocommerce_downloadable_product_permissions';
$query = $wpdb->prepare(
"UPDATE {$table_name}
SET access_expires = {$lic_expiry}
WHERE order_id = %d AND product_id = %d",
$order_id,
$product_id
);

// Execute the query
$wpdb->query($query);
}
}
}
}

// Optionally, log the query for debugging (commented out by default)
////SLM_Helper_Class::write_log('log:' . $query);
}


/**
* Get License by Key
*
* @param string $licence_key License key to fetch the record for.
* @return array|false Returns license data array if found, false otherwise.
*/
function get_licence_by_key($licence_key)
{
global $wpdb;

// Check if license key is empty and sanitize input
if (empty($licence_key)) {
return false;
}
$licence_key = esc_attr($licence_key);

// Prepare and execute the SQL query
$lic_keys_table = SLM_TBL_LICENSE_KEYS;
$sql_prep = $wpdb->prepare(
"SELECT * FROM {$lic_keys_table} WHERE license_key = %s ORDER BY id DESC LIMIT 1",
$licence_key
);

// Fetch the record and return as an associative array
$record = $wpdb->get_row($sql_prep, ARRAY_A);
return $record ? $record : false;
}


/**
* Get Allowed Number of Sites for a Product
*
* @param int $product_id WooCommerce Product ID.
* @return int|false Returns the number of allowed domains if set, false otherwise.
*/
function wc_slm_get_sites_allowed($product_id)
{
// Get the number of allowed domains for a product
$wc_slm_sites_allowed = absint(get_post_meta($product_id, '_domain_licenses', true));

// Return false if no value is set, otherwise return the value
return !empty($wc_slm_sites_allowed) ? $wc_slm_sites_allowed : false;
}


/**
* Get Number of Allowed Devices
*
* @param int $product_id Product ID.
* @return int|false Number of allowed devices or false if not set.
*/
function wc_slm_get_devices_allowed($product_id)
{
$_devices_licenses = absint(get_post_meta($product_id, '_devices_licenses', true));
return !empty($_devices_licenses) ? $_devices_licenses : false;
}


/**
* Get Licensing Renewal Period
*
* @param int $product_id Product ID.
* @return int Licensing renewal period in days or 0 if not set.
*/
function wc_slm_get_licensing_renewal_period($product_id)
{
$_license_renewal_period_lenght = absint(get_post_meta($product_id, '_license_renewal_period_length', true));
return !empty($_license_renewal_period_lenght) ? $_license_renewal_period_lenght : 0;
}

/**
* Get Licensing Renewal Period Term
*
* @param int $product_id Product ID.
* @return string Renewal period term (e.g., days, months, years) or empty string if not set.
*/
function wc_slm_get_licensing_renewal_period_term($product_id)
{
$term = get_post_meta($product_id, '_license_renewal_period_term', true);
return !empty($term) ? sanitize_text_field($term) : '';
}

/**
* Get Payment Transaction ID
*
* @param int $order_id WooCommerce Order ID.
* @return string|null Transaction ID or null if not found.
*/
function wc_get_payment_transaction_id($order_id)
{
return get_post_meta($order_id, '_transaction_id', true);
}

/**
* Handle Order Completion Actions
*
* @param int $order_id WooCommerce Order ID.
* @return void
*/
function slm_order_completed($order_id)
{
if (!$order_id) {
return; return;
} }


$order = wc_get_order($order_id); // Display licenses
if (!$order) { echo '<h2>' . esc_html__('License Information', 'slm-plus') . '</h2>';
return; echo '<table class="woocommerce-table woocommerce-table--order-details shop_table order_details">
}

$order_billing_email = $order->get_billing_email();

// If billing email is empty, use current user's email
if (empty($order_billing_email)) {
$current_user = wp_get_current_user();
if ($current_user->exists()) {
$order_billing_email = $current_user->user_email;
}
}

// Create the note text
if (!empty($order_billing_email)) {
$note = sprintf(
// Translators: %1$s is the mailto link, %2$s is the plain email address
__("Order confirmation email sent to: <a href='mailto:%1\$s'>%2\$s</a>", 'slm-plus'),
esc_attr($order_billing_email),
esc_html($order_billing_email)
);

// Add the note to the order and save
$order->add_order_note($note);
$order->save();
}
}


/**
* Display License Details on the Order Details Page for Customers
*
* @param WC_Order $order The WooCommerce Order object.
* @return void
*/
function slm_order_details($order)
{
// Get all the items from the order
$items = $order->get_items();
$licences = [];

foreach ($items as $item_key => $item_details) {
$product = $item_details->get_product();
// Check if product is of type 'slm_license'
if ($product->is_type('slm_license')) {
// Retrieve license keys and types from the order item meta
$lic_keys = wc_get_order_item_meta($item_details->get_id(), 'License Key', false);
$lic_types = wc_get_order_item_meta($item_details->get_id(), 'License Type', false);

if ($lic_keys && $lic_types) {
$licenses_data = array_map(function ($keys, $types) {
return [
'lic_key' => sanitize_text_field($keys),
'lic_type' => sanitize_text_field($types),
];
}, $lic_keys, $lic_types);

$licences = array_merge($licences, $licenses_data);
}
}
}

// Display license details if available
if (!empty($licences)) {
echo '
<h2 class="woocommerce-order-details__title">' . esc_html__('License Details', 'slm-plus') . '</h2>
<table class="woocommerce-table woocommerce-table--order-details shop_table order_details">
<thead>
<tr>
<th class="woocommerce-table__product-name product-name">' . esc_html__('License Key', 'slm-plus') . '</th>
<th class="woocommerce-table__product-table product-total">' . esc_html__('Type', 'slm-plus') . '</th>
</tr>
</thead>
<tbody>
';
foreach ($licences as $lic_row) {
echo '
<tr class="woocommerce-table__line-item order_item">
<td class="woocommerce-table__product-name product-name">
' . esc_html($lic_row['lic_key']) . ' -
<a href="' . esc_url(get_permalink(wc_get_page_id('myaccount'))) . 'my-licenses">' . esc_html__('View My Licenses', 'slm-plus') . '</a>
</td>
<td class="woocommerce-table__product-total product-total">
' . esc_html($lic_row['lic_type']) . '
</td>
</tr>
';
}
echo '
</tbody>
</table>
';
}
}
add_action('woocommerce_order_details_after_order_table', 'slm_order_details');


add_action('woocommerce_email_before_order_table', 'slm_add_license_to_order_confirmation', 20, 4);

/**
* Adds license key information to the order confirmation email.
*
* @param WC_Order $order Order object.
* @param bool $sent_to_admin Whether the email is sent to the admin.
* @param bool $plain_text Whether the email is in plain text.
* @param WC_Email $email Email object.
*/
function slm_add_license_to_order_confirmation($order, $sent_to_admin, $plain_text, $email)
{
// Only display the license information in customer completed order emails
if ($email->id !== 'customer_completed_order') {
return;
}

// Fetch the order items
$items = $order->get_items();
$licenses = [];

// Iterate through items to find licenses
foreach ($items as $item_key => $item_details) {
$product = $item_details->get_product();
// Check if the product type is 'slm_license'
if ($product && $product->is_type('slm_license')) {
$meta_data = wc_get_order_item_meta($item_details->get_id(), '_slm_lic_key', false);

// Store license information in an array
foreach ($meta_data as $meta_row) {
$licenses[] = [
'product' => sanitize_text_field($product->get_name()),
'lic_key' => sanitize_text_field($meta_row),
];
}
}
}

// If there are licenses, add them to the email
if (!empty($licenses)) {
?>
<h2><?php echo esc_html__('License Keys', 'slm-plus'); ?></h2>
<table class="td cart_slm slm_licenses_table" cellspacing="0" cellpadding="6" border="1" style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; margin-bottom: 40px;">
<thead> <thead>
<tr> <tr>
<th class="td" colspan="2" scope="col" style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"> <th>' . esc_html__('License Key', 'slm-plus') . '</th>
<?php echo esc_html__('Product', 'slm-plus'); ?> <th>' . esc_html__('Status', 'slm-plus') . '</th>
</th> <th>' . esc_html__('Actions', 'slm-plus') . '</th>
<th class="td" scope="col" style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;">
<?php echo esc_html__('License Key', 'slm-plus'); ?>
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>';
<?php foreach ($licenses as $license) : ?>
<tr> foreach ($licenses as $license) {
<td class="td" style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"> $license_key = esc_html($license['license_key']);
<?php echo esc_html($license['product']); ?> $status = esc_html(ucfirst($license['lic_status']));
</td> $license_url = esc_url(add_query_arg('license_key', $license_key, wc_get_page_permalink('myaccount') . 'my-licenses'));
<td class="td" style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;">
<?php echo esc_html($license['lic_key']); ?> echo "<tr>
</td> <td>$license_key</td>
</tr> <td>$status</td>
<?php endforeach; ?> <td><a href='$license_url'>" . esc_html__('View License', 'slm-plus') . "</a></td>
</tbody> </tr>";
</table>
<br><br>
<?php
} }

echo '</tbody></table>';
}

function wc_slm_create_new_license($order) {
global $wpdb;

// Validate the order object
if (!$order instanceof WC_Order) {
SLM_Helper_Class::write_log("Invalid order object passed.");
return;
}

// Check if a license has already been created for this order
$license_created = get_post_meta($order->get_id(), '_slm_license_created', true);
if (!empty($license_created)) {
SLM_Helper_Class::write_log("License already created for Order ID: {$order->get_id()}");
return;
}

$items = $order->get_items();
$customer_id = $order->get_user_id();
$billing_email = sanitize_email($order->get_billing_email());

// Loop through the order items
foreach ($items as $item_key => $values) {
$product_id = $values->get_product_id();
$product = $values->get_product();

// Skip if product is not a license product
if (!$product->is_type('slm_license')) {
continue;
}

// Retrieve product custom fields
$custom_fields = [
'max_allowed_domains' => intval(get_post_meta($product_id, '_domain_licenses', true)),
'max_allowed_devices' => intval(get_post_meta($product_id, '_devices_licenses', true)),
'slm_billing_interval' => sanitize_text_field(get_post_meta($product_id, '_license_renewal_period_term', true)),
'slm_billing_length' => intval(get_post_meta($product_id, '_license_renewal_period_length', true)),
'current_ver' => sanitize_text_field(get_post_meta($product_id, '_license_current_version', true)),
'until' => sanitize_text_field(get_post_meta($product_id, '_license_until_version', true)),
'lic_type' => sanitize_text_field(get_post_meta($product_id, '_license_type', true)),
'item_reference' => sanitize_text_field(get_post_meta($product_id, '_license_item_reference', true)),
];

// Calculate expiration date
$expiration_date = ($custom_fields['slm_billing_interval'] === 'onetime')
? date('Y-m-d', strtotime('+200 years'))
: date('Y-m-d', strtotime('+' . $custom_fields['slm_billing_length'] . ' ' . $custom_fields['slm_billing_interval']));

// Generate a new license key
$new_license_key = slm_get_license(get_option('slm_license_prefix', 'SLM'));

// Insert the license into the database
$result = $wpdb->insert(
SLM_TBL_LICENSE_KEYS, // Ensure constant is defined for table name
[
'license_key' => $new_license_key,
'max_allowed_domains' => $custom_fields['max_allowed_domains'],
'max_allowed_devices' => $custom_fields['max_allowed_devices'],
'slm_billing_interval' => $custom_fields['slm_billing_interval'],
'slm_billing_length' => $custom_fields['slm_billing_length'],
'current_ver' => $custom_fields['current_ver'],
'until' => $custom_fields['until'],
'lic_type' => $custom_fields['lic_type'],
'item_reference' => $product_id,
'wc_order_id' => $order->get_id(),
'product_ref' => $product_id,
'email' => $billing_email,
'first_name' => sanitize_text_field($order->get_billing_first_name()),
'last_name' => sanitize_text_field($order->get_billing_last_name()),
'date_created' => current_time('mysql'),
'date_expiry' => $expiration_date,
'lic_status' => 'pending',
'purchase_id_' => $order->get_id(),
'txn_id' => $order->get_id(),
'subscr_id' => $customer_id,
]
);

if ($result === false) {
SLM_Helper_Class::write_log("Failed to create license for Product ID: {$product_id} in Order ID: {$order->get_id()}. Error: {$wpdb->last_error}");
continue;
}

// Associate license with WooCommerce order
update_post_meta($order->get_id(), '_slm_license_key', $new_license_key);
update_post_meta($order->get_id(), 'License Key', $new_license_key);

SLM_Helper_Class::write_log("New license key created for Product ID: {$product_id} in Order ID: {$order->get_id()}");
}

// Mark the license as created
update_post_meta($order->get_id(), '_slm_license_created', true);
SLM_Helper_Class::write_log("License creation process completed for Order ID: {$order->get_id()}");
} }

View file

@ -1,9 +1,15 @@
<?php <?php


/**
* Handles SLM License Templates and WooCommerce Overrides
*
* @package SLM_Plus
*/

// Action to load SLM license template on single product pages
add_action('woocommerce_single_product_summary', 'slm_license_template', 60); add_action('woocommerce_single_product_summary', 'slm_license_template', 60);


function slm_license_template() function slm_license_template() {
{
global $product; global $product;


// Ensure $product is a valid WooCommerce product object // Ensure $product is a valid WooCommerce product object
@ -12,29 +18,109 @@ function slm_license_template()
} }


// Get the product type with backward compatibility handling // Get the product type with backward compatibility handling
$product_type = ''; $product_type = method_exists($product, 'get_type') ? $product->get_type() : $product->product_type;
if (method_exists($product, 'get_type')) {
$product_type = $product->get_type();
} else {
$product_type = $product->product_type; // For older versions
}


// Check if the product type is 'slm_license' // Check if the product type is 'slm_license'
if ($product_type === 'slm_license') { if ($product_type === 'slm_license') {
$template_path = SLM_WOO . 'templates/'; $template_path = SLM_WOO;


// Ensure the template path exists, if not fall back to plugin's default template directory // Detect if the request includes a renew_license_key
if (!file_exists($template_path . 'single-product/add-to-cart/slm_license.php')) { $is_renewal = isset($_GET['renew_license_key']) && !empty($_GET['renew_license_key']);
// If template is not found, provide a fallback to default WooCommerce template directory or a custom one $renew_license_key = $is_renewal ? sanitize_text_field($_GET['renew_license_key']) : '';
$template_path = plugin_dir_path(__FILE__) . 'templates/';
}


// Load the template // Pass renewal status and key as variables to the template
wc_get_template( wc_get_template(
'single-product/add-to-cart/slm_license.php', 'single-product/add-to-cart/slm_license.php',
array(), array(
'is_renewal' => $is_renewal,
'renew_license_key' => $renew_license_key,
),
'', '',
trailingslashit($template_path) trailingslashit($template_path)
); );
} }
} }



/**
* Override default WooCommerce templates and template parts from plugin.
*
* E.g.
* Override template 'woocommerce/loop/result-count.php' with 'my-plugin/woocommerce/loop/result-count.php'.
* Override template part 'woocommerce/content-product.php' with 'my-plugin/woocommerce/content-product.php'.
*
* Note: We used folder name 'woocommerce' in plugin to override all woocommerce templates and template parts.
* You can change it as per your requirement.
*/
// Override Template Part's.
add_filter( 'wc_get_template_part', 'slm_override_woocommerce_template_part', 10, 3 );
// Override Template's.
add_filter( 'woocommerce_locate_template', 'slm_override_woocommerce_template', 10, 3 );
/**
* Template Part's
*
* @param string $template Default template file path.
* @param string $slug Template file slug.
* @param string $name Template file name.
* @return string Return the template part from plugin.
*/
function slm_override_woocommerce_template_part( $template, $slug, $name ) {
// UNCOMMENT FOR @DEBUGGING
// echo '<pre>';
// echo 'template: ' . $template . '<br/>';
// echo 'slug: ' . $slug . '<br/>';
// echo 'name: ' . $name . '<br/>';
// echo '</pre>';
// Template directory.
// E.g. /wp-content/plugins/my-plugin/woocommerce/
$template_directory = untrailingslashit( plugin_dir_path( __FILE__ ) ) . 'woocommerce/';
if ( $name ) {
$path = $template_directory . "{$slug}-{$name}.php";
} else {
$path = $template_directory . "{$slug}.php";
}
return file_exists( $path ) ? $path : $template;
}
/**
* Template File
*
* @param string $template Default template file path.
* @param string $template_name Template file name.
* @param string $template_path Template file directory file path.
* @return string Return the template file from plugin.
*/
function slm_override_woocommerce_template( $template, $template_name, $template_path ) {
// UNCOMMENT FOR @DEBUGGING
// echo '<pre>';
// echo 'template: ' . $template . '<br/>';
// echo 'template_name: ' . $template_name . '<br/>';
// echo 'template_path: ' . $template_path . '<br/>';
// echo '</pre>';
// Template directory.
// E.g. /wp-content/plugins/my-plugin/woocommerce/
$template_directory = untrailingslashit( plugin_dir_path( __FILE__ ) ) . 'woocommerce/';
$path = $template_directory . $template_name;
return file_exists( $path ) ? $path : $template;
}



// Load template for the specific page
add_filter('page_template', 'slm_load_license_cart_template');
function slm_load_license_cart_template($page_template) {
if (get_page_template_slug() == 'page-license-cart.php') {
$page_template = SLM_TEMPLATES . 'page-license-cart.php';
}
return $page_template;
}

/**
* Add "License Cart" template to the Page Attributes template dropdown.
*/
add_filter('theme_page_templates', 'slm_add_license_cart_template', 10, 4);
function slm_add_license_cart_template($post_templates, $wp_theme, $post, $post_type) {
// Add the custom template to the dropdown
$post_templates['page-license-cart.php'] = __('License Cart', 'slm-plus');
return $post_templates;
}

View file

@ -383,64 +383,55 @@ function add_slm_properties_meta_box()


function display_slm_properties_meta_box($post) function display_slm_properties_meta_box($post)
{ {
$license_key = get_post_meta($post->ID, 'License Key', true);
$license_type = get_post_meta($post->ID, 'License Type', true); global $wpdb;

$order = wc_get_order($post->ID); $order = wc_get_order($post->ID);
$order_status = $order->get_status(); if (!$order) {

echo '<p><em>' . esc_html__('Order not found.', 'slm-plus') . '</em></p>';
// Check if the license key exists in the database return;
if (empty($license_key)) {
// Retrieve purchase_id and check if license key exists in the license table
$purchase_id = get_post_meta($post->ID, 'purchase_id', true); // Fetch purchase_id meta

if (empty($purchase_id)) {
// If no purchase_id is found, we attempt to retrieve it from the order if possible
$purchase_id = $order->get_id(); // Use order ID if purchase_id isn't set
}

if (!empty($purchase_id)) {
global $wpdb;
// Query the license table to find a matching license
$license_data = $wpdb->get_row($wpdb->prepare(
"SELECT license_key, lic_type FROM " . SLM_TBL_LICENSE_KEYS . " WHERE item_reference = %d",
$purchase_id
));

if ($license_data) {
// Assign the license data to variables
$license_key = $license_data->license_key;
$license_type = $license_data->lic_type;

// Save the purchase_id, license_key, and license_type as metadata
update_post_meta($post->ID, 'purchase_id', $purchase_id);
update_post_meta($post->ID, 'License Key', $license_key);
update_post_meta($post->ID, 'License Type', $license_type);

// Log success for debugging
SLM_Helper_Class::write_log("Purchase ID $purchase_id found. License Key: $license_key, License Type: $license_type saved to order.");
} else {
// Log that no license was found for the given purchase_id
SLM_Helper_Class::write_log("No license found for Purchase ID: $purchase_id.");
}
}
} }


$order_id = $order->get_id();
$order_status = $order->get_status();


// Fetch license details from the database
$license_data = $wpdb->get_row(
$wpdb->prepare(
"SELECT license_key, lic_type FROM " . SLM_TBL_LICENSE_KEYS . " WHERE wc_order_id = %d LIMIT 1",
$order_id
)
);


$license_key = $license_data->license_key ?? '';
$license_type = $license_data->lic_type ?? '';


// Check if license can be created based on order status and license key existence // Determine if a new license can be created based on the order status
$can_create_license = empty($license_key) && in_array($order_status, ['completed', 'processing']); $can_create_license = empty($license_key) && in_array($order_status, ['completed', 'processing']);


// Display license information if a key exists // Display license information if it exists
if (!empty($license_key)) { if (!empty($license_key)) {
echo '<p><strong>' . esc_html__('License Key:', 'slm-plus') . '</strong> ' . esc_html($license_key) . '</p>'; $license_id = $wpdb->get_var(
echo '<p><strong>' . esc_html__('License Type:', 'slm-plus') . '</strong> ' . esc_html($license_type) . '</p>'; $wpdb->prepare(
echo '<p><em>' . esc_html__('A license key is already assigned to this order.', 'slm-plus') . '</em></p>'; "SELECT id FROM " . SLM_TBL_LICENSE_KEYS . " WHERE license_key = %s LIMIT 1",
$license_key
)
);


$license_view_url = esc_url(admin_url('admin.php?page=slm_manage_license&edit_record=' . $license_key)); if ($license_id) {
echo '<a href="' . esc_url($license_view_url) . '" class="button button-secondary" target="_blank">' . esc_html__('View License', 'slm-plus') . '</a>'; echo '<p><strong>' . esc_html__('License Key:', 'slm-plus') . '</strong> ' . esc_html($license_key) . '</p>';
} elseif ($can_create_license) { echo '<p><strong>' . esc_html__('License Type:', 'slm-plus') . '</strong> ' . esc_html($license_type) . '</p>';
// Show the license creation option if no license exists and order is eligible echo '<p><em>' . esc_html__('A license key is already assigned to this order.', 'slm-plus') . '</em></p>';

// Link to view the license using its ID
$license_view_url = esc_url(admin_url('admin.php?page=slm_manage_license&edit_record=' . $license_id));
echo '<a href="' . esc_url($license_view_url) . '" class="button button-secondary" target="_blank">' . esc_html__('View License', 'slm-plus') . '</a>';
} else {
echo '<p><em>' . esc_html__('License information could not be retrieved.', 'slm-plus') . '</em></p>';
}
}
elseif ($can_create_license) {
// Show license creation options for eligible orders
echo '<label for="slm_lic_type">' . esc_html__('License Type:', 'slm-plus') . '</label>'; echo '<label for="slm_lic_type">' . esc_html__('License Type:', 'slm-plus') . '</label>';
echo '<select id="slm_lic_type" name="slm_lic_type" class="postbox"> echo '<select id="slm_lic_type" name="slm_lic_type" class="postbox">
<option value="subscription" ' . selected($license_type, 'subscription', false) . '>' . esc_html__('Subscription', 'slm-plus') . '</option> <option value="subscription" ' . selected($license_type, 'subscription', false) . '>' . esc_html__('Subscription', 'slm-plus') . '</option>
@ -449,7 +440,7 @@ function display_slm_properties_meta_box($post)


echo '<button type="button" class="button button-primary" id="create_license_button">' . esc_html__('Create License', 'slm-plus') . '</button>'; echo '<button type="button" class="button button-primary" id="create_license_button">' . esc_html__('Create License', 'slm-plus') . '</button>';
} else { } else {
// Display informational message for new or ineligible orders // Informational message for ineligible orders
echo '<p><em>' . esc_html__('Order must be completed or processing to create a license.', 'slm-plus') . '</em></p>'; echo '<p><em>' . esc_html__('Order must be completed or processing to create a license.', 'slm-plus') . '</em></p>';
echo '<button type="button" class="button button-primary" id="create_license_button" disabled>' . esc_html__('Create License', 'slm-plus') . '</button>'; echo '<button type="button" class="button button-primary" id="create_license_button" disabled>' . esc_html__('Create License', 'slm-plus') . '</button>';
} }
@ -510,9 +501,11 @@ function display_slm_properties_meta_box($post)
add_action('wp_ajax_slm_generate_license_for_order', 'slm_generate_license_for_order_callback'); add_action('wp_ajax_slm_generate_license_for_order', 'slm_generate_license_for_order_callback');
function slm_generate_license_for_order_callback() function slm_generate_license_for_order_callback()
{ {
// Validate nonce for security
check_ajax_referer('slm_generate_license_nonce', 'security'); check_ajax_referer('slm_generate_license_nonce', 'security');


global $wpdb; global $wpdb;

$order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : null; $order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : null;
$lic_type = isset($_POST['lic_type']) ? sanitize_text_field($_POST['lic_type']) : 'subscription'; $lic_type = isset($_POST['lic_type']) ? sanitize_text_field($_POST['lic_type']) : 'subscription';


@ -520,130 +513,103 @@ function slm_generate_license_for_order_callback()
wp_send_json_error(['message' => __('Invalid order ID', 'slm-plus')]); wp_send_json_error(['message' => __('Invalid order ID', 'slm-plus')]);
} }


// Fetch the WooCommerce order
$order = wc_get_order($order_id); $order = wc_get_order($order_id);

if (!$order || !in_array($order->get_status(), ['completed', 'processing'])) { if (!$order || !in_array($order->get_status(), ['completed', 'processing'])) {
wp_send_json_error(['message' => __('Order must be completed or processing to create a license', 'slm-plus')]); wp_send_json_error(['message' => __('Order must be completed or processing to create a license', 'slm-plus')]);
} }


// Gather required order details // Fetch necessary details from the order
$first_name = $order->get_billing_first_name(); $first_name = $order->get_billing_first_name();
$last_name = $order->get_billing_last_name(); $last_name = $order->get_billing_last_name();
$email = $order->get_billing_email(); $email = $order->get_billing_email();
$purchase_id = $order; $txn_id = $order->get_transaction_id();
$txn_id = $order->get_transaction_id(); $company_name = $order->get_billing_company();
$company_name = $order->get_billing_company(); $date_created = $order->get_date_created() ? $order->get_date_created()->date('Y-m-d') : current_time('mysql');
$date_created = $order->get_date_created()->date('Y-m-d'); $user_id = $order->get_user_id();
$user_id = $order->get_user_id();
// Get the first item from the order (if available)
$order_items = $order->get_items();
$product_ref = !empty($order_items) ? reset($order_items)->get_name() : ''; // Using the first item name for simplicity


// Default values from options
$slm_billing_length = SLM_API_Utility::get_slm_option('slm_billing_length');
$slm_billing_interval = SLM_API_Utility::get_slm_option('slm_billing_interval');
$default_domains = SLM_DEFAULT_MAX_DOMAINS;
$default_devices = SLM_DEFAULT_MAX_DEVICES;


$slm_billing_length = SLM_API_Utility::get_slm_option('slm_billing_length'); // Determine expiration date
$slm_billing_interval = SLM_API_Utility::get_slm_option('slm_billing_interval'); $date_expiry = $lic_type === 'lifetime'
? date('Y-m-d', strtotime('+120 years', strtotime($date_created)))
: date('Y-m-d', strtotime("+$slm_billing_length $slm_billing_interval", strtotime($date_created)));


$date_expiry = $lic_type === 'lifetime' ? date('Y-m-d', strtotime("+120 years", strtotime($date_created))) : $licenses = [];
date('Y-m-d', strtotime("+$slm_billing_length $slm_billing_interval", strtotime($date_created))); foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$product = wc_get_product($product_id);


// License data array, using all fields from original if ($product && $product->is_type('slm_license')) {
$license_data = [ // Fetch custom fields for the license
'slm_action' => 'slm_create_new', $product_data = [
'lic_status' => 'pending', 'current_ver' => get_post_meta($product_id, '_license_current_version', true),
'lic_type' => $lic_type, 'until_ver' => get_post_meta($product_id, '_license_until_version', true),
'first_name' => $first_name, 'max_devices' => get_post_meta($product_id, '_devices_licenses', true) ?: $default_devices,
'last_name' => $last_name, 'max_domains' => get_post_meta($product_id, '_domain_licenses', true) ?: $default_domains,
'email' => $email, 'item_reference' => get_post_meta($product_id, '_license_item_reference', true),
'purchase_id' => $purchase_id, ];
'txn_id' => $txn_id,
'company_name' => $company_name,
'max_allowed_domains' => SLM_DEFAULT_MAX_DOMAINS,
'max_allowed_devices' => SLM_DEFAULT_MAX_DEVICES,
'date_created' => $date_created,
'date_expiry' => $date_expiry,
'product_ref' => $product_ref,
'current_ver' => SLM_API_Utility::get_slm_option('license_current_version'),
'until' => SLM_API_Utility::get_slm_option('license_until_version'),
'subscr_id' => $user_id,
'item_reference' => $order_id,
'slm_billing_length' => $slm_billing_length,
'slm_billing_interval' => $slm_billing_interval,
'secret_key' => KEY_API
];


$response = wp_remote_post(SLM_API_URL, [ // Generate a new license key
'method' => 'POST', $new_license_key = slm_get_license(KEY_API_PREFIX);
'body' => $license_data,
'timeout' => 45,
'sslverify' => false,
]);


if (is_wp_error($response)) { // Insert the new license into the database
wp_send_json_error(['message' => __('API request failed', 'slm-plus')]); $wpdb->insert(SLM_TBL_LICENSE_KEYS, [
'license_key' => $new_license_key,
'wc_order_id' => $order_id,
'product_ref' => $product_id,
'txn_id' => $order_id,
'purchase_id_' => $order_id,
'subscr_id' => $user_id,
'item_reference' => $product_data['item_reference'],
'max_allowed_domains' => intval($product_data['max_domains']),
'max_allowed_devices' => intval($product_data['max_devices']),
'date_created' => $date_created,
'date_expiry' => $date_expiry,
'slm_billing_length' => intval($slm_billing_length),
'slm_billing_interval' => sanitize_text_field($slm_billing_interval),
'current_ver' => sanitize_text_field($product_data['current_ver']),
'until' => sanitize_text_field($product_data['until_ver']),
'lic_type' => sanitize_text_field($lic_type),
'email' => sanitize_email($email),
'first_name' => sanitize_text_field($first_name),
'last_name' => sanitize_text_field($last_name),
'company_name' => sanitize_text_field($company_name),
'lic_status' => 'pending',
]);

// Add the license key to the order note
$order->add_order_note(sprintf(__('License Key generated: %s', 'slm-plus'), $new_license_key));
// Collect license info for the response
$licenses[] = [
'license_key' => $new_license_key,
'product_name' => $product->get_name(),
];
}
} }


$body = wp_remote_retrieve_body($response); // Save the order after updating
$api_response = json_decode($body, true); $order->save();


if ($api_response && isset($api_response['result']) && $api_response['result'] === 'success') { // Send success response with license information

if (!empty($licenses)) {
$license_key = sanitize_text_field($api_response['key']); wp_send_json_success([
$_license_current_version = SLM_API_Utility::get_slm_option('license_current_version'); 'message' => __('License created successfully', 'slm-plus'),
$_license_until_version = SLM_API_Utility::get_slm_option('license_until_version'); 'licenses' => $licenses,
$amount_of_licenses_devices = SLM_DEFAULT_MAX_DEVICES; ]);
$sites_allowed = SLM_DEFAULT_MAX_DOMAINS;

// Add an order note
$order->add_order_note(
// Translators: %s is the license key generated for the order
sprintf(__('License Key generated: %s', 'slm-plus'), $license_key)
);

// Update order item meta with the license key for each item in the order
foreach ($order->get_items() as $item_id => $item) {
// Sanitize the license key and license type
$license_key = sanitize_text_field($license_key);
$_license_current_version = sanitize_text_field($_license_current_version);
$_license_until_version = sanitize_text_field($_license_until_version);
$amount_of_licenses_devices = sanitize_text_field($amount_of_licenses_devices);
$sites_allowed = sanitize_text_field($sites_allowed);

// Ensure the item is a valid order item
if ($item instanceof WC_Order_Item) {
// Set the license key and license type metadata for the item
wc_add_order_item_meta($item, 'License Key', $license_key, true);
wc_add_order_item_meta($item, 'License Type', 'subscription', true);

$item->update_meta_data('License Key', sanitize_text_field($license_key));
$item->update_meta_data('License Type', 'subscription');
$item->update_meta_data('Current Ver.', sanitize_text_field($_license_current_version));
$item->update_meta_data('Until Ver.', sanitize_text_field($_license_until_version));
$item->update_meta_data('Max Devices', sanitize_text_field($amount_of_licenses_devices));
$item->update_meta_data('Max Domains', sanitize_text_field($sites_allowed));

// Save the item metadata
$item->save(); // Save the item to persist the metadata
}
}

// Save the order after updating the items
$order->save(); // This saves the order and ensures the changes are committed


// Optionally, log the order save for debugging
SLM_Helper_Class::write_log("Order $order_id saved with updated license information.");


// Send success response
wp_send_json_success(['message' => __('License created successfully', 'slm-plus')]);
} else { } else {
wp_send_json_error(['message' => __('License creation failed', 'slm-plus')]); wp_send_json_error(['message' => __('No licenses were generated', 'slm-plus')]);
} }
} }



add_action('wp_ajax_check_order_user_info', 'check_order_user_info_callback'); add_action('wp_ajax_check_order_user_info', 'check_order_user_info_callback');
function check_order_user_info_callback() function check_order_user_info_callback(){
{
check_ajax_referer('slm_generate_license_nonce', 'security'); check_ajax_referer('slm_generate_license_nonce', 'security');


$order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : null; $order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : null;
@ -656,7 +622,8 @@ function check_order_user_info_callback()
$last_name = $order->get_billing_last_name(); $last_name = $order->get_billing_last_name();
$email = $order->get_billing_email(); $email = $order->get_billing_email();
wp_send_json_success(['last_name' => $last_name, 'email' => $email]); wp_send_json_success(['last_name' => $last_name, 'email' => $email]);
} else { }
else {
wp_send_json_error(['message' => __('Order not found', 'slm-plus')]); wp_send_json_error(['message' => __('Order not found', 'slm-plus')]);
} }
} }

View file

@ -1,56 +0,0 @@
<?php
/**
* Simple product add to cart
*
* This template can be overridden by copying it to yourtheme/woocommerce/single-product/add-to-cart/simple.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://woocommerce.com/document/template-structure/
* @package WooCommerce\Templates
* @version 7.0.1
*/

defined( 'ABSPATH' ) || exit;

global $product;

if ( ! $product->is_purchasable() ) {
return;
}

echo wc_get_stock_html( $product ); // WPCS: XSS ok.

if ( $product->is_in_stock() ) : ?>

<?php do_action( 'woocommerce_before_add_to_cart_form' ); ?>

<form class="cart" action="<?php echo esc_url( apply_filters( 'woocommerce_add_to_cart_form_action', $product->get_permalink() ) ); ?>" method="post" enctype='multipart/form-data'>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>

<?php
do_action( 'woocommerce_before_add_to_cart_quantity' );

woocommerce_quantity_input(
array(
'min_value' => apply_filters( 'woocommerce_quantity_input_min', $product->get_min_purchase_quantity(), $product ),
'max_value' => apply_filters( 'woocommerce_quantity_input_max', $product->get_max_purchase_quantity(), $product ),
'input_value' => isset( $_POST['quantity'] ) ? wc_stock_amount( wp_unslash( $_POST['quantity'] ) ) : $product->get_min_purchase_quantity(), // WPCS: CSRF ok, input var ok.
)
);

do_action( 'woocommerce_after_add_to_cart_quantity' );
?>

<button type="submit" name="add-to-cart" value="<?php echo esc_attr( $product->get_id() ); ?>" class="single_add_to_cart_button button alt<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>

<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
</form>

<?php do_action( 'woocommerce_after_add_to_cart_form' ); ?>

<?php endif; ?>

View file

@ -36,7 +36,7 @@ if ($enable_downloads_page == 1) {
} }




// Step 1: Register the endpoint and add it to WooCommerces query vars // Register the endpoint and add it to WooCommerces query vars
add_filter('woocommerce_get_query_vars', function($query_vars) { add_filter('woocommerce_get_query_vars', function($query_vars) {
$query_vars['my-licenses'] = 'my-licenses'; $query_vars['my-licenses'] = 'my-licenses';
return $query_vars; return $query_vars;
@ -48,7 +48,7 @@ function slm_flush_rewrite_rules() {
} }
register_activation_hook(__FILE__, 'slm_flush_rewrite_rules'); register_activation_hook(__FILE__, 'slm_flush_rewrite_rules');


// Step 2: Add the My Licenses link to WooCommerce account menu //Add the My Licenses link to WooCommerce account menu
function slm_add_my_licenses_endpoint($items) { function slm_add_my_licenses_endpoint($items) {
if (SLM_API_Utility::get_slm_option('slm_woo')) { if (SLM_API_Utility::get_slm_option('slm_woo')) {
// Add "My Licenses" item just before "Log out" // Add "My Licenses" item just before "Log out"
@ -66,7 +66,7 @@ function slm_add_my_licenses_endpoint($items) {
} }
add_filter('woocommerce_account_menu_items', 'slm_add_my_licenses_endpoint'); add_filter('woocommerce_account_menu_items', 'slm_add_my_licenses_endpoint');


// Step 3: Display content based on endpoint value //Display content based on endpoint value
add_action('woocommerce_account_my-licenses_endpoint', function($value) { add_action('woocommerce_account_my-licenses_endpoint', function($value) {


//SLM_Helper_Class::write_log('slm_add_my_licenses_endpoint loaded'); //SLM_Helper_Class::write_log('slm_add_my_licenses_endpoint loaded');
@ -90,7 +90,7 @@ add_action('woocommerce_account_my-licenses_endpoint', function($value) {
} }
}); });


// Step 4: Display the main licenses table //Display the main licenses table
function slm_display_license_table() { function slm_display_license_table() {


//SLM_Helper_Class::write_log('slm_display_license_table loaded'); //SLM_Helper_Class::write_log('slm_display_license_table loaded');
@ -162,7 +162,124 @@ function slm_display_license_table() {
} }


//SLM_Helper_Class::write_log('file loaded');
add_action('wp_loaded', function () {
if (isset($_GET['renew_license']) && isset($_GET['product_id'])) {
// Sanitize inputs
$license_key = sanitize_text_field($_GET['renew_license']);
$product_id = absint($_GET['product_id']);

// Validate and process
if (!empty($license_key) && !empty($product_id)) {
slm_direct_renew_and_redirect($license_key, $product_id);
}
}
});



function slm_direct_renew_and_redirect($license_key, $product_id) {
// Ensure WooCommerce is loaded
if (!function_exists('wc_get_product')) {
error_log('WooCommerce is not loaded. Cannot process renewal.');
return;
}

// Prevent redirection loops by checking a custom flag
if (isset($_GET['redirected']) && $_GET['redirected'] === 'true') {
return; // Skip processing if already redirected
}

// Validate inputs
if (empty($license_key) || empty($product_id)) {
wc_add_notice(__('Invalid license or product.', 'slm-plus'), 'error');
return;
}

// Safely retrieve the product
$product = wc_get_product($product_id);
if (!$product || !$product->is_type('simple')) {
wc_add_notice(__('Invalid product for renewal.', 'slm-plus'), 'error');
return;
}

// Delay cart operations
add_action('woocommerce_cart_loaded_from_session', function () use ($license_key, $product_id) {
$cart_item_data = [
'renew_license_key' => sanitize_text_field($license_key), // Attach the license key
];
$added_to_cart = WC()->cart->add_to_cart($product_id, 1, 0, [], $cart_item_data);

if (!$added_to_cart) {
wc_add_notice(__('Failed to add product to cart.', 'slm-plus'), 'error');
return;
}

// Build the redirect URL with a 'redirected' flag
$redirect_url = add_query_arg([
'renew_license' => $license_key,
'product_id' => $product_id,
'add-to-cart' => $product_id,
'redirected' => 'true', // Add the flag to prevent loops
], site_url('/license-cart')); // Update to your cart URL

// Redirect to the custom cart page
wp_safe_redirect($redirect_url);
exit;
});
}

add_action('woocommerce_before_cart', function() {
WC()->cart->get_cart_contents_count(); // Total cart items
error_log(print_r(WC()->cart->get_cart(), true)); // Logs all cart items
});






// Example usage with enhanced safety checks
// Example usage with enhanced safety checks
add_action('init', function () {
if (isset($_GET['renew_license']) && isset($_GET['product_id'])) {
// Ensure WooCommerce is active
if (!function_exists('wc_get_product')) {
if (!is_plugin_active('woocommerce/woocommerce.php')) {
error_log('WooCommerce is not active. Please enable it to use the SLM Plus plugin.');
return;
}
}

// Sanitize input values
$license_key = sanitize_text_field($_GET['renew_license']);
$product_id = absint($_GET['product_id']);

// Validate required values
if (!empty($license_key) && !empty($product_id)) {
// Start WooCommerce session if not already initialized
if (!WC()->session) {
WC()->initialize_session_handler();
WC()->session = new WC_Session_Handler();
WC()->session->init();
error_log('WooCommerce session initialized.');
}

// Store license key in session for later use in checkout
WC()->session->set('renew_license_key', $license_key);

// Log for debugging
SLM_Helper_Class::write_log("Renew license key set in session during redirect: {$license_key}");

// Redirect or process renewal
slm_direct_renew_and_redirect($license_key, $product_id);
} else {
error_log('Missing or invalid license key or product ID for renewal.');
}
}
});




// Step 5: Display individual license details // Step 5: Display individual license details
function slm_license_view($encoded_license_id) { function slm_license_view($encoded_license_id) {
@ -220,8 +337,9 @@ function slm_license_view($encoded_license_id) {
'date_expiry' => __('Date Expiry', 'slm-plus'), 'date_expiry' => __('Date Expiry', 'slm-plus'),
'product_ref' => __('Product Reference', 'slm-plus'), 'product_ref' => __('Product Reference', 'slm-plus'),
'subscr_id' => __('Subscription ID', 'slm-plus'), 'subscr_id' => __('Subscription ID', 'slm-plus'),
'subscr_id' => __('Subscription ID', 'slm-plus'),
'max_allowed_domains' => __('Max Allowed Domains', 'slm-plus'), 'max_allowed_domains' => __('Max Allowed Domains', 'slm-plus'),
'max_allowed_devices' => __('Max Allowed Devices', 'slm-plus'), 'associated_orders' => __('Associated Orders', 'slm-plus'),
'company_name' => __('Company Name', 'slm-plus'), 'company_name' => __('Company Name', 'slm-plus'),
]; ];


@ -235,6 +353,7 @@ function slm_license_view($encoded_license_id) {
// Check if the field is set and get the value // Check if the field is set and get the value
$field_value = isset($license->$field_key) ? esc_html($license->$field_key) : ''; $field_value = isset($license->$field_key) ? esc_html($license->$field_key) : '';



// Special handling for purchase_id_ to link to the order // Special handling for purchase_id_ to link to the order
if ($field_key === 'purchase_id_') { if ($field_key === 'purchase_id_') {
if (!empty($field_value)) { if (!empty($field_value)) {
@ -246,6 +365,103 @@ function slm_license_view($encoded_license_id) {
} }
} }



if ($field_key === 'associated_orders') {
if (!empty($field_value)) {
// Fetch the associated orders using the provided function
$associated_orders = SLM_Utility::slm_get_associated_orders($license->license_key);
// Debugging: Log the retrieved value
SLM_Helper_Class::write_log('Associated Orders Raw Data: ' . print_r($associated_orders, true));
if (!empty($associated_orders) && is_array($associated_orders)) {
$links = [];
foreach ($associated_orders as $order_id) {
// Generate a link to the WooCommerce account orders page
$order_url = wc_get_endpoint_url('view-order', $order_id, wc_get_page_permalink('myaccount'));
$links[] = sprintf(
'<a href="%s">#%s</a>',
esc_url($order_url), // Sanitize the URL
esc_html($order_id) // Escape and sanitize the order ID
);
}
// Join all links with a comma for display
$field_value = implode(', ', $links);
} else {
$field_value = __('No Associated Orders Found (Data Issue)', 'slm-plus');
}
} else {
$field_value = __('No Order Information Available', 'slm-plus');
}
}

if ($field_key === 'lic_status') {
$license_key = isset($license->license_key) ? esc_html($license->license_key) : '';
$purchase_id = isset($license->purchase_id_) ? absint($license->purchase_id_) : 0;
// Ensure date_expiry is checked safely
$expiration_date = isset($license->date_expiry) ? strtotime($license->date_expiry) : false;
// Determine if the license is expired
$is_expired = (!empty($expiration_date) && $expiration_date < time()) || $license->lic_status === 'expired';
if ($is_expired && !empty($license_key) && !empty($purchase_id)) {
$product_id = 0; // Initialize product_id
// Ensure WooCommerce functions are available
if (!function_exists('wc_get_order')) {
// Include WooCommerce files to make functions accessible
if (defined('WC_ABSPATH')) {
include_once WC_ABSPATH . 'includes/wc-order-functions.php';
include_once WC_ABSPATH . 'includes/wc-product-functions.php';
} else {
// If WooCommerce is not loaded, skip further processing
$field_value = sprintf(
'<span class="status-expired">%s</span> <span class="warning">%s</span>',
__('Expired', 'slm-plus'),
__('WooCommerce not loaded.', 'slm-plus')
);
return;
}
}
// Retrieve the product ID associated with the license
$order = wc_get_order($purchase_id);
// Ensure order is valid and contains items
if ($order) {
$items = $order->get_items();
$product_id = $items ? current($items)->get_product_id() : 0;
}
if (!empty($product_id)) {
// Generate the renewal URL
$renew_url = add_query_arg([
'renew_license' => $license_key,
'product_id' => $product_id,
], site_url('/my-account/my-licenses'));
// Update field value to include Renew button
$field_value = sprintf(
'<span class="status-expired">%s</span> <a href="%s" class="button renew-button">%s</a>',
__('Expired', 'slm-plus'),
esc_url($renew_url),
__('Renew', 'slm-plus')
);
} else {
// Handle missing product ID case (e.g., display a warning)
$field_value = sprintf(
'<span class="status-expired">%s</span> <span class="warning">%s</span>',
__('Expired', 'slm-plus'),
__('Product not found for renewal.', 'slm-plus')
);
}
}
}

// Special handling for product_ref to link to the product page // Special handling for product_ref to link to the product page
if ($field_key === 'product_ref') { if ($field_key === 'product_ref') {
if (!empty($field_value)) { if (!empty($field_value)) {
@ -256,7 +472,12 @@ function slm_license_view($encoded_license_id) {


if ($product_url && $product_name) { if ($product_url && $product_name) {
// Format as "#ID - ProductName" // Format as "#ID - ProductName"
$field_value = '<a href="' . esc_url($product_url) . '">#' . esc_html($product_id) . ' - ' . esc_html($product_name) . '</a>'; $field_value = sprintf(
'<a href="%s">#%s - %s</a>',
esc_url($product_url), // Sanitize the URL
esc_html($product_id), // Escape and sanitize the product ID
esc_html($product_name) // Escape and sanitize the product name
);
} else { } else {
$field_value = __('Product Not Found', 'slm-plus'); $field_value = __('Product Not Found', 'slm-plus');
} }
@ -270,7 +491,7 @@ function slm_license_view($encoded_license_id) {
$field_value = ($field_key === 'date_activated') ? __('Not activated yet', 'slm-plus') : __('Not renewed yet', 'slm-plus'); $field_value = ($field_key === 'date_activated') ? __('Not activated yet', 'slm-plus') : __('Not renewed yet', 'slm-plus');
} }


echo '<tr><th>' . esc_html($field_label) . '</th><td>' . esc_html($field_value) . '</td></tr>'; echo '<tr><th>' . esc_html($field_label) . '</th><td>' . $field_value . '</td></tr>';
} }
echo '</tbody>'; echo '</tbody>';
echo '</table>'; echo '</table>';

View file

@ -0,0 +1,63 @@
<?php
/**
* Simple product add to cart
* Template for handling SLM licenses (renewals and new).
*/

defined('ABSPATH') || exit;

global $product;

if (!$product->is_purchasable()) {
return;
}

echo wc_get_stock_html($product); // Display stock status if applicable.

if ($product->is_in_stock()) :
// Determine if this is a renewal (renew_license_key present in URL).
$is_renewal = isset($_GET['renew_license_key']) && !empty($_GET['renew_license_key']);
$renew_license_key = $is_renewal ? sanitize_text_field($_GET['renew_license_key']) : '';
?>

<?php do_action('woocommerce_before_add_to_cart_form'); ?>

<form class="cart" action="<?php echo esc_url(apply_filters('woocommerce_add_to_cart_form_action', $product->get_permalink())); ?>" method="post" enctype='multipart/form-data'>
<?php do_action('woocommerce_before_add_to_cart_button'); ?>

<div class="license-product-details">
<?php if ($is_renewal) : ?>
<!-- Display renewal information -->
<p class="license-renewal-info">
<?php echo esc_html__('You are renewing the license for:', 'slm-plus'); ?>
<strong><?php echo esc_html($renew_license_key); ?></strong>
</p>
<!-- Add hidden field for renew_license_key -->
<input type="hidden" name="renew_license_key" value="<?php echo esc_attr($renew_license_key); ?>">
<input type="hidden" name="quantity" value="1">
<?php else : ?>
<!-- Display quantity input for new licenses -->
<?php
do_action('woocommerce_before_add_to_cart_quantity');
woocommerce_quantity_input(
array(
'min_value' => apply_filters('woocommerce_quantity_input_min', $product->get_min_purchase_quantity(), $product),
'max_value' => apply_filters('woocommerce_quantity_input_max', $product->get_max_purchase_quantity(), $product),
'input_value' => isset($_POST['quantity']) ? wc_stock_amount(wp_unslash($_POST['quantity'])) : $product->get_min_purchase_quantity(), // CSRF ok.
)
);
do_action('woocommerce_after_add_to_cart_quantity');
?>
<?php endif; ?>
</div>

<button type="submit" name="add-to-cart" value="<?php echo esc_attr($product->get_id()); ?>" class="single_add_to_cart_button button alt<?php echo esc_attr(wc_wp_theme_get_element_class_name('button') ? ' ' . wc_wp_theme_get_element_class_name('button') : ''); ?>">
<?php echo esc_html($is_renewal ? __('Renew License', 'slm-plus') : $product->single_add_to_cart_text()); ?>
</button>

<?php do_action('woocommerce_after_add_to_cart_button'); ?>
</form>

<?php do_action('woocommerce_after_add_to_cart_form'); ?>

<?php endif; ?>