249 lines
9.0 KiB
Java
249 lines
9.0 KiB
Java
package com.dsideal.Ai.Util.Liblib.Kit;
|
||
|
||
import java.security.InvalidKeyException;
|
||
import java.security.NoSuchAlgorithmException;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.util.concurrent.TimeUnit;
|
||
|
||
import javax.crypto.Mac;
|
||
import javax.crypto.spec.SecretKeySpec;
|
||
|
||
import com.alibaba.fastjson.JSON;
|
||
import com.alibaba.fastjson.JSONObject;
|
||
import lombok.Getter;
|
||
import okhttp3.*;
|
||
import org.apache.commons.codec.binary.Base64;
|
||
import org.apache.commons.lang3.RandomStringUtils;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
|
||
import java.io.IOException;
|
||
|
||
public class LibLibCommon {
|
||
// API基础URL
|
||
protected static final String API_BASE_URL = "https://openapi.liblibai.cloud";
|
||
// API访问凭证
|
||
protected static final String accessKey="sOCtVLVTNOZkRMajlhzCmg"; // Access Key
|
||
protected static final String secretKey="PUe8QTRG9i0G9EbpedHmIpLQ0FyxoYY9"; // Secret Key
|
||
// 查询任务状态API路径
|
||
protected static final String QUERY_STATUS_PATH = "/api/generate/webui/status";
|
||
// 日志
|
||
private static final Logger log = LoggerFactory.getLogger(LibLibCommon.class);
|
||
|
||
/**
|
||
* 签名信息类,包含签名、时间戳和随机字符串
|
||
*/
|
||
@Getter
|
||
public static class SignatureInfo {
|
||
private final String signature;
|
||
private final long timestamp;
|
||
private final String signatureNonce;
|
||
|
||
public SignatureInfo(String signature, long timestamp, String signatureNonce) {
|
||
this.signature = signature;
|
||
this.timestamp = timestamp;
|
||
this.signatureNonce = signatureNonce;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建OkHttpClient实例
|
||
* @return OkHttpClient实例
|
||
*/
|
||
protected static OkHttpClient createHttpClient() {
|
||
return new OkHttpClient.Builder()
|
||
.connectTimeout(30, TimeUnit.SECONDS)
|
||
.readTimeout(60, TimeUnit.SECONDS)
|
||
.writeTimeout(60, TimeUnit.SECONDS)
|
||
.build();
|
||
}
|
||
|
||
/**
|
||
* 生成完整的签名信息,包括签名、时间戳和随机字符串
|
||
* @param uri API接口的uri地址
|
||
* @return 签名信息对象
|
||
*/
|
||
public static SignatureInfo sign(String uri) {
|
||
// 当前毫秒时间戳
|
||
long timestamp = System.currentTimeMillis();
|
||
// 随机字符串
|
||
String signatureNonce = RandomStringUtils.randomAlphanumeric(10);
|
||
// 拼接请求数据
|
||
String content = uri + "&" + timestamp + "&" + signatureNonce;
|
||
try {
|
||
// 生成签名
|
||
SecretKeySpec secret = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
|
||
Mac mac = Mac.getInstance("HmacSHA1");
|
||
mac.init(secret);
|
||
String signature = Base64.encodeBase64URLSafeString(mac.doFinal(content.getBytes()));
|
||
return new SignatureInfo(signature, timestamp, signatureNonce);
|
||
} catch (NoSuchAlgorithmException e) {
|
||
throw new RuntimeException("no such algorithm");
|
||
} catch (InvalidKeyException e) {
|
||
throw new RuntimeException(e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 清理URL,移除可能的反引号和多余空格
|
||
* @param url 原始URL
|
||
* @return 清理后的URL
|
||
*/
|
||
protected static String cleanUrl(String url) {
|
||
if (url == null || url.isEmpty()) {
|
||
return url;
|
||
}
|
||
return url.trim().replace("`", "");
|
||
}
|
||
|
||
/**
|
||
* 构建带签名的URL
|
||
* @param uri API路径
|
||
* @param signInfo 签名信息
|
||
* @return 构建好的HttpUrl.Builder
|
||
*/
|
||
protected static HttpUrl.Builder buildSignedUrl(String uri, SignatureInfo signInfo) {
|
||
return HttpUrl.parse(API_BASE_URL + uri).newBuilder()
|
||
.addQueryParameter("AccessKey", accessKey)
|
||
.addQueryParameter("Signature", signInfo.getSignature())
|
||
.addQueryParameter("Timestamp", String.valueOf(signInfo.getTimestamp()))
|
||
.addQueryParameter("SignatureNonce", signInfo.getSignatureNonce());
|
||
}
|
||
|
||
/**
|
||
* 发送HTTP请求并处理响应
|
||
* @param request HTTP请求
|
||
* @param logPrefix 日志前缀
|
||
* @return 响应的JSON对象
|
||
* @throws IOException 异常信息
|
||
*/
|
||
protected static JSONObject sendRequest(Request request, String logPrefix) throws IOException {
|
||
OkHttpClient client = createHttpClient();
|
||
|
||
// 执行请求
|
||
log.info("{}: {}", logPrefix, request.url());
|
||
Response response = client.newCall(request).execute();
|
||
|
||
// 处理响应
|
||
if (!response.isSuccessful()) {
|
||
String errorMsg = logPrefix + "失败,状态码: " + response.code();
|
||
log.error(errorMsg);
|
||
throw new IOException(errorMsg);
|
||
}
|
||
|
||
// 解析响应
|
||
String responseBody = response.body().string();
|
||
log.info("{}响应: {}", logPrefix, responseBody);
|
||
|
||
JSONObject responseJson = JSON.parseObject(responseBody);
|
||
int code = responseJson.getIntValue("code");
|
||
|
||
if (code != 0) {
|
||
String errorMsg = logPrefix + "失败,错误码: " + code + ", 错误信息: " + responseJson.getString("msg");
|
||
log.error(errorMsg);
|
||
throw new IOException(errorMsg);
|
||
}
|
||
|
||
return responseJson;
|
||
}
|
||
|
||
/**
|
||
* 查询生图任务结果
|
||
*
|
||
* @param generateUuid 生图任务UUID
|
||
* @return 任务结果信息
|
||
* @throws IOException 异常信息
|
||
*/
|
||
public static JSONObject queryTaskResult(String generateUuid) throws IOException {
|
||
// 构建请求体
|
||
JSONObject requestBody = new JSONObject();
|
||
requestBody.put("generateUuid", generateUuid);
|
||
|
||
// 获取API路径
|
||
String uri = QUERY_STATUS_PATH;
|
||
|
||
// 生成签名信息
|
||
SignatureInfo signInfo = sign(uri);
|
||
|
||
// 构建带签名的URL
|
||
HttpUrl.Builder urlBuilder = buildSignedUrl(uri, signInfo);
|
||
|
||
// 创建请求
|
||
MediaType mediaType = MediaType.parse("application/json");
|
||
RequestBody body = RequestBody.create(mediaType, requestBody.toJSONString());
|
||
Request request = new Request.Builder()
|
||
.url(urlBuilder.build())
|
||
.method("POST", body)
|
||
.addHeader("Content-Type", "application/json")
|
||
.build();
|
||
|
||
// 发送请求并获取响应
|
||
JSONObject responseJson = sendRequest(request, "查询生图任务结果");
|
||
|
||
return responseJson.getJSONObject("data");
|
||
}
|
||
|
||
/**
|
||
* 获取生成图片的URL列表
|
||
*
|
||
* @param generateUuid 生图任务UUID
|
||
* @return 图片URL列表
|
||
* @throws IOException 异常信息
|
||
*/
|
||
public static List<String> getGeneratedImageUrls(String generateUuid) throws IOException {
|
||
JSONObject resultData = queryTaskResult(generateUuid);
|
||
List<String> imageUrls = new ArrayList<>();
|
||
|
||
// 检查生成状态
|
||
int generateStatus = resultData.getIntValue("generateStatus");
|
||
if (generateStatus == 5) { // 5表示生成成功
|
||
if (resultData.containsKey("images")) {
|
||
for (Object imageObj : resultData.getJSONArray("images")) {
|
||
JSONObject imageJson = (JSONObject) imageObj;
|
||
String imageUrl = imageJson.getString("imageUrl");
|
||
if (imageUrl != null && !imageUrl.isEmpty()) {
|
||
// 清理URL
|
||
imageUrl = cleanUrl(imageUrl);
|
||
imageUrls.add(imageUrl);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
log.info("生图任务尚未完成,当前状态: {}, 完成百分比: {}%",
|
||
generateStatus, resultData.getIntValue("percentCompleted"));
|
||
}
|
||
|
||
return imageUrls;
|
||
}
|
||
|
||
/**
|
||
* 创建通用的HTTP请求
|
||
* @param uri API路径
|
||
* @param requestBody 请求体JSON对象
|
||
* @return 构建好的Request对象
|
||
*/
|
||
protected static Request createRequest(String uri, JSONObject requestBody) {
|
||
// 生成签名信息
|
||
SignatureInfo signInfo = sign(uri);
|
||
|
||
// 构建带签名的URL
|
||
HttpUrl.Builder urlBuilder = buildSignedUrl(uri, signInfo);
|
||
|
||
// 创建请求
|
||
MediaType mediaType = MediaType.parse("application/json");
|
||
RequestBody body = RequestBody.create(mediaType, requestBody.toJSONString());
|
||
return new Request.Builder()
|
||
.url(urlBuilder.build())
|
||
.method("POST", body)
|
||
.addHeader("Content-Type", "application/json")
|
||
.build();
|
||
}
|
||
|
||
public static void main(String[] args) {
|
||
String uri = "https://openapi.liblibai.cloud/api/model/version/get";
|
||
SignatureInfo signInfo = sign(uri);
|
||
|
||
System.out.println(signInfo.toString());
|
||
}
|
||
} |