快速入门

1. 获取授权码

产品页面 购买授权,或在控制台中获取已购授权的授权码。

2. 验证授权

使用 HTTP GET 请求验证授权:

curl "https://你的域名/api/verify?license_key=ZFS-XXXX-XXXX&domain=example.com&product_code=my-product"

3. 处理响应

验证成功返回 JWT Token 格式的响应:

{
  "verified": true,
  "license_id": "LIC-XXXX",
  "product_code": "my-product",
  "expires_at": "2026-12-31",
  "token": "eyJhbGciOiJSUzI1NiIs..."
}

授权管理

购买授权后,你可以在控制台查看与管理自己的所有授权。

查看授权

进入「我的授权」页面,可看到全部授权及其状态:有效 / 试用中 / 已过期 / 无效,以及到期时间与最大绑定域名数

域名管理

进入「域名管理」页面,按产品分组查看每个授权已绑定的域名,支持添加与删除绑定域名(删除需输入域名二次确认)。可绑定数量受产品设置与系统配置约束(默认 3 个)。

绑定的域名会参与客户端运行时校验:你的代码在被部署的站点上运行时,SDK 上报当前域名并与绑定列表比对,不在列表内将拒绝服务——这是防止授权被盗用的一道关键防线。

到期与续期

授权到期后将无法通过验证。到期前可在对应授权中查看剩余天数,并按提示续期或升级。

一键授权打包

上传项目 ZIP -> 自动注入 SDK -> 加密 -> 下载,无需写一行代码

1. 上传项目 ZIP

在管理后台选择产品,上传你的 PHP 项目 ZIP 文件。

2. 自动注入 + 加密

系统自动检测开发平台,注入授权配置和 Guard 保护调用,可选开启 AES-256-GCM 加密。

3. 下载分发

打包产物包含加密代码 + License 文件 + Loader 安装说明,交给客户部署即可。

无需 composer require、无需编写验证代码、无需手动配置 —— 系统自动完成所有注入工作。

API 参考

GET /api/verify

验证授权(主要端点)

参数类型必填说明
license_keystring授权码
domainstring绑定域名
ipstring客户端 IP
product_codestring产品代码

返回: verified, token (JWT), expires_at, domain

POST /api/refresh

刷新 JWT Token(需 Authorization: Bearer header)

返回: token (新 JWT)

GET /api/key/{kid}

获取公钥(客户端验签用)

路径参数: kid — 密钥 ID,返回 PEM 格式公钥

GET /api/check-revoked

查询授权是否被吊销(需有效 token)

GET /api/health

健康检查(监控用)

代码加密

AES-256-GCM 认证加密 + C 扩展运行时解密,让代码固若金汤

特性说明
加密算法AES-256-GCM 认证加密(防篡改)
密钥派生PBKDF2-SHA256,10万次迭代,每文件独立随机盐
文件格式ZFSE 加密头 + 密文(头部为定长二进制元数据)
License 保护RSA-SHA256 签名,支持域名绑定和过期控制
运行时解密C 扩展 Hook 编译流程,内存中解密,磁盘永为密文
反调试检测调试器扩展,生产环境有调试器时拒绝执行

客户侧安装步骤

# 1. 安装 Loader 扩展(选择对应 PHP 版本)
cp zfshang_loader-php8.1.so $(php -r 'echo ini_get("extension_dir");')/zfshang_loader.so
echo 'extension=zfshang_loader' >> /www/server/php/81/etc/php.ini

# 2. 放置 License 文件到项目根目录
cp zf-license.dat /var/www/html/

# 3. 重启 PHP
systemctl restart php8.1-fpm

# 4. 验证
php -m | grep zfshang

客户端 SDK 与多平台支持

绝大多数用户使用「一键授权打包」即可,系统会自动注入合适的适配器并加密,无需手动集成。本节面向需要手动集成 SDK的场景(如已有项目、或需要更精细的控制)。

平台适配

适配器适用场景
WpAdapterWordPress 主题 / 插件,自动 Hook WP 生命周期
GenericAdapterLaravel、ThinkPHP、原生 PHP 及其他框架 / standalone(需 ext-curl)

手动集成步骤

# 1. 安装 SDK(Composer)
composer require zfshang/license-client

# 2. 在入口引入并初始化 Guard
require_once __DIR__ . '/vendor/autoload.php';
use ZfLicense\Guard;
Guard::protect('/path/to/zf-license.dat');

# 3. 激活(CLI,首次部署到客户站点时执行一次)
php zf-activate.php --license-key=ZFS-XXXX-XXXX --license-id=LIC-XXXX [--domain=example.com]
激活是「客户端本地写入 token 缓存」的过程:CLI 或浏览器访问 zf-activate.php 完成(Web 激活做了同源校验,跨站 POST 会被拒绝)。激活后立即生效,无需重启服务。授权码与授权 ID 填反时激活逻辑会容错尝试两种顺序。

完整接入与 API 详见 SDK 包内 sdk/zfshang-license-client/README.md

加密配额

非 VIP 用户每月可加密次数有限(默认 5 次 / 月),配额按自然月(YYYYMM)重置。在加密页面可查看本月已用 / 剩余次数。

账户类型月加密次数可上传格式单文件上限
普通用户5 次 / 月.php500 KB
VIP不限.php / .zip.php 5 MB / .zip 100 MB
当月次数用尽后再提交加密会提示「本月加密次数已用完,请升级 VIP」。升级 VIP 后可解除限制并支持 ZIP 批量加密与更大文件。

完整安装部署指南

从零开始的部署教程

从宝塔面板配置、系统安装、Loader 编译到代码加密的全流程,新手友好。

查看完整安装指南 →

⏰ 定时任务(Cron)部署

cron/ 目录下有 4 个后台脚本,仅允许 CLI 执行(每个脚本开头都有 PHP_SAPI !== 'cli' 守卫,通过 Web 访问会返回 403 Forbidden)。请使用站点 PHP 可执行文件的绝对路径配置 crontab(以下以宝塔默认路径为例,请替换为你自己的 php 路径与项目路径)。

脚本作用建议频率
cron/backup_database.php每日数据库自动备份0 3 * * *
cron/send_emails.php消费邮件队列(需开启异步邮件)* * * * *
cron/expiration_reminder.php授权到期前 30/7/1 天邮件提醒0 4 * * *
cron/process_package_queue.php处理「SDK 模式」打包队列* * * * *

示例 crontab

# 替换为你的项目绝对路径与 php 可执行文件路径
PROJECT=/www/wwwroot/zfshang.cn
PHP=/www/server/php/81/bin/php

# 每日 03:00 数据库备份
0 3 * * * $PHP $PROJECT/cron/backup_database.php >> /dev/null 2>&1

# 每分钟:邮件队列 + 打包队列
* * * * * $PHP $PROJECT/cron/send_emails.php >> /dev/null 2>&1
* * * * * $PHP $PROJECT/cron/process_package_queue.php >> /dev/null 2>&1

# 每日 04:00 到期提醒
0 4 * * * $PHP $PROJECT/cron/expiration_reminder.php >> /dev/null 2>&1
process_package_queue.php 每次只处理 1 个任务,并写入 storage/package_queue_heartbeat 心跳文件,可据此监控 cron 是否在正常运行。

🛡️ 错误处理与安全

  • 生产环境不暴露错误详情public/index.php 捕获未处理异常后只记录日志(storage/logs/app.log),向用户返回通用 public/500.html,绝不回显堆栈、SQL 或路径。
  • 调试模式由环境变量 APP_DEBUG 控制(默认关闭)。仅临时排查时设置 APP_DEBUG=true(php-fpm / Docker 环境变量),排查完务必改回,否则会泄露错误详情。
  • config/database.php 含数据库明文密码,位于 public/ 之外;标准部署 Web 根目录指向 public/,该文件不可被直接下载。参考 install/nginx.conf.example,已对 /config/storage/app 做了 deny all 防御性拦截。

🔒 Loader 下载限流部署

后台「系统设置 → 下载设置」可配置每个 IP 在指定周期内的 Loader 可下载次数,防止 .so 被批量爬取。 但 Loader 文件默认放在 Web 根目录下,会被 Nginx 当作静态文件直接返回、不经过 PHP, 因此限流设置默认不会生效。需在本站点的 Nginx 配置中加一段规则,把 /downloads/loaders/ 交由 PHP 处理,限流才会真正运行。

① 添加 Nginx 规则

在站点 server { } 块内、与现有 PHP 处理段同级,加入:

location ^~ /downloads/loaders/ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    fastcgi_param DOCUMENT_ROOT $document_root;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;  # 与你的 PHP-FPM socket 保持一致
}

② 重载 Nginx

nginx -t && systemctl reload nginx

③ 验证是否生效

用浏览器或 curl 访问一次 Loader 下载地址:

curl -I https://你的域名/downloads/loaders/zfshang_loader-php8.1.so

能正常返回 200 即说明请求已交给 PHP 处理;若用同一未登录 IP、且额度设为 1,快速第 2 次访问应返回 429 限流响应。

已登录管理员不受限流影响,可在后台正常批量下载多个 PHP 版本 Loader。示例配置见 install/nginx.conf.example 的「Loader 下载」段。
若不添加此 Nginx 段,Loader 仍可公开下载,但后台的「下载设置」限额形同虚设。如需限流生效,必须完成上述部署。

常见问题

授权验证失败怎么办?

检查授权码是否正确、是否已过期、域名是否匹配。可在控制台查看授权状态。

如何更换绑定域名?

登录控制台,在对应授权中点击"域名管理",输入新域名即可。

API 调用频率限制是多少?

默认每 IP 每分钟 30 次验证请求。可在控制台绑定 IP 获得更高频率。

加密后的代码能破解吗?

AES-256-GCM 是目前最安全的对称加密算法之一,配合每文件独立密钥,破解一个文件不影响其他文件。

Loader 扩展需要额外付费吗?

ZFShang Loader 扩展完全免费,支持 PHP 7.4 ~ 8.3。

如何更换加密密钥?

在管理后台「代码加密」页面点击「轮换加密密钥」。注意:轮换后已加密的旧文件需重新打包。