prefix . 'woonoow_licenses'; // Check if table exists if ($wpdb->get_var("SHOW TABLES LIKE '$table'") !== $table) { LicenseManager::create_tables(); } } /** * Handle module enable */ public static function on_module_enabled($module_id) { if ($module_id === 'licensing') { LicenseManager::create_tables(); } } /** * Register license connect rewrite endpoint */ public static function register_license_connect_endpoint() { add_rewrite_endpoint('license-connect', EP_ROOT | EP_PAGES); } /** * Handle license-connect endpoint (OAuth confirmation page) */ public static function handle_license_connect() { // Parse the request URI to check if this is the license-connect page $request_uri = $_SERVER['REQUEST_URI'] ?? ''; $parsed_path = parse_url($request_uri, PHP_URL_PATH); // Check if path contains license-connect if (strpos($parsed_path, '/license-connect') === false) { return; } // Get parameters $license_key = sanitize_text_field($_GET['license_key'] ?? ''); $site_url = esc_url_raw($_GET['site_url'] ?? ''); $return_url = esc_url_raw($_GET['return_url'] ?? ''); $state = sanitize_text_field($_GET['state'] ?? ''); $action = sanitize_text_field($_GET['action'] ?? ''); // Handle form submission (confirmation) if ($action === 'confirm' && !empty($_POST['confirm_license'])) { self::process_license_confirmation(); return; } // Require login if (!is_user_logged_in()) { $login_url = wp_login_url(add_query_arg($_GET, home_url('/my-account/license-connect/'))); wp_redirect($login_url); exit; } // Validate parameters if (empty($license_key) || empty($site_url) || empty($state)) { self::render_license_connect_page([ 'error' => __('Invalid license connection request. Missing required parameters.', 'woonoow'), ]); return; } // Verify state token $state_data = LicenseManager::verify_oauth_state($state); if (!$state_data) { self::render_license_connect_page([ 'error' => __('Invalid or expired connection request. Please try again.', 'woonoow'), ]); return; } // Get license and verify ownership $license = LicenseManager::get_license_by_key($license_key); if (!$license) { self::render_license_connect_page([ 'error' => __('License key not found.', 'woonoow'), ]); return; } // Verify license belongs to current user $current_user_id = get_current_user_id(); if ((int)$license['user_id'] !== $current_user_id) { self::render_license_connect_page([ 'error' => __('This license does not belong to your account.', 'woonoow'), ]); return; } // Check license status if ($license['status'] !== 'active') { self::render_license_connect_page([ 'error' => __('This license is not active.', 'woonoow'), ]); return; } // Check activation limit if ($license['activation_limit'] > 0 && $license['activation_count'] >= $license['activation_limit']) { self::render_license_connect_page([ 'error' => sprintf( __('Activation limit reached (%d/%d sites).', 'woonoow'), $license['activation_count'], $license['activation_limit'] ), ]); return; } // Get product info $product = wc_get_product($license['product_id']); $product_name = $product ? $product->get_name() : __('Unknown Product', 'woonoow'); // Render confirmation page self::render_license_connect_page([ 'license' => $license, 'product_name' => $product_name, 'site_url' => $site_url, 'return_url' => $return_url, 'state' => $state, ]); } /** * Process license confirmation form submission */ private static function process_license_confirmation() { if (!is_user_logged_in()) { wp_die(__('You must be logged in.', 'woonoow')); } // Verify nonce if (!wp_verify_nonce($_POST['_wpnonce'] ?? '', 'woonoow_license_connect')) { wp_die(__('Security check failed.', 'woonoow')); } $license_key = sanitize_text_field($_POST['license_key'] ?? ''); $site_url = esc_url_raw($_POST['site_url'] ?? ''); $return_url = esc_url_raw($_POST['return_url'] ?? ''); $state = sanitize_text_field($_POST['state'] ?? ''); // Verify state $state_data = LicenseManager::verify_oauth_state($state); if (!$state_data) { wp_die(__('Invalid or expired request.', 'woonoow')); } // Get and verify license $license = LicenseManager::get_license_by_key($license_key); if (!$license || (int)$license['user_id'] !== get_current_user_id()) { wp_die(__('Invalid license.', 'woonoow')); } // Generate activation token $token_data = LicenseManager::generate_activation_token($license['id'], $site_url); // Build return URL with token $callback_url = add_query_arg([ 'activation_token' => $token_data['token'], 'license_key' => $license_key, 'state' => $state, ], $return_url); // Redirect back to client site wp_redirect($callback_url); exit; } /** * Render license connect confirmation page */ private static function render_license_connect_page($args) { // Set headers status_header(200); nocache_headers(); // Include WP header get_header('woonoow'); echo '
'; if (!empty($args['error'])) { echo '
'; echo '' . esc_html__('Error', 'woonoow') . ': ' . esc_html($args['error']); echo '
'; echo '← ' . esc_html__('Return Home', 'woonoow') . ''; } else { $license = $args['license']; $activations_remaining = $license['activation_limit'] > 0 ? $license['activation_limit'] - $license['activation_count'] : '∞'; echo '

' . esc_html__('Connect Site to License', 'woonoow') . '

'; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
' . esc_html__('Site', 'woonoow') . ':' . esc_html($args['site_url']) . '
' . esc_html__('Product', 'woonoow') . ':' . esc_html($args['product_name']) . '
' . esc_html__('License', 'woonoow') . ':' . esc_html($license['license_key']) . '
' . esc_html__('Activations', 'woonoow') . ':' . esc_html($license['activation_count']) . '/' . ($license['activation_limit'] ?: '∞') . ' ' . esc_html__('used', 'woonoow') . '
'; echo '
'; echo '
'; echo wp_nonce_field('woonoow_license_connect', '_wpnonce', true, false); echo ''; echo ''; echo ''; echo ''; echo '
'; echo ''; echo ''; echo esc_html__('Cancel', 'woonoow'); echo ''; echo '
'; echo '
'; } echo '
'; get_footer('woonoow'); exit; } /** * Add licensing fields to product edit page */ public static function add_product_licensing_fields() { global $post; if (!ModuleRegistry::is_enabled('licensing')) { return; } echo '
'; woocommerce_wp_checkbox([ 'id' => '_woonoow_licensing_enabled', 'label' => __('Enable Licensing', 'woonoow'), 'description' => __('Generate license keys for this product on purchase', 'woonoow'), ]); woocommerce_wp_text_input([ 'id' => '_woonoow_license_activation_limit', 'label' => __('Activation Limit', 'woonoow'), 'description' => __('Max activations per license (0 = use default, leave empty for unlimited)', 'woonoow'), 'type' => 'number', 'custom_attributes' => [ 'min' => '0', 'step' => '1', ], ]); woocommerce_wp_text_input([ 'id' => '_woonoow_license_expiry_days', 'label' => __('License Expiry (Days)', 'woonoow'), 'description' => __('Days until license expires (0 = never expires)', 'woonoow'), 'type' => 'number', 'custom_attributes' => [ 'min' => '0', 'step' => '1', ], ]); // Only show activation method if per-product override is enabled $licensing_settings = get_option('woonoow_module_licensing_settings', []); $allow_override = $licensing_settings['allow_product_override'] ?? false; if ($allow_override) { woocommerce_wp_select([ 'id' => '_woonoow_license_activation_method', 'label' => __('Activation Method', 'woonoow'), 'description' => __('Override site-level setting for this product', 'woonoow'), 'options' => [ '' => __('Use Site Default', 'woonoow'), 'api' => __('Simple API (license key only)', 'woonoow'), 'oauth' => __('Secure OAuth (requires account login)', 'woonoow'), ], ]); } echo '
'; } /** * Save licensing fields */ public static function save_product_licensing_fields($post_id) { $licensing_enabled = isset($_POST['_woonoow_licensing_enabled']) ? 'yes' : 'no'; update_post_meta($post_id, '_woonoow_licensing_enabled', $licensing_enabled); if (isset($_POST['_woonoow_license_activation_limit'])) { update_post_meta($post_id, '_woonoow_license_activation_limit', absint($_POST['_woonoow_license_activation_limit'])); } if (isset($_POST['_woonoow_license_expiry_days'])) { update_post_meta($post_id, '_woonoow_license_expiry_days', absint($_POST['_woonoow_license_expiry_days'])); } if (isset($_POST['_woonoow_license_activation_method'])) { $method = $_POST['_woonoow_license_activation_method']; // Accept empty (site default), api, or oauth if ($method === '' || in_array($method, ['api', 'oauth'])) { update_post_meta($post_id, '_woonoow_license_activation_method', sanitize_key($method)); } } } }