PHP integration guide

Activate, verify Ed25519 and deactivate with curl and ext-sodium.

This guide covers the full loop: activate → store → verify on startup → deactivate. It assumes you already have a workspace and a license key.

Requires PHP 8+ with ext-sodium and ext-curl. Verification uses sodium’s native Ed25519 API.

1. Activate

license.php
<?php
const BASE = 'https://keygate.unionuser.com';

function activate(string $licenseKey, string $deviceId): string {
    $ch = curl_init(BASE . '/api/v1/license/activate');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode([
            'license_key' => $licenseKey,
            'identifier' => $deviceId,
            'identifier_type' => 'device',
        ]),
        CURLOPT_TIMEOUT => 15,
    ]);
    $raw = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    $body = json_decode($raw, true);
    if ($status !== 200 || empty($body['success'])) {
        throw new RuntimeException($body['error']['code'] ?? 'ACTIVATE_FAILED');
    }
    return $body['data']['token'];
}

2. Verify offline

verify.php
<?php
const RAW_PUBLIC = 'bf17435ee7b937b3592808941683c21d37c4e124d95d4e8fdd86fe775dd23b11';

function verifyToken(string $token, string $deviceId): array {
    [$payloadB64, $sigB64] = explode('.', $token, 2);
    $signature = base64UrlDecode($sigB64);
    $publicKey = hex2bin(RAW_PUBLIC);

    if (!sodium_crypto_sign_verify_detached($signature, $payloadB64, $publicKey)) {
        throw new RuntimeException('INVALID_SIGNATURE');
    }

    $claims = json_decode(base64UrlDecode($payloadB64), true);
    if (($claims['did'] ?? null) !== $deviceId) {
        throw new RuntimeException('DEVICE_MISMATCH');
    }
    if (($claims['exp'] ?? 0) < time()) {
        throw new RuntimeException('TOKEN_EXPIRED');
    }
    return $claims;
}

function base64UrlDecode(string $value): string {
    $value = strtr($value, '-_', '+/');
    $pad = strlen($value) % 4;
    if ($pad > 0) $value .= str_repeat('=', 4 - $pad);
    return base64_decode($value, true);
}

3. Deactivate

deactivate.php
<?php
$ch = curl_init(BASE . '/api/v1/license/deactivate');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'license_key' => $licenseKey,
        'identifier' => $deviceId,
    ]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

Deployment notes

  • Make sure sodium is enabled; some distributions need it installed separately.
  • Never store keys or tokens in downloadable files under the web root.
  • For desktop apps, prefer a local runtime or a thin local service.