Skip to content

C# SDK

基于 System.Net.Http 的轻量客户端,.NET 6+ 可直接使用,无需第三方依赖

安装

将以下代码保存为 A7Client.cs 并加入工程即可(需 using System.Text.Json)。

完整客户端代码

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://www.a7p.cn/api/verify";
    private static readonly HttpClient Http = new() { Timeout = TimeSpan.FromSeconds(10) };

    private readonly string _appId;
    private readonly string _appKey;
    public string ApiPassword { get; private set; } = "";

    public A7Client(string appId, string appKey)
    {
        _appId = appId;
        _appKey = appKey;
    }

    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>Init 握手,返回 ApiPassword 并缓存到实例。</summary>
    public async Task<string> InitAsync()
    {
        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(Base, 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()}");

        ApiPassword = root.GetProperty("data").GetProperty("api_password").GetString() ?? "";
        return ApiPassword;
    }

    /// <summary>通用 Handle 调用。plain 为 action=...&amp;k=v 明文串。</summary>
    public async Task<JsonElement> CallAsync(string plain)
    {
        if (string.IsNullOrEmpty(ApiPassword))
            throw new InvalidOperationException("请先调用 InitAsync() 获取 ApiPassword");

        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();
    }
}

使用示例

csharp
var client = new A7Client("150018", "YOUR_APP_KEY");
await client.InitAsync();

JsonElement result = await client.CallAsync(
    "action=SingleLogin&Card=6PCG-ZRSZ-EX83-YBEH&Mac=MAC001");

int code = result.GetProperty("code").GetInt32();
if (code == 200)
{
    JsonElement data = result.GetProperty("data");
    Console.WriteLine($"登录成功,到期 {data.GetProperty("expire_at").GetString()}");
}
else
{
    Console.WriteLine($"失败 {code}: {result.GetProperty("message").GetString()}");
}

要点

  • ApiPassword 缓存在内存,建议登录成功后即用即丢,不要持久化。
  • 推荐通过请求头 X-Api-Password 传递接口密码。
  • 时间戳窗口 ±300 秒,确保客户端时钟准确。
  • 完整 API 见 12 个业务 action

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