Skip to content

Init 初始化握手

Init 是 A7验证两步模型的第一步:用 AppId + AppKey 换取本次会话的 ApiPassword(32 位接口密码)。之后所有业务请求都通过 Handle 发起,并用这个 ApiPassword 做 RC4 加密与 MD5 签名。

项目
请求方式POST
请求地址https://api.a7p.cn/api/verify
Content-Typeapplication/x-www-form-urlencoded
是否加密否(Init 阶段明文提交,仅做签名校验)
时间戳窗口±300 秒

调用步骤

  1. 从控制台取得 AppIdAppKey(见获取 AppID 与 API 密钥)。
  2. 取当前 Unix 秒级时间戳 作为 TimeStamp
  3. MD5(AppId + AppKey + TimeStamp + AppKey) 计算 Sign,注意 AppKey 出现两次。
  4. 以表单方式 POSThttps://api.a7p.cn/api/verify,提交 AppIdAppKeyTimeStampSign 四个字段。
  5. 校验响应 code 是否为 200
  6. data.api_password 取出 ApiPassword只保存在内存变量,不要落盘。
  7. 携带 ApiPassword 进入 Handle 阶段调用业务 action。

请求参数

字段类型必填说明
AppIdstring程序编号,如 150018,控制台产品详情页可查
AppKeystring程序密钥,32 位大写字母 + 数字,机密值
TimeStampstringUnix 秒级时间戳,服务端允许 ±300 秒偏差
SignstringMD5(AppId + AppKey + TimeStamp + AppKey),推荐小写 32 位

签名口诀

AppIdAppKeyTimeStampAppKey。第二个 AppKey 相当于「盐」,很多人第一次接入就是漏了它,然后一直卡在 1010

请求示例

bash
APP_ID="150018"
APP_KEY="YOUR_APP_KEY"
TS=$(date +%s)
SIGN=$(printf "%s%s%s%s" "$APP_ID" "$APP_KEY" "$TS" "$APP_KEY" | md5sum | cut -d' ' -f1)

curl -s -X POST "https://api.a7p.cn/api/verify" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "AppId=${APP_ID}&AppKey=${APP_KEY}&TimeStamp=${TS}&Sign=${SIGN}"
python
import hashlib
import json
import time
import urllib.request

BASE = "https://api.a7p.cn/api/verify"
APP_ID = "150018"
APP_KEY = "YOUR_APP_KEY"

ts = int(time.time())
sign = hashlib.md5(f"{APP_ID}{APP_KEY}{ts}{APP_KEY}".encode("utf-8")).hexdigest()
body = f"AppId={APP_ID}&AppKey={APP_KEY}&TimeStamp={ts}&Sign={sign}".encode("utf-8")

req = urllib.request.Request(
    BASE, data=body,
    headers={"Content-Type": "application/x-www-form-urlencoded"},
)
with urllib.request.urlopen(req, timeout=10) as resp:
    result = json.loads(resp.read().decode("utf-8"))

if result["code"] != 200:
    raise RuntimeError(f"Init 失败 {result['code']}: {result['message']}")

api_password = result["data"]["api_password"]
print("ApiPassword =", api_password)
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 static class A7Init
{
    private static readonly HttpClient Http = new HttpClient
    {
        Timeout = TimeSpan.FromSeconds(10)
    };

    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>Init 握手,返回 ApiPassword;失败抛出异常。</summary>
    public static async Task<string> InitAsync(string appId, string appKey)
    {
        long ts = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        string sign = Md5($"{appId}{appKey}{ts}{appKey}");

        using var content = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["AppId"] = appId,
            ["AppKey"] = appKey,
            ["TimeStamp"] = ts.ToString(),
            ["Sign"] = sign
        });

        using HttpResponseMessage resp =
            await Http.PostAsync("https://api.a7p.cn/api/verify", content);
        string body = await resp.Content.ReadAsStringAsync();
        JsonElement root = JsonDocument.Parse(body).RootElement;

        int code = root.GetProperty("code").GetInt32();
        if (code != 200)
        {
            throw new InvalidOperationException(
                $"Init 失败 {code}: {root.GetProperty("message").GetString()}");
        }
        return root.GetProperty("data").GetProperty("api_password").GetString() ?? "";
    }
}
text
.版本 2

.子程序 A7_Init, 文本型, 公开, 握手成功返回 ApiPassword,失败返回空文本
.参数 AppId, 文本型
.参数 AppKey, 文本型
.局部变量 TimeStamp, 文本型
.局部变量 Sign, 文本型
.局部变量 返回文本, 文本型

TimeStamp = 到文本 (时间_取现行时间戳 ())
Sign = 取数据摘要 (到字节集 (AppId + AppKey + TimeStamp + AppKey))
返回文本 = 到文本 (网页_访问 ("https://api.a7p.cn/api/verify", 1, ;
    "AppId=" + AppId + "&AppKey=" + AppKey + "&TimeStamp=" + TimeStamp + "&Sign=" + Sign))

.如果真 (JSON_解析 (返回文本, "code") ≠ "200")
    输出调试文本 ("Init 失败:" + JSON_解析 (返回文本, "message"))
    返回 ("")
.如果真结束

返回 (JSON_解析 (返回文本, "data.api_password"))

原始 HTTP 报文长这样:

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

成功响应

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

关于 app_name / version 等扩展字段

部分历史版本文档展示过 app_idapp_nameversionversion_name 等回显字段。以当前后端实现为准,Init 稳定返回的是 api_password;程序名称与版本信息请通过 GetVariableGetLatestVersion 获取。请勿假设 Init 一定返回版本字段。

失败响应

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

错误码

错误码含义解决方案
1001程序不存在检查 AppId 是否写错、是否属于当前账号
1010签名错误核对 MD5(AppId + AppKey + TimeStamp + AppKey),确认 AppKey 拼接两次且无空格
1011程序密钥错误AppKey 与服务端不一致,去控制台重新复制
1012程序未审核通过产品待审核 / 被驳回 / 套餐过期,去控制台确认状态
1013参数不完整四个字段 AppId AppKey TimeStamp Sign 缺一不可
1014时间戳已过期校准本机时间,或改用服务器时间;偏差需在 ±300 秒内

完整列表见错误码对照表

相关文档

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