PHPackages                             licensesos/php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. licensesos/php-sdk

ActiveLibrary

licensesos/php-sdk
==================

PHP SDK for LicensesOS - License validation and activation for PHP applications

v1.0.0(3mo ago)00MITPHPPHP ^8.1CI passing

Since Feb 9Pushed 3mo agoCompare

[ Source](https://github.com/licensesos/php-sdk)[ Packagist](https://packagist.org/packages/licensesos/php-sdk)[ Docs](https://docs.licensesos.com/sdks/php)[ RSS](/packages/licensesos-php-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

LicensesOS PHP SDK
==================

[](#licensesos-php-sdk)

A PHP SDK for integrating with the LicensesOS license management API. Provides license validation, activation, and deactivation with built-in caching and WordPress integration.

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Guzzle HTTP client 7.0+

Installation
------------

[](#installation)

```
composer require licenseos/php-sdk
```

Quick Start
-----------

[](#quick-start)

```
use LicensesOS\LicensesOsClient;

$client = new LicensesOsClient('your_api_key');

// Validate a license
$result = $client->validate('LIC-XXXX-XXXX-XXXX-XXXX', 'example.com');

if ($result->isValid()) {
    echo "License is valid!";
    echo "Status: " . $result->status;
    echo "Expires: " . $result->expiresAt;
}
```

Core Features
-------------

[](#core-features)

### License Validation

[](#license-validation)

Validate a license key for a specific domain or device:

```
$result = $client->validate(
    licenseKey: 'LIC-XXXX-XXXX-XXXX-XXXX',
    identifier: 'example.com',
    metadata: [
        'app_version' => '1.2.3',
        'php_version' => PHP_VERSION,
    ]
);

// Check validation status
if ($result->isValid()) {
    // License is valid for this identifier
}

if ($result->isActive()) {
    // License status is "active"
}

if ($result->isExpired()) {
    // License has expired
}

if ($result->isRevoked()) {
    // License was revoked
}

// Access entitlements
if ($result->hasEntitlement('plan')) {
    $plan = $result->getEntitlement('plan');
}

// Get remaining activations
$remaining = $result->getRemainingActivations();
```

### License Activation

[](#license-activation)

Activate a license for a domain or device:

```
$result = $client->activate(
    licenseKey: 'LIC-XXXX-XXXX-XXXX-XXXX',
    identifier: 'example.com'
);

if ($result->isActivated()) {
    echo "Successfully activated!";
    echo "Remaining activations: " . $result->getRemainingActivations();
} else {
    echo "Activation failed: " . $result->getErrorMessage();
    // Error codes: ACTIVATION_LIMIT_REACHED, LICENSE_EXPIRED, etc.
}
```

### License Deactivation

[](#license-deactivation)

Deactivate a license from a domain or device:

```
$result = $client->deactivate(
    licenseKey: 'LIC-XXXX-XXXX-XXXX-XXXX',
    identifier: 'example.com'
);

if ($result->isDeactivated()) {
    echo "License deactivated. Remaining: " . $result->getRemainingActivations();
}
```

### List Activations

[](#list-activations)

Get all activations for a license:

```
$result = $client->listActivations('LIC-XXXX-XXXX-XXXX-XXXX');

echo "Total activations: " . $result->total;
echo "Limit: " . $result->limit;
echo "Remaining: " . $result->remaining;

foreach ($result->getActiveActivations() as $activation) {
    echo $activation['identifier'] . " - " . $activation['activated_at'];
}

// Check if a specific identifier is activated
if ($result->hasActivation('example.com')) {
    // This domain is activated
}
```

Domain Normalization
--------------------

[](#domain-normalization)

The SDK automatically normalizes domain identifiers:

```
// All of these become "example.com"
$client->validate($key, 'https://www.example.com/');
$client->validate($key, 'HTTP://EXAMPLE.COM:8080/path');
$client->validate($key, 'www.example.com');
$client->validate($key, 'example.com');

// Subdomain is preserved
$client->validate($key, 'app.example.com'); // becomes "app.example.com"

// IDN domains are converted to punycode
$client->validate($key, 'münchen.de'); // becomes "xn--mnchen-3ya.de"
```

You can also normalize domains manually:

```
$normalized = LicensesOsClient::normalizeDomain('https://www.Example.COM/page');
// Returns: "example.com"
```

Caching
-------

[](#caching)

The SDK includes a caching layer for reduced API calls and offline tolerance.

### Basic Caching

[](#basic-caching)

```
use LicensesOS\LicensesOsClient;
use LicensesOS\Cache\LicenseCache;
use LicensesOS\Cache\FileCache;

$client = new LicensesOsClient('your_api_key');
$cache = new FileCache('/path/to/cache/dir');
$licenseCache = new LicenseCache($client, $cache);

// Validate with caching (12-hour TTL)
$result = $licenseCache->validate($licenseKey, $domain);

// Force refresh from API
$result = $licenseCache->validate($licenseKey, $domain, [], true);

// Check if premium features should be allowed
// (uses cache with 48-hour grace period for offline tolerance)
if ($licenseCache->shouldAllowPremium($licenseKey, $domain)) {
    // Enable premium features
}
```

### Cache Configuration

[](#cache-configuration)

```
$licenseCache = new LicenseCache(
    client: $client,
    cache: $cache,
    cacheTtl: 43200,    // 12 hours (default)
    gracePeriod: 172800  // 48 hours (default)
);
```

### Available Cache Adapters

[](#available-cache-adapters)

**FileCache** - Stores cache in JSON files:

```
use LicensesOS\Cache\FileCache;

$cache = new FileCache('/var/cache/myapp', 'myapp');
```

**WordPressCache** - Uses WordPress transients:

```
use LicensesOS\Cache\WordPressCache;

$cache = new WordPressCache('my_plugin');
```

**Custom Cache** - Implement `CacheInterface`:

```
use LicensesOS\Cache\CacheInterface;

class RedisCache implements CacheInterface
{
    public function get(string $key): mixed { /* ... */ }
    public function set(string $key, mixed $value, int $ttl): bool { /* ... */ }
    public function delete(string $key): bool { /* ... */ }
}
```

WordPress Integration
---------------------

[](#wordpress-integration)

The SDK includes ready-to-use WordPress integration classes.

### Step 1: Create Your License Manager

[](#step-1-create-your-license-manager)

```
use LicensesOS\WordPress\LicenseManager;

class MyPluginLicense extends LicenseManager
{
    private static ?self $instance = null;

    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    protected function getApiKey(): string
    {
        return 'your_api_key_here';
    }

    protected function getOptionPrefix(): string
    {
        return 'my_plugin';
    }

    protected function getPluginVersion(): string
    {
        return MY_PLUGIN_VERSION;
    }
}
```

### Step 2: Create a Settings Page

[](#step-2-create-a-settings-page)

```
use LicensesOS\WordPress\SettingsPage;

class MyPluginSettings extends SettingsPage
{
    protected function getLicenseManager(): LicenseManager
    {
        return MyPluginLicense::getInstance();
    }

    protected function getPageTitle(): string
    {
        return 'My Plugin License';
    }

    protected function getMenuTitle(): string
    {
        return 'License';
    }

    protected function getMenuSlug(): string
    {
        return 'my-plugin-license';
    }

    protected function getPurchaseUrl(): string
    {
        return 'https://yoursite.com/pricing';
    }
}

// Register the settings page
add_action('admin_menu', function() {
    $settings = new MyPluginSettings();
    $settings->addMenuPage();
});
```

### Step 3: Gate Premium Features

[](#step-3-gate-premium-features)

```
$license = MyPluginLicense::getInstance();

// Simple premium check
if ($license->isPremium()) {
    // Enable all premium features
}

// Check specific entitlements
if ($license->hasEntitlement('advanced_export')) {
    // Enable advanced export feature
}

// Get entitlement values
$maxItems = $license->getEntitlement('max_items', 10);
```

### Step 4: Background Validation (Optional)

[](#step-4-background-validation-optional)

Refresh license status periodically via cron:

```
// Register cron hook
add_action('my_plugin_license_check', function() {
    $license = MyPluginLicense::getInstance();
    if ($license->needsRefresh()) {
        $license->validate(true);
    }
});

// Schedule daily check on activation
register_activation_hook(__FILE__, function() {
    if (!wp_next_scheduled('my_plugin_license_check')) {
        wp_schedule_event(time(), 'daily', 'my_plugin_license_check');
    }
});

// Clear on deactivation
register_deactivation_hook(__FILE__, function() {
    wp_clear_scheduled_hook('my_plugin_license_check');
});
```

Error Handling
--------------

[](#error-handling)

The SDK throws two types of exceptions:

### ApiException

[](#apiexception)

Thrown when the API returns an error response:

```
use LicensesOS\Exceptions\ApiException;

try {
    $result = $client->validate($licenseKey, $domain);
} catch (ApiException $e) {
    echo "API Error: " . $e->getMessage();
    echo "Error Code: " . $e->getErrorCode();
    echo "HTTP Status: " . $e->getStatusCode();
}
```

Common error codes:

- `LICENSE_NOT_FOUND` - License key doesn't exist
- `LICENSE_EXPIRED` - License has expired
- `LICENSE_REVOKED` - License was revoked
- `ACTIVATION_LIMIT_REACHED` - No more activations available
- `RATE_LIMITED` - Too many requests
- `AUTH_INVALID_API_KEY` - Invalid API key

### NetworkException

[](#networkexception)

Thrown when unable to connect to the API:

```
use LicensesOS\Exceptions\NetworkException;

try {
    $result = $client->validate($licenseKey, $domain);
} catch (NetworkException $e) {
    // Network error - use cached data if available
    echo "Network Error: " . $e->getMessage();
}
```

### Graceful Degradation Pattern

[](#graceful-degradation-pattern)

```
use LicensesOS\Exceptions\ApiException;
use LicensesOS\Exceptions\NetworkException;

function checkLicense(LicenseCache $cache, string $key, string $domain): bool
{
    try {
        $result = $cache->validate($key, $domain);
        return $result->isValid();
    } catch (NetworkException $e) {
        // Network error - fall back to grace period
        return $cache->shouldAllowPremium($key, $domain);
    } catch (ApiException $e) {
        // API error - license is invalid
        return false;
    }
}
```

Best Practices
--------------

[](#best-practices)

### 1. Cache API Responses

[](#1-cache-api-responses)

Always use the `LicenseCache` class to avoid excessive API calls:

```
// Good
$cache = new LicenseCache($client, new FileCache('/tmp/cache'));
$result = $cache->validate($key, $domain);

// Bad - calls API every time
$result = $client->validate($key, $domain);
```

### 2. Handle Network Errors Gracefully

[](#2-handle-network-errors-gracefully)

Don't break your app when the API is unreachable:

```
// Good - uses grace period
if ($licenseCache->shouldAllowPremium($key, $domain)) {
    enablePremiumFeatures();
}

// Bad - might throw on network error
$result = $client->validate($key, $domain);
if ($result->isValid()) {
    enablePremiumFeatures();
}
```

### 3. Store License Key Securely

[](#3-store-license-key-securely)

For WordPress, use options (they're in the database):

```
// Good
update_option('my_plugin_license_key', $licenseKey);

// Bad - don't store in plain files
file_put_contents('license.txt', $licenseKey);
```

### 4. Validate on Reasonable Schedule

[](#4-validate-on-reasonable-schedule)

Don't validate on every page load:

```
// Good - validate if cache is stale
if ($licenseCache->needsRefresh($key, $domain)) {
    $licenseCache->validate($key, $domain, [], true);
}

// Bad - validates every time
$client->validate($key, $domain);
```

### 5. Soft Gate Features

[](#5-soft-gate-features)

Disable UI/features rather than breaking functionality:

```
// Good - soft gating
function renderExportButton() {
    $license = MyPluginLicense::getInstance();
    if ($license->isPremium()) {
        echo 'Export';
    } else {
        echo 'Export (Pro)';
        echo 'Upgrade to Pro';
    }
}

// Bad - hard gating that breaks UX
function exportData() {
    if (!MyPluginLicense::getInstance()->isPremium()) {
        die('License required');
    }
}
```

API Reference
-------------

[](#api-reference)

### LicensesOsClient

[](#licensesosclient)

MethodDescription`validate(string $licenseKey, string $identifier, array $metadata = [])`Validate a license`activate(string $licenseKey, string $identifier, array $metadata = [])`Activate a license`deactivate(string $licenseKey, string $identifier)`Deactivate a license`listActivations(string $licenseKey)`List all activations`normalizeDomain(string $input)`Normalize a domain (static)`shouldAllowPremium(array $cachedState, int $graceTtl = 172800)`Check cached state (static)### LicenseCache

[](#licensecache)

MethodDescription`validate(...)`Validate with caching`shouldAllowPremium(string $licenseKey, ?string $identifier = null)`Check premium status`getCachedState(string $licenseKey, ?string $identifier = null)`Get cached state`clearCache(string $licenseKey, ?string $identifier = null)`Clear cached data`needsRefresh(string $licenseKey, ?string $identifier = null)`Check if refresh needed### WordPress\\LicenseManager

[](#wordpresslicensemanager)

MethodDescription`getLicenseKey()`Get stored license key`setLicenseKey(string $key)`Store license key`clearLicenseKey()`Clear license key and cache`getStatus()`Get cached status`getLicenseData()`Get cached license data`isPremium()`Check if premium features allowed`hasEntitlement(string $key)`Check for entitlement`getEntitlement(string $key, mixed $default = null)`Get entitlement value`validate(bool $forceRefresh = false)`Validate license`activate(string $licenseKey)`Activate license`deactivate()`Deactivate license`needsRefresh()`Check if refresh neededLicense
-------

[](#license)

MIT

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance82

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

95d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8e5c1e7a46238fd50e833f9974bd209d726ba1dd41c45cf3fbd98d441c9f8867?d=identicon)[licensesos](/maintainers/licensesos)

---

Top Contributors

[![hsalem7](https://avatars.githubusercontent.com/u/6441901?v=4)](https://github.com/hsalem7 "hsalem7 (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/licensesos-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/licensesos-php-sdk/health.svg)](https://phpackages.com/packages/licensesos-php-sdk)
```

###  Alternatives

[neuron-core/neuron-ai

The PHP Agentic Framework.

1.8k245.3k21](/packages/neuron-core-neuron-ai)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3731.2M42](/packages/tencentcloud-tencentcloud-sdk-php)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
