卡密管理
| 卡密代码 | 类型 | 状态 | 开卡账号 | 多开 | 设备ID | 备注 | 创建时间 | 激活时间 | 到期时间 | 操作 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 暂无数据 | |||||||||||
| 软件名称 | 备注 | AppKey | AppSecret | 多开 | 前缀 | 状态 | 卡密 | 在线 | 归属账号 | 创建时间 | 操作 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
📇
暂无软件数据
|
||||||||||||
👥 一级代理
| 代理账号 | 授权软件 | 备注 | 已开卡数 | 状态 | 操作 |
|---|---|---|---|---|---|
| 加载中... | |||||
🔐 超级管理员 - 用户管理
| ID | 用户名 | 软件备注 | 角色 | 软件数 | 卡密数 | 在线设备 | 注册时间 | 操作 |
|---|---|---|---|---|---|---|---|---|
| 加载中... | ||||||||
📋 基础信息
| 基础URL | http://localhost:3002 |
| 认证方式 | Bearer Token (JWT) |
| 数据格式 | JSON |
🔐 认证说明
管理后台的受保护 HTTP 接口需要在请求头中携带 JWT Token:
Authorization: Bearer <your_jwt_token>
🔐 WS 登录签名
连接 /ws/card 后,收到 card_challenge 再计算登录签名。AppKey 和 AppSecret 沿用软件列表中的现有值。
const payload = JSON.stringify([challenge, requestId, appKey, card, deviceId, deviceInfo, resume]);
const sign = require('crypto').createHmac('sha256', appSecret).update(payload).digest('hex');deviceInfo 为字符串,resume 为布尔值。挑战有效期 60 秒,每次尝试后更换。正常登录用 false,断线恢复用 true。
登录后的请求复用连接身份,无需重复携带卡密和签名。消息统一用 msgType,响应携带原 requestId。线上使用 WSS。
🔐 认证接口
用户注册
/api/auth/register
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | 是 | 用户名(3-20字符) |
| string | 是 | 邮箱地址 | |
| password | string | 是 | 密码(至少6位) |
| referralCode | string | 否 | 推荐码 |
请求示例
{
"username": "testuser",
"email": "test@example.com",
"password": "123456"
}
响应示例
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": { "id": 1, "username": "testuser", "role": "user" }
}
用户登录
/api/auth/login
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | 是 | 用户名 |
| password | string | 是 | 密码 |
响应示例
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": { "id": 1, "username": "testuser", "role": "user" }
}
获取当前用户信息
/api/auth/me
需要认证
响应示例
{
"success": true,
"user": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"role": "user",
"balance": 100.00
}
}
🎫 卡密接口
生成卡密
/api/cards/generate
需要认证
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cardType | string | 是 | 卡密类型:day/week/month/quarter/year/permanent |
| count | int | 是 | 生成数量(1-200) |
| duration | int | 是 | 时长(天) |
| softwareId | int | 是 | 所属软件ID |
卡密类型说明
| 类型 | 说明 |
|---|---|
| day | 天卡 |
| week | 周卡 |
| month | 月卡 |
| quarter | 季卡 |
| year | 年卡 |
| permanent | 永久卡 |
请求示例
{
"cardType": "month",
"count": 10,
"duration": 30,
"softwareId": 1
}
获取卡密列表
/api/cards
需要认证
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| status | string | 否 | 卡密状态:unused/used/expired |
| cardType | string | 否 | 卡密类型 |
| keyword | string | 否 | 搜索关键字(卡密代码/设备ID) |
| softwareName | string | 否 | 软件名称 |
| softwareId | int | 否 | 软件ID(精确筛选) |
| page | int | 否 | 页码(默认1) |
| limit | int | 否 | 每页数量(默认10) |
请求示例
GET /api/cards?status=unused&cardType=month&page=1&limit=20
使用卡密
/api/cards/:id/use
需要认证
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| deviceId | string | 否 | 设备ID |
禁用/启用卡密
/api/cards/:id/disable
需要认证
启用卡密:
/api/cards/:id/enable
需要认证
💻 软件接口
创建软件
/api/software
需要认证
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 软件名称(不超过20字符) |
| multiDeviceLimit | int | 否 | 多开上限(默认1,最大10) |
| cardPrefix | string | 否 | 卡密前缀(不超过5字符) |
| deviceBind | boolean | 否 | 是否开启设备绑定 |
| description | string | 否 | 软件描述 |
响应示例
{
"success": true,
"message": "软件创建成功",
"data": {
"id": 1,
"name": "测试软件",
"app_key": "abc123...",
"app_secret": "xyz789..."
}
}
获取软件列表
/api/software
需要认证
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 软件名称(模糊搜索) |
| page | int | 否 | 页码(默认1) |
| pageSize | int | 否 | 每页数量(默认10) |
更新软件
/api/software/:id
需要认证
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 软件名称 |
| multiDeviceLimit | int | 否 | 多开上限 |
| cardPrefix | string | 否 | 卡密前缀 |
| deviceBind | boolean | 否 | 是否开启设备绑定 |
| description | string | 否 | 软件描述 |
删除软件
/api/software/:id
需要认证
重置AppSecret
/api/software/:id/reset-secret
需要认证
禁用/启用软件
/api/software/:id/disable
需要认证
启用软件:
/api/software/:id/enable
需要认证
📱 客户端 WebSocket
客户端卡密协议统一使用 WebSocket,完整字段、签名算法、响应验签、心跳授权窗口和重连请查看 完整 WS 对接文档。下面保留快速示例。
连接 ws://localhost:3008/ws/card,收到 card_challenge 后发送:
{
"msgType": "card_login",
"requestId": "login-1",
"appKey": "your_app_key",
"card": "your_card",
"deviceId": "stable_device_id",
"deviceInfo": "{}",
"resume": false,
"sign": "hmac_sha256_hex"
}card_login_response 返回 code、success、message、result、nonce 和 sign。code 为 0 才表示业务登录成功。
result.lease_seconds 为授权有效窗口(90 秒),expires_ts 为卡密到期秒时间戳。断线恢复用 resume: true,只恢复仍有效的设备绑定,被顶号或解绑后不会自动抢回。
心跳与主动通知
{"msgType":"heartbeat"}按登录结果中的 result.heartbeat_gap 发送心跳,当前为25秒。heartbeat_ack 只代表消息收到,随后要检查 card_status.code === 0;只有成功授权结果会延长授权窗口。收到 card_revoked 或关闭码4003时必须停止任务。
card_updated 更新卡密授权和配置。card_revoked 表示到期、冻结、删除或被顶号,客户端应停止任务;撤销后关闭码为 4003。
查询当前卡密
{"msgType":"card_query","requestId":"query-1"}需先登录。card_query_response.result 返回当前卡密类型、状态、绑定和到期时间。卡密与设备始终取当前会话。
解绑当前设备
{"msgType":"card_unbind","requestId":"unbind-1"}需先登录。card_unbind_response 返回结果。沿用软件解绑开关及至少保留一个有效绑定的规则;成功后当前授权撤销。
软件配置、公告与退出
{"msgType":"software_info","requestId":"info-1"}
{"msgType":"software_announcement","requestId":"notice-1"}
{"msgType":"card_logout","requestId":"logout-1"}配置与公告需先登录,响应 msgType 为请求名加 _response。退出或断线自动标记离线,保留卡密激活记录和设备绑定。网页管理后台继续使用 HTTP,卡密客户端不要调用旧的 /api/client/* 接口。
⚡ 状态码说明
| 状态码 | 说明 |
|---|---|
| 200 | 请求成功 |
| 201 | 创建成功 |
| 400 | 请求参数错误 |
| 401 | 未认证/Token无效 |
| 403 | 权限不足 |
| 404 | 资源不存在 |
| 429 | 请求过于频繁 |
| 500 | 服务器内部错误 |
错误响应格式
{
"success": false,
"message": "错误描述",
"errors": [
{ "field": "username", "message": "用户名不能为空" }
]
}
📱 客户端返回码
| 返回码 | 说明 |
|---|---|
| 0 | 调用成功 |
| 400 | 参数错误 |
| 403 | 权限不足或软件被禁用 |
| 500 | 服务器错误 |
| 签名相关 | |
| 10010 | 登录签名无效或挑战已超过60秒;当前 WS 协议统一返回此码 |
| 卡密相关 | |
| 10210 | 卡密已过期 |
| 10212 | 卡密已被冻结 |
| 10215 | 解绑时未找到当前设备的有效绑定 |
| 10216 | 软件未开启解绑设备功能 |
| 10217 | 绑定失效、设备被顶掉或连接被新连接接管 |
| 10218 | 卡密未激活,请先登录 |
| 10230 | 卡密不属于当前软件 |
| 10240 | 卡密不存在 |
| 10255 | 该卡密不可解绑设备 |