多语言签名示例
以下示例口径完全一致:submit 提交(JSON + 文件 base64)→ query 查询 → report 取报告地址。把 APP_ID 与 APP_SECRET 替换为您的值即可运行。
Java
PHP
Python
Node.js
Bash
Java
// 开放 API 签名与调用示例(Java 17+)。// JSON 序列化用 Jackson(主流三方库);HMAC/HTTP 用 JDK 自带。// 依赖:com.fasterxml.jackson.core:jackson-databind(Maven 引入后编译运行)。// <dependency>// <groupId>com.fasterxml.jackson.core</groupId>// <artifactId>jackson-databind</artifactId>// <version>2.17.0</version>// </dependency>// 用法:APP_ID=oa... APP_SECRET=... java -cp .:jackson-*.jar SignAndSubmit submit ./paper.pdf 2 OT001 "标题"// APP_ID=oa... APP_SECRET=... java ... SignAndSubmit query <taskNo> | online <taskNo>//// 签名:以 appSecret(Base64 解码为 32 字节)为密钥对待签内容做 HMAC-SHA256,结果 Base64。// bodyHash = SHA-256(原始 JSON body 字节) 的十六进制小写;GET 用空串。import com.fasterxml.jackson.databind.ObjectMapper;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.nio.file.Files;import java.nio.file.Path;import java.security.MessageDigest;import java.security.SecureRandom;import java.util.Base64;import java.util.HexFormat;import java.util.LinkedHashMap;import java.util.Map;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;public class SignAndSubmit {static final String BASE_URL = envOr("BASE_URL", "https://open.ais.cn");static final String APP_ID = System.getenv("APP_ID");static final String APP_SECRET = System.getenv("APP_SECRET"); // 平台下发的 Base64 共享密钥static final ObjectMapper MAPPER = new ObjectMapper();public static void main(String[] args) throws Exception {switch (args[0]) {case "submit" -> submit(Path.of(args[1]), args[2], args[3], args.length > 4 ? args[4] : null);case "query" -> get("/api/open/v1/tasks/query/" + args[1]);case "online" -> get("/api/open/v1/tasks/online/" + args[1]);default -> System.err.println("usage: submit <file> <checkType> <outTradeNo> <title> | query <taskNo> | online <taskNo>");}}static void submit(Path file, String checkType, String outTradeNo, String title) throws Exception {String path = "/api/open/v1/tasks/submit";String fileBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));// 用 Jackson 组 JSON body(LinkedHashMap 保序);序列化结果即实际发送的字节,用于 bodyHash// 公共字段在顶层;类型专属参数(文件/引文等)收在 payload 子对象Map<String, Object> payload = new LinkedHashMap<>();payload.put("fileName", file.getFileName().toString());payload.put("fileBase64", fileBase64);Map<String, Object> reqBody = new LinkedHashMap<>();reqBody.put("outTradeNo", outTradeNo);reqBody.put("checkType", Integer.parseInt(checkType)); // 数字码:1=AI率 2=相似度 3=参考文献reqBody.put("title", title);reqBody.put("payload", payload);byte[] bodyBytes = MAPPER.writeValueAsBytes(reqBody);Map<String, String> headers = authHeaders("POST", path, sha256Hex(bodyBytes));HttpRequest.Builder rb = HttpRequest.newBuilder(URI.create(BASE_URL + path)).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofByteArray(bodyBytes));headers.forEach(rb::header);System.out.println(HttpClient.newHttpClient().send(rb.build(), HttpResponse.BodyHandlers.ofString()).body());}static void get(String path) throws Exception {Map<String, String> headers = authHeaders("GET", path, sha256Hex(new byte[0]));HttpRequest.Builder rb = HttpRequest.newBuilder(URI.create(BASE_URL + path)).GET();headers.forEach(rb::header);System.out.println(HttpClient.newHttpClient().send(rb.build(), HttpResponse.BodyHandlers.ofString()).body());}static Map<String, String> authHeaders(String method, String path, String bodyHash) throws Exception {String ts = String.valueOf(System.currentTimeMillis());byte[] nb = new byte[16];new SecureRandom().nextBytes(nb);String nonce = HexFormat.of().formatHex(nb);String content = method + "\n" + path + "\n" + ts + "\n" + nonce + "\n" + bodyHash;Mac mac = Mac.getInstance("HmacSHA256");mac.init(new SecretKeySpec(Base64.getDecoder().decode(APP_SECRET), "HmacSHA256"));String sign = Base64.getEncoder().encodeToString(mac.doFinal(content.getBytes(StandardCharsets.UTF_8)));Map<String, String> h = new LinkedHashMap<>();h.put("X-App-Id", APP_ID);h.put("X-Timestamp", ts);h.put("X-Nonce", nonce);h.put("X-Signature", sign);return h;}static String sha256Hex(byte[] data) throws Exception {return HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(data));}static String envOr(String k, String d) {String v = System.getenv(k);return v == null || v.isBlank() ? d : v;}}