chore: sdk

This commit is contained in:
xiaojunnuo
2026-05-14 18:31:25 +08:00
parent f8f51adf88
commit 639756dfcd
11 changed files with 874 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
import java.io.IOException;
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.time.Instant;
import java.util.Base64;
public class CertdClient {
private final String keyId;
private final String keySecret;
private final String baseUrl;
private final boolean encrypt;
private final String signType;
public CertdClient(String keyId, String keySecret) {
this(keyId, keySecret, "http://127.0.0.1:7001", false);
}
public CertdClient(String keyId, String keySecret, String baseUrl, boolean encrypt) {
if (isBlank(keyId)) {
throw new IllegalArgumentException("keyId is required");
}
if (isBlank(keySecret)) {
throw new IllegalArgumentException("keySecret is required");
}
this.keyId = keyId;
this.keySecret = keySecret;
this.baseUrl = trimRightSlash(isBlank(baseUrl) ? "http://127.0.0.1:7001" : baseUrl);
this.encrypt = encrypt;
this.signType = "md5";
}
public String getSign(String content) throws Exception {
if (!"md5".equals(signType)) {
throw new IllegalArgumentException("Unsupported signType: " + signType);
}
return md5Hex(content + keySecret);
}
public String getToken() throws Exception {
String content = "{\"keyId\":\"" + jsonEscape(keyId) + "\",\"t\":" + Instant.now().getEpochSecond()
+ ",\"encrypt\":" + encrypt + ",\"signType\":\"" + signType + "\"}";
String sign = getSign(content);
return base64(content) + "." + base64(sign);
}
public String request(String path, String bodyJson) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + path))
.header("content-type", "application/json")
.header("x-certd-token", getToken())
.POST(HttpRequest.BodyPublishers.ofString(bodyJson, StandardCharsets.UTF_8))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IOException("HTTP " + response.statusCode() + ": " + response.body());
}
return response.body();
}
public String getCert(String paramsJson) throws Exception {
return request("/api/v1/cert/get", paramsJson);
}
public static String jsonEscape(String value) {
StringBuilder escaped = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char ch = value.charAt(i);
switch (ch) {
case '"':
escaped.append("\\\"");
break;
case '\\':
escaped.append("\\\\");
break;
case '\b':
escaped.append("\\b");
break;
case '\f':
escaped.append("\\f");
break;
case '\n':
escaped.append("\\n");
break;
case '\r':
escaped.append("\\r");
break;
case '\t':
escaped.append("\\t");
break;
default:
if (ch < 0x20) {
escaped.append(String.format("\\u%04x", (int) ch));
} else {
escaped.append(ch);
}
}
}
return escaped.toString();
}
private static String md5Hex(String value) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(value.getBytes(StandardCharsets.UTF_8));
StringBuilder hex = new StringBuilder();
for (byte b : digest) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
private static String base64(String value) {
return Base64.getEncoder().encodeToString(value.getBytes(StandardCharsets.UTF_8));
}
private static boolean isBlank(String value) {
return value == null || value.isBlank();
}
private static String trimRightSlash(String value) {
return value.replaceAll("/+$", "");
}
}
+84
View File
@@ -0,0 +1,84 @@
public class GetCert {
public static void main(String[] args) {
try {
new GetCert().run();
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
private void run() throws Exception {
CertdClient client = new CertdClient(
requireEnv("CERTD_KEY_ID"),
requireEnv("CERTD_KEY_SECRET"),
env("CERTD_BASE_URL", "http://127.0.0.1:7001"),
boolEnv("CERTD_ENCRYPT", false)
);
String certId = System.getenv("CERTD_CERT_ID");
String domains = System.getenv("CERTD_DOMAINS");
String format = System.getenv("CERTD_FORMAT");
if (isBlank(certId) && isBlank(domains)) {
throw new IllegalArgumentException("Set CERTD_CERT_ID or CERTD_DOMAINS");
}
StringBuilder body = new StringBuilder();
body.append("{");
boolean hasField = false;
if (!isBlank(certId)) {
body.append("\"certId\":").append(Long.parseLong(certId));
hasField = true;
}
if (!isBlank(domains)) {
appendComma(body, hasField);
body.append("\"domains\":\"").append(CertdClient.jsonEscape(domains)).append("\"");
hasField = true;
}
appendComma(body, hasField);
body.append("\"autoApply\":").append(boolEnv("CERTD_AUTO_APPLY", false));
hasField = true;
if (!isBlank(format)) {
appendComma(body, hasField);
body.append("\"format\":\"").append(CertdClient.jsonEscape(format)).append("\"");
}
body.append("}");
System.out.println(client.getCert(body.toString()));
}
private static String requireEnv(String name) {
String value = System.getenv(name);
if (isBlank(value)) {
throw new IllegalArgumentException("Missing environment variable: " + name);
}
return value;
}
private static String env(String name, String defaultValue) {
String value = System.getenv(name);
return isBlank(value) ? defaultValue : value;
}
private static boolean boolEnv(String name, boolean defaultValue) {
String value = System.getenv(name);
if (isBlank(value)) {
return defaultValue;
}
return value.equalsIgnoreCase("1")
|| value.equalsIgnoreCase("true")
|| value.equalsIgnoreCase("yes")
|| value.equalsIgnoreCase("y");
}
private static boolean isBlank(String value) {
return value == null || value.isBlank();
}
private static void appendComma(StringBuilder builder, boolean hasField) {
if (hasField) {
builder.append(",");
}
}
}