Java SDK
提供 A7Client 参考实现,基于 Java 11+ 标准库(java.net.http.HttpClient、java.security.MessageDigest、Gson 或 javax.json 解析 JSON)。本示例使用 org.json。
依赖
xml
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version>
</dependency>完整参考实现
A7Client.java:
java
import org.json.JSONObject;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Map;
import java.util.TreeMap;
public class A7Client {
private static final String BASE = "https://api.a7p.cn/api/verify";
private final String appId;
private final String appKey;
private String apiPassword = "";
private final HttpClient http = HttpClient.newHttpClient();
public A7Client(String appId, String appKey) {
this.appId = appId;
this.appKey = appKey;
}
private static String md5(String text) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b = md.digest(text.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte x : b) sb.append(String.format("%02x", x));
return sb.toString();
}
private static String rc4Hex(String key, String data) {
byte[] k = key.getBytes(StandardCharsets.UTF_8);
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] + (k[i % k.length] & 0xff)) % 256;
int t = s[i]; s[i] = s[j]; s[j] = t;
}
byte[] p = data.getBytes(StandardCharsets.UTF_8);
byte[] out = new byte[p.length];
int x = 0, y = 0;
for (int i = 0; i < p.length; i++) {
x = (x + 1) % 256;
y = (y + s[x]) % 256;
int t = s[x]; s[x] = s[y]; s[y] = t;
out[i] = (byte) (p[i] ^ s[(s[x] + s[y]) % 256]);
}
StringBuilder sb = new StringBuilder();
for (byte b : out) sb.append(String.format("%02X", b));
return sb.toString();
}
private JSONObject post(String url, Map<String, String> form, Map<String, String> headers) throws Exception {
StringBuilder body = new StringBuilder();
for (var e : form.entrySet()) {
if (body.length() > 0) body.append("&");
body.append(e.getKey()).append("=").append(e.getValue());
}
HttpRequest.Builder b = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(body.toString()));
for (var h : headers.entrySet()) b.header(h.getKey(), h.getValue());
HttpResponse<String> r = http.send(b.build(), HttpResponse.BodyHandlers.ofString());
return new JSONObject(r.body());
}
public void init() throws Exception {
long ts = System.currentTimeMillis() / 1000;
String sign = md5(appId + appKey + ts + appKey);
Map<String, String> form = new TreeMap<>();
form.put("AppId", appId);
form.put("AppKey", appKey);
form.put("TimeStamp", String.valueOf(ts));
form.put("Sign", sign);
JSONObject resp = post(BASE, form, Map.of());
if (resp.getInt("code") != 200)
throw new RuntimeException("Init 失败: " + resp.getInt("code") + " " + resp.getString("message"));
apiPassword = resp.getJSONObject("data").getString("api_password");
}
public JSONObject call(String action, Map<String, String> params) throws Exception {
if (apiPassword.isEmpty()) init();
Map<String, String> sorted = new TreeMap<>();
if (params != null) sorted.putAll(params);
StringBuilder plain = new StringBuilder("action=").append(action);
for (var e : sorted.entrySet())
plain.append("&").append(e.getKey()).append("=").append(e.getValue());
long ts = System.currentTimeMillis() / 1000;
String data = rc4Hex(apiPassword, plain.toString());
String sign = md5(apiPassword + ts + data);
Map<String, String> form = new TreeMap<>();
form.put("TimeStamp", String.valueOf(ts));
form.put("Data", data);
form.put("Sign", sign);
return post(BASE, form, Map.of("X-Api-Password", apiPassword));
}
}使用示例
java
A7Client client = new A7Client("150018", "YOUR_APP_KEY");
Map<String, String> params = new java.util.HashMap<>();
params.put("Card", "UTDE-7TCX-N5AT-ZDSP");
params.put("Mac", "TEST-ABC-123");
JSONObject resp = client.call("SingleLogin", params);
if (resp.getInt("code") == 200) {
System.out.println("token: " + resp.getJSONObject("data").getString("token"));
} else {
System.out.println("失败: " + resp.getInt("code") + " " + resp.getString("message"));
}注意事项
apiPassword仅保存在实例字段。- 使用
TreeMap排序拼接明文,结果可复现(顺序本身不影响服务端解析)。 - 更多接口参数见 API 参考。
相关链接
- 签名校验与 RC4 加密
- API 概述 · 两步模型
- 其它 SDK:Python · C# · Go · Node.js · C++ · 易语言