TICKET MANAGE
管理你的产品授权
一个后台,完成发码、导出与设备管理。
WORKSPACE
授权工作台
买断资格长期有效,联网验证后按方案签发设备凭证。
应用0
授权方案0
当前筛选的激活码0
1 创建应用
2 创建方案
3 批量发码
参数在发码时锁定。生成、导出、激活分别记录;导出不代表售出。
激活码与设备
列表只显示脱敏码;点「复制码」按需取回单个完整码,或按批次导出。完整码只通过安全渠道交付。
| 脱敏码 / 应用 | 批次 / 方案 | 快照参数 | 生成 / 导出 / 激活 | 设备 | 操作 |
|---|
没有匹配的激活码。可以在「发码」页签生成新批次。
已激活设备
渠道商品与订单
内部发码接口已就绪。阿奇索协议适配待官方文档,当前不能直接配置为阿奇索兼容接口。
商品映射
渠道密钥由部署者本地生成,仅绑定指定渠道和店铺。请求不能覆盖设备数或 TTL。
按订单项查询 / 补发原码
同一订单项重试返回原码,商品或数量变化会拒绝。补发不会生成新码;不自动退款或发送消息。
| 渠道 | 店铺 | 商品 / SKU | 方案 |
|---|
接入指南
把客户端应用接到本服务:四个 JSON 接口加本地 Ed25519 验签,没有 SDK、没有额外依赖。下面几项直接复制给开发者。
服务地址
读取中…应用 ID
—公钥算法 / key_id
Ed25519读取中…固定公钥(应随安装包预置,不要运行时下载后无条件信任)
读取中…1 客户端生命周期
| 时机 | 调用 | 说明 |
|---|---|---|
| 用户输入激活码 | POST /api/v1/activate | 返回票据;保存 license_id 与完整票据,后续不必再发送激活码 |
| 启动时 / 到期前 | POST /api/v1/verify | 旧票据过期也能续签,不要求提交有效旧票据;建议提前续签并加随机抖动 |
| 换机 / 退授权 | POST /api/v1/unbind | 释放设备名额;重复解绑返回 404,可视为已经解绑 |
| 打包 / 首次配网 | GET /api/v1/public-key | 只用于取得公钥,公钥必须固定在客户端 |
写接口均为 POST application/json,请求体上限 16 KiB;正式接入使用 HTTPS。
2 客户端必须自己做的三件事
- 保存设备身份。首启用密码学安全随机源生成
device_id(16–128 字节)与device_secret(至少 32 字节),持久保存且重试复用同一对;秘密丢失只能由管理员在后台重置,光凭设备 ID 无法找回。 - 先验签,再解析。把
payload与signature按 base64url 无填充解码,用预置公钥对原始 payload 字节做 Ed25519 校验;不要先解析再重新序列化。 - 核对声明并真正执行限制。确认
v=1、app_id、device_id、license_id与本地记录一致且未过期,然后由客户端执行功能限制——服务端挡不住被篡改的客户端。
3 错误码与客户端动作
| HTTP | error | 客户端动作 |
|---|---|---|
| 403 | license_disabled | 明确撤销,停止授权 |
| 403 | device_secret_mismatch | 不能接管此设备,提示联系管理员 |
| 404 | license_not_found | 授权不存在或不属于当前应用 |
| 404 | activation_not_found | 未激活、已解绑或被后台重置 |
| 409 | device_limit | 已达设备上限,提示先解绑 |
| 429 | rate_limit | 等待 60 秒后用原参数重试 |
| 500 | internal_error | 服务故障,稍后重试 |
| — | 网络错误 / 超时 | 都不能视为明确撤销:保留票据按离线策略继续,稍后重试 |
4 可直接复制的示例
激活
BASE="服务地址"
APP_ID="应用 ID"
DEVICE_ID=$(openssl rand -hex 16)
DEVICE_SECRET=$(openssl rand -hex 32)
curl -sS "$BASE/api/v1/activate" \
-H 'Content-Type: application/json' \
-d "{\"app_id\":\"$APP_ID\",\"code\":\"TM-从后台批次导出一个码\",\"device_id\":\"$DEVICE_ID\",\"device_secret\":\"$DEVICE_SECRET\"}"
票据验签与声明核对(Go)
payload, err := base64.RawURLEncoding.DecodeString(ticket.Payload)
sig, err := base64.RawURLEncoding.DecodeString(ticket.Signature)
if len(sig) != ed25519.SignatureSize || !ed25519.Verify(pub, payload, sig) {
return errors.New("票据签名无效") // 先验签,再解析
}
var c Claims
if err := json.Unmarshal(payload, &c); err != nil {
return err
}
if c.Version != 1 || c.AppID != appID || c.DeviceID != deviceID ||
c.LicenseID != ticket.LicenseID || c.ExpiresAt <= time.Now().Unix() {
return errors.New("票据声明与本地记录不符或已过期")
}
示例只演示关键判定;完整可运行的参考客户端见仓库 docs/API.md 与后续的示例目录。
接入前请注意
票据离线有效期内无法即时撤销:方案 TTL 越长,离线可用越久,禁用或退款的生效也越慢。设备秘密应存系统密钥链,不要写进明文配置、URL 或日志。时间回拨无法根治,可在客户端记录单调时间做基本检测。服务端无法阻止被破解的客户端,功能限制必须由客户端真实执行。
操作说明
禁用后拒绝新激活和联网续验,已签发的离线凭证会在到期后失效。后台重置会释放此码的全部设备名额,不会换码;如激活码泄露,请禁用并重新发码。
网络错误或服务端 500 不代表明确撤销。客户端接入方法、签名校验与备份步骤见仓库中文文档。