卡密管理

当前总数 0
未使用 0
已使用 0
在线设备 0
过期/禁用 0
正在加载软件...
卡密代码 类型 状态 开卡账号 多开 设备ID 备注 创建时间 激活时间 到期时间 操作
暂无数据
软件名称 备注 AppKey AppSecret 多开 前缀 状态 卡密 在线 归属账号 创建时间 操作
📇
暂无软件数据

👥 一级代理

代理只能使用你授权的软件开卡,已生成卡密仍归代理账号记录。
代理账号授权软件备注已开卡数状态操作
加载中...
👥
0
用户总数
💻
0
接入软件数
🎫
0
卡密总数
📱
0
在线设备

🔐 超级管理员 - 用户管理

ID 用户名 软件备注 角色 软件数 卡密数 在线设备 注册时间 操作
加载中...
📋 基础信息
基础配置
认证说明
签名验证
🔐 认证接口
用户注册
用户登录
获取用户信息
🎫 卡密接口
生成卡密
卡密列表
使用卡密
禁用/启用卡密
📱 客户端接口
WS 卡密登录
WS 心跳与授权
WS 查询卡密
WS 解绑设备
完整 WS 对接文档 ↗
💻 软件接口
创建软件
软件列表
更新软件
删除软件
⚡ 状态码
状态码说明
客户端返回码

📋 基础信息

基础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。

🔐 认证接口

用户注册

POST
/api/auth/register

请求参数

参数 类型 必填 说明
username string 是 用户名(3-20字符)
email 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" }
}

用户登录

POST
/api/auth/login

请求参数

参数 类型 必填 说明
username string 是 用户名
password string 是 密码

响应示例

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": { "id": 1, "username": "testuser", "role": "user" }
}

获取当前用户信息

GET
/api/auth/me 需要认证

响应示例

{
  "success": true,
  "user": {
    "id": 1,
    "username": "testuser",
    "email": "test@example.com",
    "role": "user",
    "balance": 100.00
  }
}

🎫 卡密接口

生成卡密

POST
/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
}

获取卡密列表

GET
/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

使用卡密

POST
/api/cards/:id/use 需要认证

请求参数

参数 类型 必填 说明
deviceId string 否 设备ID

禁用/启用卡密

POST
/api/cards/:id/disable 需要认证

启用卡密:

POST
/api/cards/:id/enable 需要认证

💻 软件接口

创建软件

POST
/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..."
  }
}

获取软件列表

GET
/api/software 需要认证

请求参数

参数 类型 必填 说明
name string 否 软件名称(模糊搜索)
page int 否 页码(默认1)
pageSize int 否 每页数量(默认10)

更新软件

PUT
/api/software/:id 需要认证

请求参数

参数 类型 必填 说明
name string 否 软件名称
multiDeviceLimit int 否 多开上限
cardPrefix string 否 卡密前缀
deviceBind boolean 否 是否开启设备绑定
description string 否 软件描述

删除软件

DELETE
/api/software/:id 需要认证

重置AppSecret

POST
/api/software/:id/reset-secret 需要认证

禁用/启用软件

POST
/api/software/:id/disable 需要认证

启用软件:

POST
/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 该卡密不可解绑设备