仪表盘
卡密总数
{{ ds.total }}
未使用
{{ ds.unused }}
已使用
{{ ds.used }}
已禁用
{{ ds.disabled }}
今日验证
{{ ds.today_total }}
成功 {{ ds.today_success }} 次
成功率
{{ ds.today_total>0?Math.round(ds.today_success/ds.today_total*100):0 }}%
各软件卡密分布
最近验证
| 卡密 | 软件 | 结果 | 机器码 | IP | 归属地 | 时间 |
|---|---|---|---|---|---|---|
| {{ l.card_key }} | {{ l.software_name||'-' }} | {{ l.result?'成功':'失败' }} | {{ l.machine_code||'-' }} | {{ l.ip }} | {{ l.ip_location||'-' }} | {{ fmt(l.created_at) }} |
暂无数据
软件管理
| 名称 | 标识符 | 备注 | 卡密数 | 创建时间 | 操作 |
|---|---|---|---|---|---|
| {{ s.name }} | {{ s.identifier }} | {{ s.remark||'-' }} | {{ s.key_count }} | {{ fmt(s.created_at) }} |
暂无软件
生成卡密
卡密格式:XXXX-XXXX-XXXX-XXXX
(与客户端 license.js 格式一致)
生成结果 ({{ gened.length }} 条)
{{ k }}
卡密列表
| 卡密 | 软件 | 类型 | 状态 | 机器码 | 创建时间 | 操作 | |
|---|---|---|---|---|---|---|---|
{{ k.card_key }} |
{{ k.software_name||'-' }} | {{ ctName(k.card_type,k.custom_days) }} | {{ stTxt(k.status) }} | {{ k.machine_code||'-' }} | {{ fmt(k.created_at) }} |
暂无卡密
验证记录
| 卡密 | 软件 | 结果 | 机器码 | IP | 归属地 | 时间 |
|---|---|---|---|---|---|---|
| {{ l.card_key }} | {{ l.software_name||'-' }} | {{ l.result?'成功':'失败' }} | {{ l.machine_code||'-' }} | {{ l.ip }} | {{ l.ip_location||'-' }} | {{ fmt(l.created_at) }} |
暂无记录
API 对接
将你的客户端软件 license.js 接入服务端验证
卡密格式
格式:XXXX-XXXX-XXXX-XXXX (大写字母+数字)
结构:
第1位 类型标识 M=月卡/周卡 Y=年卡 P=永久
第2-3位 随机字符
第4位 校验位 (类型+天数) mod 36
第5-6位 有效天数 Base36编码 (0U=30天, 07=7天, A5=365天)
第7-16位 随机字符
示例:
月卡: MZFK-Z0UX-K8R2-7BNQ
年卡: YABM-A5KQ-R3W7-P2X9
永久: PCZR-RU7G-M4N8-J6K2
验证接口
POST {{ apiBase }}?action=verify
Content-Type: application/json
// 请求
{ "card_key": "XXXX-XXXX-XXXX-XXXX", // 必填
"software": "your_app_id", // 必填,软件标识符
"machine_code": "MACHINE-XXX" } // 可选
// 成功 (code=0)
{ "code": 0, "message": "验证成功",
"data": {
"type": "monthly", // monthly / yearly / permanent
"typeName": "月卡",
"days": 30,
"expireDate": 1738300800000, // JS毫秒时间戳,直接写入 localStorage
"expire": "2025-01-31 12:00:00",
"cardKey": "MZFK-Z0UX-K8R2-7BNQ",
"firstVerify": "2025-01-01 12:00:00"
}}
// 失败 (code=1)
{ "code": 1, "message": "卡密无效" }
// message 可能为: "卡密无效" / "卡密已被禁用" / "卡密已过期" / "软件标识无效"
集成到 license.js
替换 license.js 中的
activateLicense 函数,其余代码无需修改
// ===== 在 license.js 顶部添加配置 =====
var VERIFY_URL = "{{ apiBase }}?action=verify";
var SOFTWARE_ID = "your_app_id"; // 替换为你的软件标识符
// ===== 替换 activateLicense 函数 =====
function activateLicense(key) {
// 1. 本地格式校验 (保留原有)
var result = validateLicenseKey(key);
if (!result.valid) return result;
// 2. 服务端验证
try {
var xhr = new XMLHttpRequest();
xhr.open("POST", VERIFY_URL, false); // 同步请求
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({
card_key: key,
software: SOFTWARE_ID,
machine_code: getMachineCode() // 你的机器码获取函数
}));
if (xhr.status === 200) {
var resp = JSON.parse(xhr.responseText);
if (resp.code !== 0) {
return { valid: false, error: resp.message };
}
// 3. 写入授权
var license = getLicense() || {};
license.activated = true;
license.type = resp.data.type;
license.expireDate = resp.data.expireDate;
license.activateDate = Date.now();
license.key = resp.data.cardKey;
saveLicense(license);
return { valid: true, typeName: resp.data.typeName };
}
return { valid: false, error: "服务器连接失败" };
} catch(e) {
// 离线回退: 使用本地解析
var license = getLicense() || {};
license.activated = true;
license.type = result.type;
license.expireDate = result.expireDate;
license.activateDate = Date.now();
license.key = key;
saveLicense(license);
return { valid: true, typeName: result.typeName };
}
}
离线回退说明
上述代码内置了离线回退机制:当服务端无法连接时,自动降级为本地卡密解析验证。
这保证了用户在网络异常时仍可正常激活,但离线激活无法被服务端追踪和管控(禁用、过期等操作不会生效)。
如需强制在线验证,删除 catch 块中的回退逻辑,直接返回错误即可。
设置
修改密码