LicenseV 授权验证 API
用于脚本授权验证的 HTTP API。验证授权码是否有效、是否到期、绑定设备。
所有接口入参/出参均为
application/json,字符编码 UTF-8。Base URL
https://yanzheng.yunzai.love
授权流程
推荐的调用流程:
# 1. 脚本启动时验证一次 POST /api/verify → 检查 key 有效性 + 绑定设备 # 2. 脚本运行中定时心跳(可选,建议每 5~30 分钟) POST /api/heartbeat → 更新设备活跃时间 # 3. 异常时可用 ping 检查服务连通性 GET /api/ping
POST /api/verify
验证授权码。首次携带 device_id 会自动绑定设备。
Request
{
"key": "YZ-XXXX-XXXX-XXXX", // 必填,授权码
"device_id": "设备唯一标识", // 可选,不传则不绑定设备
"device_name":"设备名称" // 可选,便于后台识别
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| key | string | 是 | 授权码,格式 YZ-XXXX-XXXX-XXXX |
| device_id | string | 否 | 设备唯一标识。传了会绑定设备并校验设备数上限;不传则只验证授权码本身 |
| device_name | string | 否 | 设备别名,仅在 device_id 存在时有效 |
Response 200(验证通过)
{
"code": 200,
"message": "验证通过",
"data": {
"key": "YZ-XXXX-XXXX-XXXX",
"status": "active",
"expire_time": "2027-05-09 23:59:59", // null = 永久有效
"expire_timestamp": 1809835199, // Unix 时间戳
"days_left": 365, // 剩余天数,null = 永久
"never_expires": false,
"max_devices": 3, // 允许绑定的最大设备数
"device_bound": true, // 本次是否绑定了设备
"note": "备注信息"
},
"server_time": "2026-05-09 12:00:00"
}
Response 401(授权码无效)
{ "code":401, "message":"授权码无效", "data":[], "server_time":"..." }
Response 403(已过期 / 已禁用 / 设备上限 / IP限制)
{ "code":403, "message":"授权已于 2025-01-01 到期", "data":[], "server_time":"..." }
| message | 含义 |
|---|---|
| 授权码已被禁用 | 管理员在后台手动禁用了该 key |
| 授权已于 YYYY-MM-DD 到期 | key 已超过有效期 |
| 当前IP未授权访问 | 该 key 设置了 IP 白名单,当前 IP 不在其中 |
| 设备绑定数量已达上限(N) | 绑定的设备数超过了 max_devices 限制 |
POST /api/heartbeat
设备心跳。更新设备最后活跃时间,用于后台监控设备在线状态。
Request
{
"key": "YZ-XXXX-XXXX-XXXX", // 必填
"device_id": "设备唯一标识" // 必填,必须已绑定
}
Response 200
{
"code":200,
"message":"心跳已更新",
"data":{ "key":"YZ-...", "device_id":"dev-001", "last_heartbeat":"2026-05-09 12:00:00" },
"server_time":"..."
}
Response 404
{ "code":404, "message":"设备未绑定,请先调用 verify" }
GET /api/ping
服务连通性测试,无需任何参数。
Response 200
{
"code":200,
"message":"pong",
"data":{
"service":"License Validation System",
"version":"2.0",
"stats":{ "total_keys":10, "active_keys":8 }
},
"server_time":"..."
}
状态码速查
| code | 含义 | 处理建议 |
|---|---|---|
| 200 | 成功 | 正常继续 |
| 400 | 缺少必填参数 | 检查请求体 |
| 401 | 授权码不存在 | 检查 key 是否正确,或联系管理员 |
| 403 | 授权码已过期 / 禁用 / IP限制 / 设备满 | 根据 message 判断具体原因 |
| 404 | 接口不存在,或 heartbeat 时设备未绑定 | 先调 verify 再调 heartbeat |
| 405 | 请求方法错误 | verify/heartbeat 必须用 POST |
| 429 | 请求过于频繁 | 降低频率,默认限制 60秒30次 |
Python 示例
一行验证(推荐)
# pip install 无需额外依赖,纯标准库 from client import check check("https://yanzheng.yunzai.love", "YZ-XXXX-XXXX-XXXX") # 验证失败自动 exit(1),通过则继续执行
获取详细信息
from client import check info = check("https://yanzheng.yunzai.love", "YZ-XXXX-XXXX-XXXX") print(f"到期: {info['expire_time']}, 剩余 {info['days_left']} 天")
手动控制流程
from client import LicenseClient lc = LicenseClient("https://yanzheng.yunzai.love", "YZ-XXXX-XXXX-XXXX") # 验证 if lc.verify(): print(f"有效,剩余 {lc.days_left()} 天") # ... 你的业务代码 ... lc.heartbeat() # 心跳 else: print(f"失败: {lc.last_error}")
使用 requests 库(不依赖 client.py)
import requests r = requests.post("https://yanzheng.yunzai.love/api/verify", json={"key":"YZ-XXXX-XXXX-XXXX", "device_id":"my-device-001"}) data = r.json() if data["code"] == 200: print(f"✓ 剩余 {data['data']['days_left']} 天") else: print(f"✕ {data['message']}")
JavaScript / 前端 示例
// 验证授权码 const resp = await fetch('https://yanzheng.yunzai.love/api/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: 'YZ-XXXX-XXXX-XXXX', device_id: 'browser-' + navigator.hardwareConcurrency, device_name: navigator.userAgent.slice(0,50) }) }); const data = await resp.json(); if (data.code === 200) { console.log(`有效,剩余 ${data.data.days_left} 天`); } else { console.error(data.message); }
curl 测试
# 验证 curl -X POST https://yanzheng.yunzai.love/api/verify \ -H "Content-Type: application/json" \ -d '{"key":"YZ-XXXX-XXXX-XXXX","device_id":"test-001"}' # 心跳 curl -X POST https://yanzheng.yunzai.love/api/heartbeat \ -H "Content-Type: application/json" \ -d '{"key":"YZ-XXXX-XXXX-XXXX","device_id":"test-001"}' # 连通测试 curl https://yanzheng.yunzai.love/api/ping
频率限制
每个 IP 每 60 秒最多 30 次请求。超出返回 429,响应头带 Retry-After。
建议:脚本启动时调一次 verify,运行中 heartbeat 间隔不小于 1 分钟。