code-heaven/license-sdk 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

code-heaven/license-sdk

Composer 安装命令:

composer require code-heaven/license-sdk

包简介

Vendor SDK for the Code Heaven Developer License API (validation, domain activation, updates, downloads).

README 文档

README

Vendor SDK for the Code Heaven Developer License API. Use it inside your plugin/theme/app to validate licenses, activate and free domain seats, check for updates, and fetch signed download URLs.

This is the vendor server-to-server flow. Authentication is a single vendor API key (X-CH-Vendor-Key), not the buyer OAuth flow.

  • Base URL: https://api.code-heaven.com/v1
  • PHP 8.0+
  • No hard runtime dependencies (cURL or file_get_contents); pluggable HTTP so it works happily inside WordPress via wp_remote_request.

Install

composer require code-heaven/license-sdk

Quick start: validate and gate

use CodeHeaven\License\Client;
use CodeHeaven\License\LicenseException;
use CodeHeaven\License\TransportException;

$client = new Client('YOUR_VENDOR_KEY', [
    'cacheTtl'     => 12 * 3600,        // serve a fresh answer for 12h
    'offlineGrace' => 14 * 24 * 3600,   // keep working up to 14 days if the API is down
]);

try {
    $res = $client->validate('LICENSE-KEY', 'shop.example.com', 'booknetic-pro');
} catch (LicenseException $e) {
    // 403: invalid / expired / domain_not_activated  ($e->apiCode tells you which)
    bail("License problem: {$e->apiCode}");
} catch (TransportException $e) {
    // API unreachable AND no cached valid result within grace.
    bail('License server unreachable.');
}

if ($res['valid']) {
    enable_premium_features();
} else {
    // $res['status'] is one of: valid | invalid | expired | domain_not_activated | revoked
    disable_premium_features($res['status']);
}

validate() returns the decoded API body plus two SDK markers:

key meaning
valid bool
status valid | invalid | expired | domain_not_activated | revoked
product product slug (or null)
expiresAt ISO 8601 string or null
activations [{domain, activatedAt}, ...]
seatLimit int
_cached present & true when served from cache
_offline present & true when served from cache during an outage

Activate a seat on first run

When validate() returns domain_not_activated (a LicenseException with apiCode === 'domain_not_activated'), claim a seat:

use CodeHeaven\License\SeatLimitException;

try {
    $client->activateDomain('LICENSE-KEY', 'shop.example.com');
} catch (SeatLimitException $e) {
    // 409 — buyer has used every seat; prompt them to deactivate another site.
}

Check for and apply an update

$update = $client->checkUpdate('LICENSE-KEY', 'booknetic-pro', '4.1.0', 'shop.example.com');

if ($update['hasUpdate']) {
    // latestVersion + changelog[{version,date,notes}]
    $dl = $client->download('LICENSE-KEY', 'booknetic-pro', 'shop.example.com', $update['latestVersion']);
    // $dl['url'] is a short-lived signed package URL; $dl['expiresAt'] tells you when it dies.
    download_and_install_zip($dl['url']);
}

Free the seat on uninstall

$client->deactivateDomain('LICENSE-KEY', 'shop.example.com');

Caching and offline grace

validate() is cached so repeated calls in one request never hit the wire twice, and the result persists across requests when you supply a persistent cache:

  • cacheTtl — how long a cached answer is considered fresh. Within this window validate() returns the cached body without any network call.
  • offlineGrace — how long a cached valid answer may be served after it goes stale, but only when the API is unreachable. This stops a transient outage from locking out paying customers. Served results carry _offline => true.

Persistent caches:

use CodeHeaven\License\FileCache;
use CodeHeaven\License\TransientCache;

// Outside WordPress:
new Client($key, ['cache' => new FileCache('/var/cache/myplugin')]);

// Inside WordPress (rides transients / the object cache):
new Client($key, ['cache' => new TransientCache('myplugin_')]);

The default is an in-process ArrayCache (no cross-request persistence, so no offline grace across requests — supply FileCache/TransientCache in production).

Custom HTTP transport (WordPress, Guzzle, …)

Inject any callable as http. It receives (method, url, headers, ?body) and must return ['status' => int, 'headers' => array, 'body' => string], or throw TransportException on a connection failure (which triggers offline grace).

new Client($key, [
    'http' => function (string $method, string $url, array $headers, ?string $body): array {
        $res = wp_remote_request($url, compact('method', 'headers', 'body') + ['timeout' => 15]);
        if (is_wp_error($res)) {
            throw new \CodeHeaven\License\TransportException($res->get_error_message());
        }
        return [
            'status'  => (int) wp_remote_retrieve_response_code($res),
            'headers' => wp_remote_retrieve_headers($res)->getAll(),
            'body'    => (string) wp_remote_retrieve_body($res),
        ];
    },
]);

See examples/gate-plugin.php for a complete, fail-safe WordPress gate (validate → activate-on-first-run → admin nag → deactivate-on-uninstall).

Exceptions

All extend CodeHeaven\License\CodeHeavenException and expose ->statusCode, ->apiCode, ->response.

Exception HTTP When
AuthException 401 Vendor key missing/invalid (your packaging bug)
LicenseException 403 license_invalid / expired / domain_not_activated
SeatLimitException 409 seat_limit_exceeded on activateDomain()
RateLimitException 429 Rate limited (->retryAfter holds the hint, if any)
TransportException API unreachable and no usable cached result
CodeHeavenException 4xx/5xx Any other non-2xx response

Note: an invalid or expired license that the API reports with HTTP 200 and valid:false is returned as data, not thrown. The API only throws LicenseException for the 403 cases above.

Development

composer install
composer test      # phpunit

License

MIT.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-08

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固