使用文档

时光授权系统文档

从快速开始到 API 对接,全面了解授权系统的使用与集成

授权验证接口

POST /api/verify.php 是核心 API,插件客户端通过它验证授权码的有效性。

接口详情

项说明
URLhttps://license.example.com/api/verify.php
方法POST(同时支持 JSON body / application/x-www-form-urlencoded / GET query)
鉴权HMAC-SHA256 签名(必填)
速率限制60 次/分钟/IP(可在后台调整)
响应格式JSON,支持 AES 加密返回(encrypt=1)

请求参数

参数类型必填说明
license_key string 授权码,格式 LIC-XXXXX-XXXXX-XXXXX-XXXXX
domain string 当前访问域名(系统会自动去除 www. 转为小写)
product string 产品 slug,例 shiguang-quark-qrcode(与后台产品管理一致)
signature string HMAC-SHA256 签名,也可放 X-Api-Signature 请求头
serial int — 序列号,默认 1(防止重放;切换域名/续期会自动 +1)
plugin_version string — 插件版本号(可选,仅用于日志和更新检查)
site_url string — 完整站点 URL,包含协议(可选,仅用于审计日志)
product_secret string — 产品密钥(强校验:开启后必须与服务端 product_secret 一致)
encrypt 0/1 — 是否返回 AES 加密的响应(推荐 1,避免明文传输授权信息)

签名生成

服务端会先把 domain 标准化(去 www.、转小写),请使用 同一份规则 拼接:

sign_data = {domain}|{license_key}|{product}|{serial}
signature = hex(HMAC-SHA256(sign_data, api_secret))

示例(PHP):

<?php
$domain      = 'www.example.com';
$license_key = 'LIC-9C20E-C6A64-B6DE1-D4F90';
$product     = 'shiguang-quark-qrcode';
$serial      = 1;
$api_secret  = 'your-api-secret';  // 与服务端 config.php 中 API_SECRET 一致

// 服务端会对 domain 做 normalize(去 www. + 转小写),这里保持原始提交
$sign_data   = "{$domain}|{$license_key}|{$product}|{$serial}";
$signature   = hash_hmac('sha256', $sign_data, $api_secret);

请求示例

cURL

curl -X POST https://license.example.com/api/verify.php \
  -d "license_key=LIC-9C20E-C6A64-B6DE1-D4F90" \
  -d "domain=www.example.com" \
  -d "product=shiguang-quark-qrcode" \
  -d "plugin_version=1.7.0" \
  -d "serial=1" \
  -d "signature=4f8a2c..."

PHP

<?php
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL        => 'https://license.example.com/api/verify.php',
    CURLOPT_POST       => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'license_key'    => 'LIC-9C20E-C6A64-B6DE1-D4F90',
        'domain'         => 'www.example.com',
        'product'        => 'shiguang-quark-qrcode',
        'plugin_version' => '1.7.0',
        'serial'         => 1,
        'signature'      => $signature,
    ]),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT       => 15,
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);

JavaScript (fetch)

const params = new URLSearchParams({
    license_key: 'LIC-9C20E-C6A64-B6DE1-D4F90',
    domain: 'www.example.com',
    product: 'shiguang-quark-qrcode',
    plugin_version: '1.7.0',
    serial: 1,
    signature: '4f8a2c...'  // 由后端生成后传给前端
});

fetch('https://license.example.com/api/verify.php', {
    method: 'POST',
    body: params
})
.then(r => r.json())
.then(data => console.log(data));

Python

import hmac
import hashlib
import requests

domain      = 'www.example.com'
license_key = 'LIC-9C20E-C6A64-B6DE1-D4F90'
product     = 'shiguang-quark-qrcode'
serial      = 1
api_secret  = 'your-api-secret'

sign_data = f'{domain}|{license_key}|{product}|{serial}'
signature = hmac.new(
    api_secret.encode(),
    sign_data.encode(),
    hashlib.sha256
).hexdigest()

response = requests.post(
    'https://license.example.com/api/verify.php',
    data={
        'license_key':    license_key,
        'domain':         domain,
        'product':        product,
        'plugin_version': '1.7.0',
        'serial':         serial,
        'signature':      signature,
    }
)

print(response.json())

成功响应(明文)

不带 encrypt=1 时返回明文:

{
    "status": "success",
    "message": "授权有效",
    "serial": 1,
    "license": {
        "key":        "LIC-9C20E-C6A64-B6DE1-D4F90",
        "domain":     "www.example.com",
        "type":       "standard",
        "status":     "active",
        "serial":     1,
        "max_sites":  1,
        "expires_at": null
    },
    "product": {
        "name":     "夸克网盘二维码插件",
        "slug":     "shiguang-quark-qrcode",
        "version":  "1.7.0",
        "homepage": "https://www.example.com",
        "author":   "shiguang"
    },
    "update": {
        "version":      "1.7.0",
        "download_url": "https://license.example.com/download/shiguang-quark-qrcode-1.7.0.zip",
        "changelog":    "修复若干已知问题",
        "requires":     "5.0",
        "tested":       "6.4",
        "file_hash":    "sha256:abcd1234..."
    }
}

字段说明:

  • serial:本次验证对应的序列号,每次验签 +1
  • license.type:授权类型(standard / pro / trial)
  • license.status:授权状态(active / expired)
  • license.expires_at:过期时间(ISO 8601 格式,null 表示永久)
  • license.max_sites:授权站点数(通常为 1)
  • product.version:产品最新版本号(来自后台产品管理)
  • update:可选字段,当后台配置了更新信息时返回(用于插件内自动更新提示)

成功响应(加密)

当请求携带 encrypt=1 时,核心字段会用 AES-256-CBC 加密返回:

{
    "valid":     true,
    "serial":    1,
    "encrypted": "base64(iv)::base64(ciphertext)::base64(hmac)"
}

解密密钥 = hash('sha256', api_secret + domain + serial),与 inc/functions.php 中的 decrypt_response() 保持一致。

失败响应

HTTP 状态码message 示例原因
400缺少域名参数 / 缺少授权码参数必填参数缺失
403缺少 API 签名 / 签名验证失败signature 不匹配
429请求过于频繁,请稍后再试触发 IP 频率限制
503服务端 API Secret 未配置管理员未生成 API Secret
200授权码与域名不匹配(算法预校验失败)license_key 与 domain 不匹配
200授权码不存在或已被吊销数据库无此 license
200授权已被禁用 / 已被吊销 / 已被暂停 / 已过期license 状态非 active
200产品已停用产品被管理员禁用
200产品标识验证失败(product_secret 不匹配)客户端 secret 与服务端不一致
200产品归属验证失败授权记录绑定的产品与请求不一致

完整 reason 值请参考 错误码 章节。

客户端缓存建议

建议客户端在本地缓存验证结果:

  • 缓存有效期:7 天
  • 缓存键:license_key + domain
  • 缓存命中:直接使用,不发请求
  • 缓存过期:重新调用 API
  • API 失败:保留缓存(容错),避免业务中断
  • 升级插件:清空缓存(防止 serial 漂移)

完整实现见 PHP 示例 章节。

下一步:阅读 回调说明 了解支付成功后如何生成授权码。