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=...&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。