Documentation v1.4.0

Welcome to OXYLicenser

OXYLicenser is a premium, SaaS-grade license management system designed to protect and manage your PHP applications. It provides a robust backend to generate, validate, and monitor licenses with sub-second performance.

Why OXYLicenser?

Built with performance and security in mind, it supports bulk actions, domain binding, and provides a lightweight API for effortless integration into any project.

The 3-Step Workflow

01. CREATE A PRODUCT

Go to Admin > Products and create your software. You'll get a unique Product ID (e.g. PRD-A3X82K).

02. GENERATE LICENSES

Create single or bulk licenses in Admin > Licenses. Assign them to users and set optional expiry dates.

03. INTEGRATE CLIENT

Drop our OXYLicenseClient.php folder into your app, hardcode your Product ID, and start validating.

Product Management

Products are the core of OXYLicenser. Each product you create acts as a container for licenses and has its own security credentials.

Credential Visibility Description
Product ID PUBLIC Safe to hardcode in your software. Identifies your tool during API calls.
RSA Public Key PUBLIC Unique to each product. Included in your software to verify authentic API responses.
License Type PUBLIC Returns regular or trial. Used to adjust app features.

License Management

Manage your user ecosystem with ease using our advanced license table. Supports real-time status updates and bulk management.

Bulk Actions

Select multiple licenses to perform batch operations:

  • Suspend/Activate
  • Edit Expiry Date
  • Delete Records

RSA Security 🛡️

Master Security Reference:

  • Asymmetric Signing: Prevents Host-file Crack.
  • Public Key: Verification on Client side.
  • Security Protocols: v1.4.0 Toggle between OPEN (Blacklist) and STRICT (Whitelist) modes per license.

Migration & Import from Other Platforms

OXYLicenser makes it easy to migrate active licenses from other licensing platforms (such as Freemius, Gumroad, Software License Manager, or custom databases) via our CSV Import module.

Supported CSV Headers

Your CSV file can map columns to the following fields during the upload process:

  • license_key (Optional): The actual key string. If empty, OXYLicenser auto-generates a key using your product format.
  • product_id (Optional): The ID of the target product. If not mapped, you must select a default product.
  • customer_email (Required): The email address of the license holder.
  • customer_name (Optional): The name of the license holder.
  • slots_max (Optional): Maximum allowed domain/site activations (Default is 1). Use 0 for unlimited.
  • expires_at (Optional): Format: YYYY-MM-DD HH:MM:SS. Leave empty for Lifetime access.
  • status (Optional): active, suspended, expired, or inactive.
  • note (Optional): Internal developer remarks.

Key Import Features

  • Delimiter Detection: Automatically detects Commas (,), Semicolons (;), and Tabs (\t).
  • Dry-Run Validation: Running a validation scan before importing checks for email formatting issues, unauthorized product IDs, and key conflicts.
  • Conflict Rules: Toggle between Skip, Overwrite, and Abort to handle pre-existing license keys.

Integrating the PHP Client

The OXYLicenseClient is the recommended way to integrate licensing. It handles cURL requests, host detection, and JSON parsing for you.

1. Activation Concept

Place this code inside your installer.php or activation form handler.

PHP / ACTIVATION
// 1. Initialize Client with RSA Verification
$oxy = new OXYLicenseClient(
    'https://license-server.com', 
    $_POST['key'], 
    'PRD-XXXXXX', // Your Product ID
    '-----BEGIN PUBLIC KEY----- ... ----END PUBLIC KEY-----' // Product RSA Public Key
);

// 2. Send Activation request
$result = $oxy->activate_license();

if ($result['success']) {
    // ✅ Save License Key AND Public Key to your local config
    save_local_config($_POST['key'], '-----BEGIN PUBLIC KEY----- ...');
} else {
    // ❌ Show error: "Invalid Key" or "Expired"
    echo $result['message'];
}

2. Runtime Validation

Verify the license on every page load (Graceful Mode). Tip: Cache this response or use a sessions hook to maintain speed.

PHP / RUNTIME CHECK
// Initialize Client with persisted Public Key
$oxy = new OXYLicenseClient(OXY_URL, LICENSE_KEY, PRODUCT_ID, PUBLIC_KEY);
$check = $oxy->check_license();
 
if (!$check['success']) {
    $is_premium = false;

    // 🔒 REMOTE WIPE (Security Kill-switch)
    if (isset($check['data']['action']) && $check['data']['action'] === 'remote_wipe') {
        // Robust Soft-Wipe: Only clears the key, preserves config
        $config = __DIR__ . '/config.php';
        if (file_exists($config)) {
            $content = file_get_contents($config);
            $pattern = "/define\s*\(\s*['\"]LICENSE_KEY['\"]\s*,\s*['\"].*?['\"]\s*\)\s*;/i";
            $content = preg_replace($pattern, "define('LICENSE_KEY', '');", $content);
            file_put_contents($config, $content);
        }
        header("Location: dashboard.php?msg=revoked");
        exit;
    }

    echo "Notice: Your status is " . htmlspecialchars($check['data']['status']);
} else {
    $is_premium = true;
    
    // NEW v1.3.0: Check Versioning, Allotments & Connected Domain
    $server_version = $check['data']['version'] ?? '1.0.0';
    $update_available = version_compare($server_version, OXY_APP_VERSION, '>');
    
    $active_domain = $check['data']['domain'] ?? 'Unknown';
    $slots_used = $check['data']['slots_used'] ?? 0;

    // NEW v1.3.1: Trial Mode Detection
    $is_trial = $oxy->is_trial($check);
}

3. Deactivation (Surgical Reset)

Logout or unbind licenses without losing database settings. Surgically clear the license key locally.

PHP / DEACTIVATION
$res = $oxy->deactivate_license();

if ($res['success']) {
    // 2. Surgical Reset: Clear only the license key
    $config = __DIR__ . '/config.php';
    if (file_exists($config)) {
        $content = file_get_contents($config);
        $pattern = "/define\s*\(\s*['\"]LICENSE_KEY['\"]\s*,\s*['\"].*?['\"]\s*\)\s*;/i";
        $content = preg_replace($pattern, "define('LICENSE_KEY', '');", $content);
        file_put_contents($config, $content);
    }
    header("Location: dashboard.php?msg=deactivated");
    exit;
}

4. Re-activation Flow

Detect missing keys and prompt users to re-activate directly from the dashboard.

PHP / RE-ACTIVATION
if (empty(LICENSE_KEY)) {
    // Show activation form instead of locking out
    echo '<form method="POST">...</form>';
}

5. Security Best Practices

Robust Key Handling

The client library automatically normalizes RSA keys, handling common copy-paste issues like extra whitespace or missing headers for you.

WordPress Support

OXYLicenser includes specialized support for WordPress, making it the perfect choice for plugin and theme developers.

Specialized SDK

The OXYLicenseClientWP class uses native WordPress functions like wp_remote_post() and the Options API (get_option, update_option) for maximum compatibility.

1. Update Notifications

Your license server can now serve update metadata that matches the WordPress Update API requirements.

Metadata Field Description
new_version The latest version number set in the Product dashboard.
requires Minimum WordPress version required.
requires_php Minimum PHP version required.
sections Includes description and changelog.

2. Implementation in WP

Use the WP-specific client to handle activation and update checks seamlessly.

PHP / WORDPRESS INTEGRATION
// Initialize the WP Client
$oxy = new OXYLicenseClientWP(
    OXY_SERVER_URL, 
    OXY_PRODUCT_ID, 
    OXY_PUBLIC_KEY,
    'my-plugin-slug' // Used for option storage
);

// Check for updates
$update_info = $oxy->get_version_info();

if ($update_info['success']) {
    $new_v = $update_info['data']['new_version'];
    // WordPress will show an update notice if local version < $new_v
}

Check the examples/wordpress-example.php for a complete starter plugin implementation.

WooCommerce Pro

OXYLicenser provides a deep, enterprise-grade integration for WooCommerce that automates license generation and delivery.

Automation Bridge

By mapping your WooCommerce products to OXY Product UIDs, you can completely automate your sales funnel. Unique keys are issued immediately upon order completion.

1. Key Features

  • Bulk Generation: Automatically handles multi-quantity purchases, issuing a unique key for every unit.
  • Sync Metadata: Automatically saves customer emails and names to the license record for easy management.
  • My Account Integration: Display keys directly in the WooCommerce customer dashboard.
  • Bulk Management Tools: NEW Search, scrollable site lists, and usage progress bars for enterprise-scale licenses.
View WooCommerce Guide

2. Security Protocols (Strict Mode)

WooCommerce integrated licenses now support advanced policy control, enabling enterprise-level security for your customers.

OPEN Mode (Default)

Allows activations from any domain. Recommended for consumer software. Supports surgical blacklisting.

STRICT Mode (Whitelist)

Blocks all domains except those explicitly whitelisted. Ideal for corporate seats and high-value B2B plugins.

Universal & Multi-Language Integrations

Since OXYLicenser operates on standard JSON-over-HTTP requests, any technology stack can validate licenses. For maximum security, we recommend verifying the server's RSA responses locally using your product's RSA Public Key.

Python Integration Example

Use the following Python snippet to communicate with OXYLicenser and verify the cryptographic signature using the cryptography library:

PYTHON / RSA INTEGRATION
import requests
import base64
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.serialization import load_pem_public_key

API_URL = "https://your-license-server.com/api.php"
PRODUCT_ID = "PRD-XXXXXXXX"
PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...\n-----END PUBLIC KEY-----"

def check_license(license_key):
    payload = {
        "action": "check",
        "license_key": license_key,
        "product_id": PRODUCT_ID
    }
    
    try:
        response = requests.post(API_URL, data=payload, timeout=10)
        if response.status_code != 200:
            return False, f"Server responded with HTTP {response.status_code}"
            
        # Verify RSA signature
        signature = base64.b64decode(response.headers.get("X-OXY-Signature", ""))
        public_key = load_pem_public_key(PUBLIC_KEY_PEM.encode())
        
        public_key.verify(
            signature,
            response.content,
            padding.PKCS1v15(),
            hashes.SHA256()
        )
        
        data = response.json()
        return data.get("success", False), data.get("message", "")
    except Exception as e:
        return False, f"Verification failed: {str(e)}"

Node.js & Electron Integration Example

Integrate OXYLicenser validations into your Node.js server or Electron application using the native crypto module:

JAVASCRIPT / NODE.JS
const https = require('https');
const crypto = require('crypto');
const querystring = require('querystring');

function verifyLicense(licenseKey, productId, publicKeyPem) {
    const postData = querystring.stringify({
        action: 'check',
        license_key: licenseKey,
        product_id: productId
    });

    const options = {
        hostname: 'your-license-server.com',
        path: '/api.php',
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': Buffer.byteLength(postData)
        }
    };

    const req = https.request(options, (res) => {
        let body = '';
        res.on('data', (chunk) => body += chunk);
        res.on('end', () => {
            const signature = res.headers['x-oxy-signature'];
            
            const verifier = crypto.createVerify('sha256');
            verifier.update(body);
            const isValid = verifier.verify(publicKeyPem, signature, 'base64');
            
            if (!isValid) {
                console.error("Signature check failed!");
                return;
            }
            
            const data = JSON.parse(body);
            console.log("Verification outcome:", data.success);
        });
    });
    req.write(postData);
    req.end();
}

Ruby Integration Example

Validate license states, track usage, and verify RSA signatures using native Ruby modules:

RUBY / RSA INTEGRATION
require 'net/http'
require 'uri'
require 'openssl'
require 'json'
require 'base64'

def verify_license(license_key, product_id, public_key_pem)
  uri = URI.parse("https://your-license-server.com/api.php")
  payload = {
    'action' => 'check',
    'license_key' => license_key,
    'product_id' => product_id
  }
  
  begin
    response = Net::HTTP.post_form(uri, payload)
    return false, "HTTP Error: #{response.code}" if response.code.to_i != 200
    
    signature_b64 = response['X-OXY-Signature']
    return false, "Missing signature" if signature_b64.nil? || signature_b64.empty?
    
    signature = Base64.decode64(signature_b64)
    pub_key = OpenSSL::PKey::RSA.new(public_key_pem)
    
    digest = OpenSSL::Digest::SHA256.new
    is_valid = pub_key.verify(digest, signature, response.body)
    return false, "Invalid signature" unless is_valid
    
    data = JSON.parse(response.body)
    return data['success'], data['message']
  rescue => e
    return false, "Verification failed: #{e.message}"
  end
end

Laravel Route Middleware Example

Secure specific routes or resource endpoints within a Laravel project by enforcing verification through an incoming HTTP request filter:

PHP / LARAVEL MIDDLEWARE
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class VerifyOXYLicense
{
    public function handle(Request $request, Closure $next)
    {
        $licenseKey = config('licensing.key');
        $productId = config('licensing.product_id');
        $publicKey = config('licensing.public_key');
        
        if (empty($licenseKey)) {
            return response()->json(['success' => false, 'message' => 'License key missing.'], 403);
        }

        $response = Http::asForm()->post('https://your-license-server.com/api.php', [
            'action' => 'check',
            'license_key' => $licenseKey,
            'product_id' => $productId,
        ]);

        if ($response->failed()) {
            return response()->json(['success' => false, 'message' => 'Licensing server offline.'], 503);
        }

        $signature = $response->header('X-OXY-Signature');
        if (!$signature) {
            return response()->json(['success' => false, 'message' => 'Unsigned response.'], 403);
        }

        $isValid = openssl_verify(
            $response->body(),
            base64_decode($signature),
            $publicKey,
            OPENSSL_ALGO_SHA256
        );

        if ($isValid !== 1) {
            return response()->json(['success' => false, 'message' => 'Signature verification failed.'], 403);
        }

        $data = $response->json();
        if (!$data || !($data['success'] ?? false)) {
            return response()->json(['success' => false, 'message' => $data['message'] ?? 'Invalid license.'], 403);
        }

        return $next($request);
    }
}

Billing & Provisioning API

OXYLicenser includes an isolated, server-to-server provisioning API endpoint that allows billing platforms like WHMCS, Blesta, or custom billing systems to automate license fulfillment.

Isolated Security Scope

Instead of using master API keys, the billing system authorizes requests using a product-specific provisioning_token. If a billing server is compromised, only that specific product's licenses are affected.

Authentication

Send the provisioning token in the request header or as a POST parameter:

HTTP HEADER
X-OXY-PROVISIONING-TOKEN: oxy_prov_xxxxxxxxxxxxxxxxxxxxxxxx

Provisioning Actions

Send a POST request to api.php with one of the following actions:

Action Parameters Fulfillment Behavior
provision_create customer_email (req)
customer_name (opt)
slots (opt)
duration_days (opt)
Generates and returns a new license key mapped to the customer.
provision_suspend license_key (req) Suspends the license key, setting its status to suspended.
provision_unsuspend license_key (req) Unsuspends the license key, setting its status back to active.
provision_terminate license_key (req) Sets status to expired and flags all active domains for a remote wipe.
provision_update license_key (req)
slots (opt)
duration_days (opt)
Modifies the active activation slot limit or extends/shortens the expiration date.

API Reference

OXYLicenser exposes a RESTful POST API at api.php. All requests must be sent as multipart/form-data or x-www-form-urlencoded.

Param Req Description
is_trial Boolean True if this is a trial license. (NEW v1.3.1-HF1: Reliable metadata)
license_type String regular or trial. (NEW v1.3.1-HF1)
action YES activate, check, deactivate, manage_activations
sub_action OPT For manage_activations: list, delete, add_restriction, remove_restriction, toggle_protection.
policy OPT Binary. 0 = Blacklist (Red), 1 = Whitelist (Green). Used with add_restriction.
restriction_id OPT Required for remove_restriction.
license_key YES The 32-character license key
product_id YES Unique Product Identifier
public_key OPT RSA Public Key for signature validation (Rec.)
host OPT Auto-detected if not provided
RSA Signature Requirement

For production environments, always provide the Product RSA Public Key during client initialization to ensure responses cannot be tampered with by hackers.

Premium Dashboard Templates

We provide high-end, SaaS-grade UI templates to give your users a premium experience immediately.

1. Standard PHP Dashboard

A standalone file with a 3x2 grid layout. Perfect for custom PHP scripts or SaaS apps.

PHP / DASHBOARD TEMPLATE
<?php
/**
 * OXYLicenser - Premium Dashboard Template
 * DESIGN: Slim & Industrial SaaS (Vercel/Linear Style)
 */

// 1. INTEGRATION CONFIGURATION
define('OXY_API_URL', 'https://your-license-server.com/api.php');
define('MY_PRODUCT_ID', 'PRD-XXXXXX');
define('MY_PUBLIC_KEY', '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----');
define('APP_VERSION', '1.0.0');

// Load the Client Library
require_once 'OXYLicenseClient.php'; 
... (Find full code in examples/premium_dashboard_template.php)

2. WordPress (Plugin/Theme) Dashboard

A "Plug & Play" class. Compatible with Themes (Appearance menu) and Plugins (Settings menu).

PHP / WP DASHBOARD CLASS
<?php
/**
 * OXYLicenser - Premium WordPress Dashboard Template (v1.3.0)
 * A professional, high-end licensing dashboard for WordPress Themes and Plugins.
 */

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

class OXY_Premium_Dashboard {
    // ... Initialization logic ...
    public function __construct($api_url, $product_id, $public_key, $slug, $is_theme = false, $version = '1.0.0') {
        // ... Load SDK & Register Menus ...
    }
}
... (Find full code in examples/premium_wordpress_dashboard.php)