系统授权接入文档
1. 接入流程
IDCG-XXXX-XXXX-XXXX-XXXX
/activate,把授权码绑定到当前域名
/verify,确认授权仍有效
application/json 或表单.env 中设置 LICENSE_SIGN_SALT 为一段随机字符串。
PHP 单文件 SDK
下载 idcgo-license.php.txt 并重命名为 idcgo-license.php,
放到你的系统授权文件中 require;licenseRequest() 已封装 JSON 提交、超时与错误归一,licenseVerifySign() 用于校验返回体签名。
require 'idcgo-license.php';
$res = licenseRequest('/verify', [
'license_key' => 'IDCG-XXXX-XXXX-XXXX-XXXX',
'domain' => 'demo.example.com',
]);
if (($res['code'] ?? -1) !== 0) {
exit($res['message'] ?? '授权校验失败');
}
if (! licenseVerifySign($res['data'], '你的 LICENSE_SIGN_SALT')) {
exit('返回体签名不合法');
}
通用资源(SDK / OpenAPI / 公开查询)统一列在 文档总览,本页不再重复。
2. 核心概念
max_activations 个域名,每条绑定同时锁定服务器 IP。域名解析结果必须与 IP 一致;协议、端口、www. 会被去掉;子域名需要单独绑定,不自动继承根域名。permanent=true 表示永久授权;否则以 expires_at 与 days_left 为准。max_activations=0 表示跟随系统默认,不代表不能绑定;实际名额以成功响应里的数值为准。/verify。成功响应会带回后台当前的校验间隔与离线宽限,请以接口返回为准,不要写死。offline_grace_hours 仍未成功校验,再判定授权失效;0 表示不设宽限。data.sign 是对其余字段的 HMAC-SHA256,用签名盐值验签即可确认未被篡改。2.1 服务器 IP 检测
授权服务端会在激活、在线校验时自动识别请求的出口公网 IP,写入绑定记录与校验日志,
并在成功响应里返回 server_ip。客户端不需要读取网卡,也不需要手动上报 IP。
/activate、/verify、/deactivate 时自动检测,并用于比对绑定 IP。data.server_ip 与 data.server_ip_version(IPv4 / IPv6)。/activate 与 /verify 会返回 1014 并拒绝。更换 IP 请在用户中心重新绑定,详见下方「IP 一致性校验」。
公开查询页 /check 也支持直接输入域名或服务器 IP, 返回该 IP 最近一次校验对应的授权,便于客服或用户自助核对。后台侧检测见 用户中心 API · 服务器 IP 检测。
域名 + IP 双重校验
绑定域名时填写的服务器 IP 会被锁定为该绑定记录的校验基准。之后每次 /activate、/verify,
服务端都会拿请求域名与本次请求的出口 IP 逐项比对,域名与 IP 必须同时匹配才放行。
1014,请重新绑定以写入 IP 基准。1014,不刷新校验时间、不增加校验次数,并在绑定记录里标记「IP 不一致」。/verify 必须同时传 license_key 与 domain。{
"code": 1014,
"message": "服务器 IP 与绑定不一致(绑定 38.76.166.40,当前 112.48.82.6),请在用户中心重新绑定后再试",
"data": null
}
IP 检测接口
客户端可以在启动时调用 GET /v1/ip 获取自己的出口公网 IP,用于展示或排查网络问题。
该接口不校验授权,限流与其它接口一致。
curl "https://api.idcxb.com/api/v1/ip"
{
"code": 0,
"message": "ok",
"data": {
"ip": "38.76.166.40",
"remote_ip": "38.76.166.40",
"version": "IPv4",
"public": true,
"forwarded": false,
"detected_at": "2026-10-28 22:10:00"
}
}
同时,/activate 与 /verify 的成功响应也会带回 server_ip,
客户端可以缓存并在后台展示,方便和用户核对。
3. 接口一览
| 接口 | 方法 | 用途 |
|---|---|---|
| /v1/ping | GET | 健康检查,确认授权服务器可达 |
| /v1/ip | GET | 服务器 IP 检测,返回调用方出口公网 IP |
| /v1/activate | POST | 首次激活,把授权码绑定到当前域名 |
| /v1/activate | GET | 链接直接激活,参数走 query |
| /v1/verify | POST | 在线校验,建议每 1 分钟调用一次 |
| /v1/deactivate | POST | 解绑,释放域名名额(迁移服务器时用) |
verify_interval_minutes 与
offline_grace_hours 就是后台当前的授权策略;客户端应以此为准,
不要写死在代码里。
4. 健康检查
GET
https://api.idcxb.com/api/v1/ping
不校验任何参数,用于部署后确认授权服务器可达。
curl "https://api.idcxb.com/api/v1/ping"
{
"code": 0,
"message": "ok",
"data": {
"server_time": "2026-10-27 20:18:00",
"server_ip": "38.76.166.40",
"server_ip_version": "IPv4"
}
}
5. 激活
POST
https://api.idcxb.com/api/v1/activate
把授权码绑定到当前部署的域名,服务端会校验该域名当前解析到的 IP 与请求出口 IP 是否一致,并一并锁定。首次部署时调用一次,成功后把结果缓存到本地。
| 参数 | 必填 | 说明 |
|---|---|---|
| license_key | 是 | 授权码 |
| domain | 是 | 当前部署域名,须为真实域名 |
| machine_code | 否 | 机器码,便于排查多机使用 |
curl -X POST "https://api.idcxb.com/api/v1/activate" \ -d "license_key=IDCG-ABCD-EFGH-JKLM-NPQR" \ -d "domain=demo.example.com"
{
"code": 0,
"message": "激活成功",
"data": {
"license_key": "IDCG-ABCD-EFGH-JKLM-NPQR",
"domain": "demo.example.com",
"status": "active",
"status_text": "正常",
"permanent": false,
"activated_at": "2026-10-27 20:18:00",
"expires_at": "2027-10-27 20:18:00",
"days_left": 365,
"max_activations": 1,
"activation_count": 1,
"verify_interval_minutes": 1,
"offline_grace_hours": 72,
"server_ip": "38.76.166.40",
"server_ip_version": "IPv4",
"server_time": "2026-10-27 20:18:00",
"sign": "…"
}
}
https://api.idcxb.com/api/v1/activate?license_key=...&domain=...,返回同样的 JSON。
6. 在线校验
POST
https://api.idcxb.com/api/v1/verify
建议每 1 分钟调用一次。license_key 与 domain 都必填,
服务端会同时核对域名和请求出口 IP,任一项不一致即返回 1014。
curl -X POST "https://api.idcxb.com/api/v1/verify" \ -d "license_key=IDCG-ABCD-EFGH-JKLM-NPQR" \ -d "domain=demo.example.com"
{
"code": 0,
"message": "ok",
"data": {
"license_key": "IDCG-ABCD-EFGH-JKLM-NPQR",
"domain": "demo.example.com",
"status": "active",
"status_text": "正常",
"permanent": false,
"expires_at": "2027-10-27 20:18:00",
"days_left": 365,
"max_activations": 1,
"activation_count": 1,
"verify_interval_minutes": 1,
"offline_grace_hours": 72,
"server_ip": "38.76.166.40",
"server_ip_version": "IPv4",
"server_time": "2026-10-27 20:18:00",
"sign": "…"
}
}
offline_grace_hours,在宽限期内继续运行并重试。
7. 解绑
POST
https://api.idcxb.com/api/v1/deactivate
迁移服务器或更换域名时调用,释放一个域名名额。license_key 与 domain 都必填。
curl -X POST "https://api.idcxb.com/api/v1/deactivate" \ -d "license_key=IDCG-ABCD-EFGH-JKLM-NPQR" \ -d "domain=demo.example.com"
成功时返回 code=0,message 为「解绑成功」。
子域名需要单独绑定与解绑,解绑时按域名精确匹配。
8. 链接授权(免代码)
不想写代码、或者想把授权交给客户自己完成时,直接用链接授权: 把带授权码的链接发给对方,打开后填上域名、点一下「确认授权」就好了。
# 网页版:打开就能填域名,适合直接发给客户 https://api.idcxb.com/activate?key=IDCG-ABCD-EFGH-JKLM-NPQR&domain=demo.example.com # 接口版:GET 直接返回 JSON,适合脚本 / 命令行 curl "https://api.idcxb.com/api/v1/activate?license_key=IDCG-ABCD-EFGH-JKLM-NPQR&domain=demo.example.com"
9. 授权回调(callback)
在链接后面加一个 callback,授权成功后会 302 跳回这个地址,
并把授权信息一并带过去。你的程序在那个入口验签、落库即可,客户全程不用复制粘贴。
# 授权成功后跳回 https://demo.example.com/license-callback
https://api.idcxb.com/activate?key=IDCG-ABCD-EFGH-JKLM-NPQR&domain=demo.example.com&callback=https://demo.example.com/license-callback
| 参数 | 说明 |
|---|---|
| license_code | 0 表示成功 |
| license_key | 授权码 |
| domain | 本次绑定的域名 |
| payload | base64 后的授权信息 JSON(含到期时间、绑定上限、功能列表等) |
| sign | 对 payload 的 HMAC-SHA256,用签名盐值验签 |
客户程序端的接收示例:
// /license-callback.php —— 放在你自己的站点上 $payload = $_GET['payload'] ?? ''; $sign = $_GET['sign'] ?? ''; // 1. 验签,防止参数被篡改 $expect = hash_hmac('sha256', $payload, '你的签名盐值'); if (! hash_equals($expect, $sign)) { exit('签名校验失败'); } // 2. 解开授权信息 $license = json_decode(base64_decode($payload), true); // 3. 写入自己的配置或数据库 file_put_contents(__DIR__ . '/license.json', json_encode($license, JSON_UNESCAPED_UNICODE)); header('Location: /admin?licensed=1');
domain 同域的地址(含子域),填别的域名会被忽略,
以免被当成开放重定向跳板;授权失败时不跳转,直接在本页显示原因,方便改完重试。
10. 请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| license_key | 是 | 授权码,形如 IDCG-XXXX-XXXX-XXXX-XXXX,大小写与连字符会被自动归一化 |
| domain | 是 | 当前部署域名,协议、端口、www. 会被自动去掉;子域名需要单独绑定 |
| machine_code | 否 | 机器码,便于排查同一授权在多台机器上的使用情况 |
11. 调用示例
激活(PHP cURL):
// 首次部署时调用一次,成功后把结果缓存到本地 $payload = [ 'license_key' => 'IDCG-ABCD-EFGH-JKLM-NPQR', 'domain' => $_SERVER['HTTP_HOST'], ]; $ch = curl_init('https://api.idcxb.com/api/v1/activate'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($payload), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, ]); $res = json_decode(curl_exec($ch), true); curl_close($ch); if (($res['code'] ?? -1) !== 0) { die('授权校验失败:' . ($res['message'] ?? '未知错误')); } // $res['data'] 内含到期时间、可绑定数量、服务器 IP 等
定时校验(建议放进计划任务,每 1 分钟一次):
// 校验失败时不要立刻停机,先看离线宽限期 $res = post('https://api.idcxb.com/api/v1/verify', $payload); if (($res['code'] ?? -1) === 0) { cache_set('license_ok_at', time()); } elseif (time() - cache_get('license_ok_at') > 72 * 3600) { // 超出 72 小时宽限期,才真正停用 die('授权已失效:' . $res['message']); }
12. 返回码
| code | 含义 | 建议处理 |
|---|---|---|
| 0 | 校验通过 | 正常放行 |
| 1001 | 缺少必要参数 | 检查 license_key 与 domain |
| 1002 | 授权码不存在 | 提示用户核对授权码 |
| 1003 | 授权已禁用 | 联系管理员 |
| 1004 | 授权已吊销 | 不可恢复,需重新申请授权 |
| 1005 | 授权已过期 | 联系管理员续期 |
| 1006 | 绑定数量已达上限 | 先在用户中心解绑旧域名 |
| 1007 | 域名未绑定 | 先调用 activate |
| 1011 | 域名已被其它授权占用 | 更换域名或先解绑 |
| 1012 | 请求过于频繁 | 降低校验频率 |
| 1013 | 未绑定域名与服务器 IP | 提示用户先绑定域名与 IP 再使用授权码 |
| 1014 | 服务器 IP 与绑定不一致 | 在用户中心重新绑定该域名,更新服务器 IP |
200,必须判断 JSON 里的 code,不能只看 HTTP 状态码。429 表示触发 IP 限流,请按 Retry-After 退避后重试。
13. 响应验签
返回体的 data 中带有一个 sign 字段,是对除 sign 外所有字段
按键名排序后做 JSON 编码、再用签名盐值做 HMAC-SHA256 得到的。客户端用同样的方式重算一次即可确认结果未被篡改。
function verifySign(array $data, string $salt): bool { $sign = $data['sign'] ?? ''; unset($data['sign']); ksort($data); $expect = hash_hmac('sha256', json_encode($data, JSON_UNESCAPED_UNICODE), $salt); return hash_equals($expect, $sign); }
14. 接入检查清单
- 激活成功后把
data缓存到本地,避免每次启动都重新激活。 - 校验间隔使用接口返回的
verify_interval_minutes,不要写死。 - 校验失败先走
offline_grace_hours宽限,不要立即停机。 - 每次成功响应都验签,确认
sign与本地重算结果一致。 - 迁移服务器前先调用
/deactivate释放旧域名,避免触发绑定上限。 - 服务器 IP 以调用方出口 IP 为准,客户端无需读取网卡;绑定域名时需确保域名解析到该 IP。
- 子域名需要单独绑定,根域名不会自动覆盖子域名。
- 日志里不要记录完整授权码,展示时至少打码中间两段。
15. 常见问题
返回 1006「绑定数量已达上限」怎么办?
先到用户中心解绑不再使用的域名,或联系管理员提高该授权的绑定上限,然后重新调用激活。
换了域名,需要重新申请授权吗?
不需要。先调用 /deactivate 解绑旧域名,再用新域名调用 /activate。
子域名需要单独绑定吗?
需要。根域名与子域名按完全一致的域名分别校验,使用子域名时请单独绑定该子域名。
校验接口偶尔超时,会不会导致客户停机?
不会。按 offline_grace_hours 继续运行并重试即可,只有超过宽限期仍未校验成功才判定失效。
可以只做本地校验、不连服务器吗?
不建议。授权状态、续期和域名变更都以服务端为准,长期离线会错过状态变化。
服务器 IP 变了,需要重新绑定吗?
需要。授权会同时校验域名与服务器 IP,IP 变化后 /verify 会返回 1014;到用户中心重新绑定该域名(点「检测」或填写新 IP)即可更新基准。
检测到的是 CDN 或代理 IP,怎么办?
授权绑定要求域名解析结果与服务器 IP 一致,CDN 节点 IP 无法作为绑定基准。请为授权接口使用直接解析到源站 IP 的域名,或调整解析后再绑定。
16. 公开授权查询
GET
https://api.idcxb.com/api/v1/check?q=example.com
无需登录即可核验授权真伪,与官网「授权查询」页面同一套判断逻辑,适合放在客户官网、帮助中心或工单页。 传域名会精确匹配已绑定的域名,传服务器 IP 会匹配绑定记录里的 IP,传授权码则直接查该授权。 每个 IP 每分钟 30 次。
| 参数 | 必填 | 说明 |
|---|---|---|
q | 是 | 域名、服务器 IP 或授权码,3–128 个字符;授权码可省略横线 |
curl "https://api.idcxb.com/api/v1/check?q=example.com"
{
"code": 0,
"message": "ok",
"data": {
"query": "example.com",
"type": "domain",
"found": true,
"license": {
"masked_key": "IDCG-****-****-****-8F2K",
"status": "active",
"status_label": "授权有效",
"status_note": null,
"expires_at": "2027-10-27 20:18:00",
"days_left": 363,
"max_activations": 3,
"active_count": 1,
"matched_domain": "example.com",
"covered_by": null,
"binding_text": "example.com"
}
}
}
| status | 含义 | 建议提示 |
|---|---|---|
| active | 授权有效 | 可正常使用 |
| unbound | 已签发但未绑定域名 | 引导用户到用户中心绑定 |
| pending | 未激活 | 提示先完成激活 |
| expired | 已过期 | 引导续期 |
| disabled | 已禁用 | 联系管理员 |
| revoked | 已吊销 | 不可恢复,需重新申请授权 |
found: false(HTTP 200),不区分「授权不存在」与「域名未绑定」,避免被枚举;
参数不合法返回 42201。接口结果实时查询,请勿在前端长时间缓存。