PHPackages                             getkeymanager/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. [Validation &amp; Sanitization](/categories/validation)
4. /
5. getkeymanager/php-sdk

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

getkeymanager/php-sdk
=====================

Official PHP SDK for License Management Platform API

3.3.0(2mo ago)0139—3.4%1MITPHPPHP ^7.4 || ^8.0

Since Jan 24Pushed 2mo agoCompare

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

READMEChangelog (10)Dependencies (4)Versions (17)Used By (1)

KeyManager - PHP SDK
====================

[](#keymanager---php-sdk)

**Version: 3.0.0** - Identifier-first architecture with offline-first validation!

Features
--------

[](#features)

### Core Features (v1.x)

[](#core-features-v1x)

- ✅ License validation (online and offline)
- ✅ License activation and deactivation
- ✅ Feature flag checking
- ✅ Hardware ID generation
- ✅ Telemetry submission
- ✅ RSA-4096-SHA256 signature verification
- ✅ Automatic retry with exponential backoff
- ✅ Built-in caching
- ✅ Idempotent operations
- ✅ PSR-12 compliant

### New in v2.0.0

[](#new-in-v200)

- ✅ **Complete license management** - Create, update, delete, list licenses
- ✅ **License assignment** - Assign licenses to customers (sync &amp; async)
- ✅ **Metadata management** - Custom metadata for licenses and products
- ✅ **Product management** - Create and manage products via API
- ✅ **Generator support** - Generate licenses programmatically
- ✅ **Contract management** - Manage API contracts
- ✅ **Downloadables access** - Provide downloadable files to users
- ✅ **Advanced telemetry** - Retrieve telemetry data with filters
- ✅ **Public changelog API** - Access changelogs without authentication

### New in v2.1.0

[](#new-in-v210)

- ✅ **New endpoints**: `getLicenseFile()`, `getProductMeta()`, `getProduct()`, `getProductChangelog()`, `getProductPublicKey()`
- ✅ **New response codes**: LICENSE\_FILE\_RETRIEVED (502), LICENSE\_FILE\_GENERATION\_FAILED (503), LICENSE\_KEY\_NOT\_FOUND\_DETAILS (501), PRODUCT\_FOUND (631), PRODUCT\_PUBLIC\_KEY\_FOUND (632), PRODUCT\_PUBLIC\_KEY\_NOT\_FOUND (633)
- ✅ **Offline .lic parsing**: `parseLicenseFile()` (Base64 decode → 256-byte chunks → RSA PKCS1 decrypt → JSON)
- ✅ **License/key sync**: `syncLicenseAndKey()` with atomic file updates + telemetry
- ✅ **Validation timers**: `isCheckIntervalPast()` and `isForceValidationPast()` (fail-safe true on error)

### New in v3.0.0 - BREAKING CHANGES

[](#new-in-v300---breaking-changes)

- ✅ **Mandatory Identifier Parameter** - All validation/activation methods now require `$identifier` (domain or HWID)
- ✅ **Configuration Inheritance** - Set `productPublicKey`, `licenseKey`, `licenseFilePath`, `defaultIdentifier` once, reuse everywhere
- ✅ **Offline-First Validation** - Try cached .lic file first, fallback to API with `ValidationType` constants
- ✅ **Type-Safe DTOs** - `ValidationResultDto`, `ActivationResultDto`, `SyncResultDto` with typed accessors
- ✅ **Constants &amp; Enums** - `ValidationType`, `IdentifierType`, `OptionKeys` for predictable behavior
- ✅ **Helper Methods** - `generateIdentifier()`, `getIdentifierOrGenerate()`, `resolvePublicKey()`, `canValidateOffline()`
- ✅ **Enhanced Error Messages** - Actionable, context-aware errors with documentation links
- ⚠️ **⚠️ MIGRATION REQUIRED:** See [Migration Guide v2→v3](#migration-guide-v2-to-v3) below

#### Offline .lic Parsing (LicenseValidator)

[](#offline-lic-parsing-licensevalidator)

```
use GetKeyManager\SDK\Validation\LicenseValidator;

// $validator is the LicenseValidator instance (used internally by LicenseClient)
$licenseData = $validator->parseLicenseFile($licFileContent, $publicKey);
```

#### Force Validation Check

[](#force-validation-check)

```
if ($validator->isForceValidationPast($licPath, $keyPath)) {
    showLicenseScreen();
    die("License validation required");
}
```

**30+ new methods added while maintaining full backward compatibility!**

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

[](#requirements)

- PHP 7.4 or higher
- ext-json
- ext-openssl
- ext-curl

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

[](#installation)

### Via Composer (Recommended)

[](#via-composer-recommended)

```
composer require getkeymanager/php-sdk
```

### Manual Installation

[](#manual-installation)

1. Download the SDK files
2. Include the autoloader:

```
require_once __DIR__ . '/vendor/autoload.php';
```

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

[](#quick-start)

### Initialize the Client

[](#initialize-the-client)

```
use GetKeyManager\SDK\LicenseClient;

$client = new LicenseClient([
    'apiKey' => 'your-api-key-here',
    'publicKey' => file_get_contents('/path/to/public-key.pem'),
    'baseUrl' => 'https://api.getkeymanager.com', // Optional
    'verifySignatures' => true, // Optional, default: true
    'cacheEnabled' => true, // Optional, default: true
    'cacheTtl' => 300, // Optional, default: 300 seconds
]);
```

### Validate a License (Online)

[](#validate-a-license-online)

```
use GetKeyManager\SDK\Constants\ValidationType;

try {
    // Basic validation with auto-generated identifier
    $result = $client->validateLicense('XXXXX-XXXXX-XXXXX-XXXXX');

    // Or specify identifier explicitly
    $result = $client->validateLicense(
        'XXXXX-XXXXX-XXXXX-XXXXX',
        'example.com',  // Domain identifier
        null,           // Use config's public key
        ValidationType::OFFLINE_FIRST,  // Try cache first
        []              // Options
    );

    if ($result['success']) {
        echo "License is valid!\n";
        echo "Status: " . $result['license']['status'] . "\n";
        echo "Expires: " . ($result['license']['expires_at'] ?? 'Never') . "\n";
    } else {
        echo "License is invalid: " . $result['message'] . "\n";
    }
} catch (LicenseException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
```

### Activate a License

[](#activate-a-license)

```
try {
    // Activation requires identifier (domain or hardware ID)
    $result = $client->activateLicense(
        'XXXXX-XXXXX-XXXXX-XXXXX',
        'workstation-01',  // Identifier: domain or HWID
        null,              // Use config's public key
        [                  // Additional options
            'idempotency_key' => 'request-uuid-here',
            'os' => 'Linux',
            'product_version' => '1.0.0'
        ]
    );

    if ($result['success']) {
        echo "License activated successfully!\n";
        echo "Activation ID: " . $result['activation_id'] . "\n";

        // .lic file generated on server
        if (isset($result['lic_file_content'])) {
            file_put_contents('/app/license.lic', $result['lic_file_content']);
        }
    }
} catch (LicenseException $e) {
    echo "Activation failed: " . $e->getMessage() . "\n";
}
```

### Deactivate a License

[](#deactivate-a-license)

```
try {
    // Identifier MUST match the activation being deactivated
    $result = $client->deactivateLicense(
        'XXXXX-XXXXX-XXXXX-XXXXX',
        'workstation-01'  // Must match activation identifier
    );

    if ($result['success']) {
        echo "License deactivated successfully!\n";
        echo "Activation ID: " . $result['activation_id'] . "\n";
    } else {
        echo "Deactivation failed: " . $result['message'] . "\n";
        // Check if activation not found
        if ($result['error'] === 'activation_not_found') {
            echo "Tip: Ensure identifier matches the activation being deactivated\n";
        }
    }
} catch (LicenseException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
```

### Check Feature Flags

[](#check-feature-flags)

```
try {
    $result = $client->checkFeature('XXXXX-XXXXX-XXXXX-XXXXX', 'premium_feature');

    if ($result['enabled']) {
        echo "Feature is enabled!\n";
        if (isset($result['value'])) {
            echo "Feature value: " . json_encode($result['value']) . "\n";
        }
    } else {
        echo "Feature is not enabled\n";
    }
} catch (LicenseException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
```

### Validate Offline License

[](#validate-offline-license)

```
use GetKeyManager\SDK\LicenseClient;

$client = new LicenseClient([
    'apiKey' => 'your-api-key',
    'publicKey' => file_get_contents('/path/to/public-key.pem')
]);

$offlineLicense = file_get_contents('/path/to/offline-license.json');

try {
    $result = $client->validateOfflineLicense($offlineLicense, [
        'hardwareId' => $client->generateHardwareId()
    ]);

    if ($result['valid']) {
        echo "Offline license is valid!\n";
        print_r($result['license']);
    } else {
        echo "Offline license validation failed:\n";
        foreach ($result['errors'] as $error) {
            echo "  - $error\n";
        }
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
```

### Send Telemetry

[](#send-telemetry)

```
$result = $client->sendTelemetry(
    'XXXXX-XXXXX-XXXXX-XXXXX',
    'application.started',
    [
        'version' => '1.0.0',
        'platform' => PHP_OS
    ],
    [
        'custom_field' => 'custom_value'
    ]
);

if ($result['success']) {
    echo "Telemetry sent successfully\n";
}
```

### Generate Hardware ID

[](#generate-hardware-id)

```
$hardwareId = $client->generateHardwareId();
echo "Hardware ID: $hardwareId\n";
```

Configuration Options
---------------------

[](#configuration-options)

OptionTypeDefaultDescription`apiKey`string*required*Your API key`publicKey`stringnullRSA public key for signature verification`baseUrl`string`https://api.getkeymanager.com`API base URL`timeout`int30Request timeout in seconds`verifySignatures`booltrueVerify response signatures`environment`stringnullEnvironment (production/staging/development)`cacheEnabled`booltrueEnable response caching`cacheTtl`int300Cache TTL in seconds`retryAttempts`int3Number of retry attempts`retryDelay`int1000Retry delay in millisecondsError Handling
--------------

[](#error-handling)

The SDK uses a hierarchy of exceptions:

```
LicenseException (base)
├── ValidationException
├── NetworkException
├── SignatureException
├── RateLimitException
└── LicenseStatusException
    ├── ExpiredException
    ├── SuspendedException
    └── RevokedException

```

### Example Error Handling

[](#example-error-handling)

```
use GetKeyManager\SDK\LicenseClient;
use GetKeyManager\SDK\ExpiredException;
use GetKeyManager\SDK\RateLimitException;
use GetKeyManager\SDK\NetworkException;

try {
    $result = $client->validateLicense($licenseKey);
} catch (ExpiredException $e) {
    echo "License has expired: " . $e->getMessage() . "\n";
} catch (RateLimitException $e) {
    echo "Rate limit exceeded. Please try again later.\n";
} catch (NetworkException $e) {
    echo "Network error: " . $e->getMessage() . "\n";
} catch (LicenseException $e) {
    echo "License error: " . $e->getMessage() . "\n";
}
```

Caching
-------

[](#caching)

The SDK automatically caches:

- License validation responses
- Feature flag checks

### Clear Cache

[](#clear-cache)

```
// Clear all cache
$client->clearCache();

// Clear cache for specific license
$client->clearLicenseCache('XXXXX-XXXXX-XXXXX-XXXXX');
```

Signature Verification
----------------------

[](#signature-verification)

All API responses are cryptographically signed. The SDK automatically verifies signatures when `verifySignatures` is enabled.

### Using SignatureVerifier Directly

[](#using-signatureverifier-directly)

```
use GetKeyManager\SDK\SignatureVerifier;

$verifier = new SignatureVerifier($publicKeyPem);

$data = '{"license":"XXXXX-XXXXX-XXXXX-XXXXX"}';
$signature = 'base64_encoded_signature';

if ($verifier->verify($data, $signature)) {
    echo "Signature is valid!\n";
} else {
    echo "Signature verification failed!\n";
}
```

### Verify JSON Response

[](#verify-json-response)

```
$jsonResponse = '{"data":{},"signature":"..."}';

if ($verifier->verifyJsonResponse($jsonResponse)) {
    echo "Response signature is valid!\n";
}
```

Idempotency
-----------

[](#idempotency)

Activation and deactivation operations support idempotency:

```
$idempotencyKey = '550e8400-e29b-41d4-a716-446655440000';

$result = $client->activateLicense($licenseKey, [
    'hardwareId' => $hardwareId,
    'idempotencyKey' => $idempotencyKey
]);

// Repeat with same key will return same response
$result2 = $client->activateLicense($licenseKey, [
    'hardwareId' => $hardwareId,
    'idempotencyKey' => $idempotencyKey
]);
```

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

[](#best-practices)

### 1. Store API Key Securely

[](#1-store-api-key-securely)

```
// ❌ Don't hardcode API keys
$client = new LicenseClient(['apiKey' => 'pk_live_...']);

// ✅ Use environment variables
$client = new LicenseClient(['apiKey' => getenv('LICENSE_API_KEY')]);
```

### 2. Cache Hardware ID

[](#2-cache-hardware-id)

```
// Generate once and store
$hardwareId = $client->generateHardwareId();
file_put_contents('/var/app/hwid.txt', $hardwareId);

// Reuse stored value
$hardwareId = file_get_contents('/var/app/hwid.txt');
```

### 3. Handle Network Failures Gracefully

[](#3-handle-network-failures-gracefully)

```
try {
    $result = $client->validateLicense($licenseKey);
} catch (NetworkException $e) {
    // Fall back to offline validation
    $offlineLicense = file_get_contents('/var/app/offline-license.json');
    $result = $client->validateOfflineLicense($offlineLicense);
}
```

### 4. Validate Licenses Periodically

[](#4-validate-licenses-periodically)

```
// Check license every 24 hours
$lastCheck = (int) file_get_contents('/var/app/last-check.txt');
if (time() - $lastCheck > 86400) {
    $result = $client->validateLicense($licenseKey);
    file_put_contents('/var/app/last-check.txt', (string) time());
}
```

Testing
-------

[](#testing)

```
# Install dependencies
composer install

# Run tests
composer test

# Run with coverage
composer test -- --coverage-html coverage/
```

Examples
--------

[](#examples)

See the `/examples` directory for complete working examples:

- `validate.php` - Basic license validation
- `activate.php` - License activation
- `features.php` - Feature flag checking
- `offline.php` - Offline license validation
- `telemetry.php` - Sending telemetry data

Support
-------

[](#support)

- **Website**:
- **Documentation**:
- **API Reference**:
- **Issues**:
- **Email**:

License
-------

[](#license)

MIT License - see LICENSE file for details

Contributing
------------

[](#contributing)

Contributions are welcome! Please read CONTRIBUTING.md for guidelines.

Changelog
---------

[](#changelog)

See CHANGELOG.md for version history.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance84

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 75% 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

Every ~1 days

Total

16

Last Release

82d ago

Major Versions

1.0 → 2.02026-01-24

2.10 → 3.0.02026-02-05

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/47470909?v=4)[vandanafuletra](/maintainers/vandanafuletra)[@vandanafuletra](https://github.com/vandanafuletra)

---

Top Contributors

[![palzinllc](https://avatars.githubusercontent.com/u/224397079?v=4)](https://github.com/palzinllc "palzinllc (3 commits)")[![vandanafuletra](https://avatars.githubusercontent.com/u/47470909?v=4)](https://github.com/vandanafuletra "vandanafuletra (1 commits)")

---

Tags

validationlicenselicense-managementDRMactivationlicensingsoftware licensing

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[composer/semver

Version comparison library that offers utilities, version constraint parsing and validation.

3.3k489.6M671](/packages/composer-semver)[giggsey/libphonenumber-for-php

A library for parsing, formatting, storing and validating international phone numbers, a PHP Port of Google's libphonenumber.

5.0k148.7M414](/packages/giggsey-libphonenumber-for-php)[respect/validation

The most awesome validation engine ever created for PHP

5.9k37.4M381](/packages/respect-validation)[composer/spdx-licenses

SPDX licenses list and validation library.

1.4k184.2M25](/packages/composer-spdx-licenses)[propaganistas/laravel-phone

Adds phone number functionality to Laravel based on Google's libphonenumber API.

3.0k35.7M106](/packages/propaganistas-laravel-phone)[opis/json-schema

Json Schema Validator for PHP

64236.9M185](/packages/opis-json-schema)

PHPackages © 2026

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