Skip to content

Handle 业务调用

Handle 是 A7验证两步模型的第二步:所有业务能力(登录、注册、心跳、查询、续期等)都通过这一个接口调用,具体执行哪个业务由加密明文中的 action 字段决定。

项目
请求方式POST
请求地址https://api.a7p.cn/api/verify/{ApiPassword}
Content-Typeapplication/x-www-form-urlencoded
是否加密是,业务参数经 RC4 加密后转 HEX 大写
时间戳窗口±300 秒

调用步骤

  1. 先完成 Init 握手,拿到 ApiPassword
  2. 拼接业务明文参数串:action=业务名&参数1=值1&参数2=值2action 放首位。
  3. ApiPassword 作为密钥对明文做 RC4 加密,密文字节转 HEX 大写,得到 Data
  4. 取当前 Unix 秒级时间戳 TimeStamp
  5. 计算 Sign = MD5(ApiPassword + TimeStamp + Data)
  6. 表单 POSThttps://api.a7p.cn/api/verify/{ApiPassword},提交 TimeStampDataSign
  7. 解析响应 JSON,code == 200 为成功,其余按错误码处理。

请求参数

字段类型必填说明
TimeStampstringUnix 秒级时间戳,±300 秒有效
DatastringRC4(ApiPassword, 明文参数) 后转 HEX 大写
SignstringMD5(ApiPassword + TimeStamp + Data)
ApiPasswordstring接口密码。可从 URL 路径传,也可用请求体字段或请求头传,三选一

ApiPassword 的三种传递方式

服务端按以下优先级读取接口密码:

优先级方式写法推荐度
1请求头X-Api-Password: A1B2C3...推荐,不会写进访问日志 / 浏览器历史
2请求体字段表单里加 ApiPassword=A1B2C3...可用
3URL 路径POST /api/verify/A1B2C3...兼容旧客户端,明文出现在 URL 中

老客户端兼容

URL 路径写法仍然可用,路径段匹配正则 [A-Z0-9]{0,32}(大写字母与数字,最长 32 位)。新项目建议改用请求头 X-Api-Password,避免接口密码被 nginx access_log 记录。

Data 明文格式

解密后的明文是标准的 URL 查询串格式,用 & 连接键值对:

text
action=SingleLogin&Card=XXXX-XXXX-XXXX-XXXX&Mac=MAC001&DeviceName=MyPC
规则说明
action 位置建议放首位;服务端用 parse_str 解析,其余键值对顺序不影响结果
action 大小写区分大小写,必须与文档完全一致,如 UserRegin 不是 UserRegist
值中含特殊字符若参数值可能包含 & = % 等字符,请先做 URL 编码再拼接
编码明文按 UTF-8 编码后再做 RC4

请求示例

python
import hashlib
import json
import time
import urllib.request

BASE = "https://api.a7p.cn/api/verify"


def rc4(key: str, data: str) -> str:
    """RC4 加密,返回 HEX 大写字符串。"""
    key_bytes = key.encode("utf-8")
    s = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s[i] + key_bytes[i % len(key_bytes)]) % 256
        s[i], s[j] = s[j], s[i]
    i = j = 0
    out = bytearray()
    for b in data.encode("utf-8"):
        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])
    return out.hex().upper()


def handle(api_pw: str, plain: str) -> dict:
    """通用 Handle 调用:传入 ApiPassword 与明文参数串,返回响应字典。"""
    ts = int(time.time())
    data_hex = rc4(api_pw, plain)
    sign = hashlib.md5(f"{api_pw}{ts}{data_hex}".encode("utf-8")).hexdigest()
    body = f"TimeStamp={ts}&Sign={sign}&Data={data_hex}".encode("utf-8")

    req = urllib.request.Request(
        BASE,
        data=body,
        headers={
            "Content-Type": "application/x-www-form-urlencoded",
            "X-Api-Password": api_pw,   # 推荐:用请求头传接口密码
        },
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read().decode("utf-8"))


# 用法
result = handle("A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6",
                "action=GetBulletin")
print(result)
csharp
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public sealed class A7Client
{
    private const string Base = "https://api.a7p.cn/api/verify";
    private readonly HttpClient _http = new HttpClient
    {
        Timeout = TimeSpan.FromSeconds(10)
    };
    private readonly string _apiPassword;

    public A7Client(string apiPassword) => _apiPassword = apiPassword;

    public static string Rc4(string key, string data)
    {
        byte[] keyBytes = Encoding.UTF8.GetBytes(key);
        byte[] dataBytes = Encoding.UTF8.GetBytes(data);
        int[] s = new int[256];
        for (int i = 0; i < 256; i++) s[i] = i;

        int j = 0;
        for (int i = 0; i < 256; i++)
        {
            j = (j + s[i] + keyBytes[i % keyBytes.Length]) % 256;
            (s[i], s[j]) = (s[j], s[i]);
        }

        var sb = new StringBuilder(dataBytes.Length * 2);
        int x = 0, y = 0;
        foreach (byte b in dataBytes)
        {
            x = (x + 1) % 256;
            y = (y + s[x]) % 256;
            (s[x], s[y]) = (s[y], s[x]);
            sb.Append((b ^ s[(s[x] + s[y]) % 256]).ToString("X2"));
        }
        return sb.ToString();
    }

    public static string Md5(string text)
    {
        using var md5 = MD5.Create();
        byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(text));
        var sb = new StringBuilder(32);
        foreach (byte b in hash) sb.Append(b.ToString("x2"));
        return sb.ToString();
    }

    /// <summary>通用 Handle 调用。plain 为 action=...&amp;k=v 明文串。</summary>
    public async Task<JsonElement> HandleAsync(string plain)
    {
        long ts = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        string dataHex = Rc4(_apiPassword, plain);
        string sign = Md5($"{_apiPassword}{ts}{dataHex}");

        using var req = new HttpRequestMessage(HttpMethod.Post, Base)
        {
            Content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                ["TimeStamp"] = ts.ToString(),
                ["Sign"] = sign,
                ["Data"] = dataHex
            })
        };
        req.Headers.Add("X-Api-Password", _apiPassword);

        using HttpResponseMessage resp = await _http.SendAsync(req);
        string body = await resp.Content.ReadAsStringAsync();
        return JsonDocument.Parse(body).RootElement.Clone();
    }
}
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...

支持的 action 一览

Handle 共支持 12 个业务 action

action中文名文档
SingleLogin卡密登录查看
UserLogin用户登录查看
UserRegin用户注册查看
UpdatePwd修改密码查看
ChangeBind换绑设备查看
UserHeartbeat心跳检测查看
GetLatestVersion获取最新版本查看
GetBulletin获取程序公告查看
GetVariable获取远程变量查看
GetUserInfo获取用户信息查看
GetCardInfo获取卡密信息查看
UserRecharge用户充值续期查看

传入列表之外的 action 会返回 1015 未知操作: xxx

通用失败响应

以下错误在任何 action 之前就会返回,属于传输层校验失败:

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

错误码

错误码含义解决方案
1001程序不存在ApiPassword 无效或拼错,重新走一次 Init
1010签名错误核对 MD5(ApiPassword + TimeStamp + Data);确认 Data 已转 HEX 大写;确认签名用的 TimeStamp 与提交的一致
1012程序未审核通过产品状态异常或套餐过期
1013参数不完整TimeStampSign 缺失
1014时间戳已过期校准本机时间
1015未知操作action 拼写错误或大小写不对;也可能是 RC4 解密失败导致明文乱码

完整列表见错误码对照表

相关文档

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