Skip to content

API 概述 · Init + Handle 两步模型

A7验证提供 RESTful API 用于软件授权验证。所有接口均使用 HTTP POST,请求体为 表单格式application/x-www-form-urlencoded),响应统一为 JSON。

接口采用 两步模型

  1. 先调用 Init,用 AppId + AppKey 换取本次会话的 ApiPassword(接口密码)。
  2. 再用 ApiPassword 对后续所有业务请求做 RC4 加密 + MD5 签名,通过 Handle 接口按明文参数中的 action 字段分发到具体业务。

这样设计的好处:程序密钥 AppKey 只在握手阶段出现一次,业务请求中不再传输,即使业务流量被抓包也拿不到永久凭据。

基本信息

项目说明
Init 接口POST https://api.a7p.cn/api/verify
Handle 接口POST https://api.a7p.cn/api/verify/{ApiPassword}
请求方式POST(仅支持 POST)
请求格式application/x-www-form-urlencoded
响应格式JSON,字符编码 UTF-8
加密方式RC4 对称加密(密文转 HEX) + MD5 签名
时间戳窗口Unix 秒级时间戳,允许 ±300 秒偏差
业务 action 数量12 个,见下方列表

机器码参数写法

机器码参数在本文档中统一写作 Mac。服务端同时兼容 Mac / mac / DeviceId 三种写法,任选其一传入即可。

调用步骤

  1. 客户端取当前 Unix 秒级时间戳 TimeStamp
  2. 计算 Init 签名:Sign = MD5(AppId + AppKey + TimeStamp + AppKey)
  3. POST /api/verify 提交 AppIdAppKeyTimeStampSign,得到 data.api_password
  4. api_password 保存在内存变量中(不要落盘、不要硬编码)。
  5. 拼接业务明文参数串,action 置于首位,例如 action=SingleLogin&Card=XXXX-XXXX-XXXX-XXXX&Mac=MAC001
  6. ApiPassword 作为密钥对明文串做 RC4 加密,密文字节转 HEX 字符串得到 Data
  7. 重新取时间戳,计算 Handle 签名:Sign = MD5(ApiPassword + TimeStamp + Data)
  8. POST /api/verify/{ApiPassword} 提交 TimeStampDataSign,解析返回的 JSON。

Step 1 · Init 初始化握手

http
POST /api/verify HTTP/1.1
Host: api.a7p.cn
Content-Type: application/x-www-form-urlencoded

AppId=150018&AppKey=YOUR_APP_KEY&TimeStamp=1780000000&Sign=3f2a...c91b

请求参数

参数类型必填说明
AppIdstring程序编号,例如 150018
AppKeystring程序密钥(32 位大写字母 + 数字)
TimeStampstringUnix 秒级时间戳,有效期 ±300 秒
SignstringMD5(AppId + AppKey + TimeStamp + AppKey)

成功响应

json
{
  "code": 200,
  "message": "success",
  "data": {
    "api_password": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
  }
}
字段类型说明
data.api_passwordstring32 位接口密码,用于后续 Handle 的签名与 RC4 加密

失败响应

json
{"code":1013,"message":"参数不完整","data":null}
{"code":1014,"message":"时间戳已过期","data":null}
{"code":1001,"message":"程序不存在","data":null}
{"code":1011,"message":"程序密钥错误","data":null}
{"code":1012,"message":"程序未审核通过","data":null}
{"code":1010,"message":"签名错误","data":null}

完整含义见 错误码对照表

Step 2 · Handle 业务调用

所有业务能力(登录、注册、心跳、查询等)都通过此接口调用。具体业务由 加密后的明文参数中的 action 字段 决定。

http
POST /api/verify/A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6 HTTP/1.1
Host: api.a7p.cn
Content-Type: application/x-www-form-urlencoded

TimeStamp=1780000000&Sign=8d41...7a2e&Data=1F3B7C90AE...

请求参数

参数类型必填说明
TimeStampstringUnix 秒级时间戳,有效期 ±300 秒
DatastringRC4(ApiPassword, 明文参数串) 后转 HEX 字符串
SignstringMD5(ApiPassword + TimeStamp + Data)

ApiPassword 的三种传递方式

服务端按以下优先级取 ApiPassword

  1. 请求头 X-Api-Password推荐,不会写进访问日志/浏览器历史)
  2. 表单字段 ApiPassword
  3. URL 路径段 /api/verify/{ApiPassword}(兼容旧客户端)
http
POST /api/verify HTTP/1.1
Host: api.a7p.cn
Content-Type: application/x-www-form-urlencoded
X-Api-Password: A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6

TimeStamp=1780000000&Sign=8d41...7a2e&Data=1F3B7C90AE...

Data 解密后的明文参数格式

& 连接的键值对,action 建议放在首位:

text
action=SingleLogin&Card=XXXX-XXXX-XXXX-XXXX&Mac=MAC001&DeviceName=MyPC

通用失败响应

json
{"code":1001,"message":"程序不存在","data":null}
{"code":1012,"message":"程序未审核通过","data":null}
{"code":1013,"message":"参数不完整","data":null}
{"code":1014,"message":"时间戳已过期","data":null}
{"code":1010,"message":"签名错误","data":null}
{"code":1015,"message":"未知操作: Xxx","data":null}

签名注意事项

要点说明
MD5 结果大小写服务端按字符串严格比对,推荐统一使用 小写 32 位
RC4 密文编码密文字节需转为 HEX 字符串(推荐 大写)后作为 Data 提交,服务端解析大小写均可
时间戳Unix 秒级(不是毫秒),服务端允许 ±300 秒偏差,超出返回 1014
参数顺序明文参数中 action 建议置于首位,其余键值对顺序不影响解析
ApiPassword32 位接口密码,仅在内存中保存,切勿硬编码或明文落盘
特殊字符明文参数值若含 & = 等符号,需先做 URL 编码再拼接

详细原理见 签名校验与 RC4 加密

cURL 调试助手

Handle 阶段需要 RC4 加密,纯 shell 实现比较麻烦。下面这段脚本定义了一个 a7call 函数,把它粘进终端后就能用一行命令调用任意 action —— 各 API 页的 cURL 示例都基于它

bash
# ===== A7验证 cURL 调试助手 =====
# 依赖:curl、python3、md5sum(macOS 用 `md5 -q` 替换 md5sum)
export A7_BASE="https://api.a7p.cn/api/verify"
export A7_APP_ID="150018"
export A7_APP_KEY="YOUR_APP_KEY"

# 1) Init 握手,把 ApiPassword 存进环境变量 A7_PW
a7init() {
  local ts sign resp
  ts=$(date +%s)
  sign=$(printf '%s%s%s%s' "$A7_APP_ID" "$A7_APP_KEY" "$ts" "$A7_APP_KEY" | md5sum | cut -d' ' -f1)
  resp=$(curl -s -X POST "$A7_BASE" \
    -d "AppId=${A7_APP_ID}" -d "AppKey=${A7_APP_KEY}" \
    -d "TimeStamp=${ts}" -d "Sign=${sign}")
  echo "Init => $resp"
  export A7_PW=$(printf '%s' "$resp" | python3 -c \
    "import sys,json;print(json.load(sys.stdin).get('data',{}).get('api_password',''))")
  echo "A7_PW=$A7_PW"
}

# 2) Handle 调用,参数为完整明文参数串
a7call() {
  local plain="$1" ts data sign
  ts=$(date +%s)
  data=$(A7K="$A7_PW" A7P="$plain" python3 -c '
import os
k = os.environ["A7K"].encode()
p = os.environ["A7P"].encode()
s = list(range(256)); j = 0
for i in range(256):
    j = (j + s[i] + k[i % len(k)]) % 256
    s[i], s[j] = s[j], s[i]
i = j = 0
out = bytearray()
for b in p:
    i = (i + 1) % 256
    j = (j + s[i]) % 256
    s[i], s[j] = s[j], s[i]
    out.append(b ^ s[(s[i] + s[j]) % 256])
print(out.hex().upper())
')
  sign=$(printf '%s%s%s' "$A7_PW" "$ts" "$data" | md5sum | cut -d' ' -f1)
  curl -s -X POST "$A7_BASE" \
    -H "X-Api-Password: ${A7_PW}" \
    -d "TimeStamp=${ts}" -d "Data=${data}" -d "Sign=${sign}"
  echo
}

用法:

bash
a7init
a7call "action=SingleLogin&Card=UTDE-7TCX-N5AT-ZDSP&Mac=TEST-ABC-123"
a7call "action=GetBulletin"

12 个业务 action 列表

action中文名说明文档
SingleLogin卡密登录卡密 + 机器码验证,首次使用自动激活并绑定设备查看
UserLogin用户登录用户名 + 密码登录,支持卡密续期与 QQ 扫码查看
UserRegin用户注册注册新用户,可同时卡密激活或绑定 QQ查看
UpdatePwd修改密码校验原密码后修改为新密码查看
ChangeBind换绑机器码校验账号密码后把绑定设备换成新机器码查看
UserHeartbeat心跳保活维持在线状态并接收后台下发消息查看
GetLatestVersion获取版本获取最新版本号、更新日志与下载地址查看
GetBulletin获取公告获取开发者在后台发布的程序公告查看
GetVariable获取远程变量读取云端配置变量,可取单个或全部查看
GetUserInfo查询用户信息用户名 + 密码查询注册用户详情查看
GetCardInfo查询卡密信息通过卡密查询状态、到期时间与绑定详情查看
UserRecharge用户续期用充值卡密给用户账号续期(无需密码)查看

只有这 12 个 action

传入列表之外的 action 会返回 1015 未知操作。文档中不存在 webhookunbindinit(作为 action)等端点。

典型业务流程

卡密模式

  1. Init 换取 ApiPassword
  2. SingleLogin 用卡密 + 机器码登录,拿到 token
  3. 缓存 token 到内存
  4. 每 5 分钟 UserHeartbeatType=card

用户账号模式

  1. Init 换取 ApiPassword
  2. UserRegin 注册(可带卡密直接激活)
  3. UserLogin 登录,拿到 token
  4. 每 5 分钟 UserHeartbeatType=user
  5. 到期时 UserRecharge 续期,换电脑时 ChangeBind 换绑

相关链接

A7验证 · 软件授权与网络验证平台