'commit'
This commit is contained in:
@@ -11,6 +11,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jfinal.kit.StrKit;
|
||||
import lombok.Getter;
|
||||
import okhttp3.*;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
@@ -49,6 +50,7 @@ public class LibLibCommon {
|
||||
|
||||
/**
|
||||
* 创建OkHttpClient实例
|
||||
*
|
||||
* @return OkHttpClient实例
|
||||
*/
|
||||
protected static OkHttpClient createHttpClient() {
|
||||
@@ -61,16 +63,22 @@ public class LibLibCommon {
|
||||
|
||||
/**
|
||||
* 生成完整的签名信息,包括签名、时间戳和随机字符串
|
||||
*
|
||||
* @param uri API接口的uri地址
|
||||
* @return 签名信息对象
|
||||
*/
|
||||
public static SignatureInfo sign(String uri) {
|
||||
return sign(uri, 0, null);
|
||||
}
|
||||
|
||||
public static SignatureInfo sign(String uri, long timestamp, String signatureNonce) {
|
||||
// 当前毫秒时间戳
|
||||
long timestamp = System.currentTimeMillis();
|
||||
if (timestamp == 0) timestamp = System.currentTimeMillis();
|
||||
// 随机字符串
|
||||
String signatureNonce = RandomStringUtils.randomAlphanumeric(10);
|
||||
if (StrKit.isBlank(signatureNonce)) signatureNonce = RandomStringUtils.randomAlphanumeric(10);
|
||||
// 拼接请求数据
|
||||
String content = uri + "&" + timestamp + "&" + signatureNonce;
|
||||
System.out.println(content);
|
||||
try {
|
||||
// 生成签名
|
||||
SecretKeySpec secret = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
|
||||
@@ -87,6 +95,7 @@ public class LibLibCommon {
|
||||
|
||||
/**
|
||||
* 清理URL,移除可能的反引号和多余空格
|
||||
*
|
||||
* @param url 原始URL
|
||||
* @return 清理后的URL
|
||||
*/
|
||||
@@ -99,6 +108,7 @@ public class LibLibCommon {
|
||||
|
||||
/**
|
||||
* 构建带签名的URL
|
||||
*
|
||||
* @param uri API路径
|
||||
* @param signInfo 签名信息
|
||||
* @return 构建好的HttpUrl.Builder
|
||||
@@ -113,6 +123,7 @@ public class LibLibCommon {
|
||||
|
||||
/**
|
||||
* 发送HTTP请求并处理响应
|
||||
*
|
||||
* @param request HTTP请求
|
||||
* @param logPrefix 日志前缀
|
||||
* @return 响应的JSON对象
|
||||
@@ -219,6 +230,7 @@ public class LibLibCommon {
|
||||
|
||||
/**
|
||||
* 创建通用的HTTP请求
|
||||
*
|
||||
* @param uri API路径
|
||||
* @param requestBody 请求体JSON对象
|
||||
* @return 构建好的Request对象
|
||||
@@ -242,8 +254,8 @@ public class LibLibCommon {
|
||||
|
||||
public static void main(String[] args) {
|
||||
String uri = "https://openapi.liblibai.cloud/api/model/version/get";
|
||||
SignatureInfo signInfo = sign(uri);
|
||||
SignatureInfo signInfo = sign(uri, 1756799766502L, "K91nkXyrCH");
|
||||
|
||||
System.out.println(signInfo.toString());
|
||||
System.out.println(signInfo.getSignature());
|
||||
}
|
||||
}
|
249
dsLightRag/Liblib/LibLibCommon.java
Normal file
249
dsLightRag/Liblib/LibLibCommon.java
Normal file
@@ -0,0 +1,249 @@
|
||||
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());
|
||||
}
|
||||
}
|
45
dsLightRag/Liblib/T1_Test.py
Normal file
45
dsLightRag/Liblib/T1_Test.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import hashlib
|
||||
|
||||
import requests
|
||||
import json
|
||||
import hmac
|
||||
from hashlib import sha1
|
||||
import base64
|
||||
import time
|
||||
import string
|
||||
import secrets
|
||||
|
||||
from Config.Config import LIBLIB_SECRETKEY, LIBLIB_URL, LIBLIB_ACCESSKEY
|
||||
|
||||
|
||||
class SignatureInfo:
|
||||
"""签名信息封装类,对应Java的SignatureInfo类"""
|
||||
|
||||
def __init__(self, signature: str, timestamp: int, signature_nonce: str):
|
||||
self.signature = signature
|
||||
self.timestamp = timestamp
|
||||
self.signature_nonce = signature_nonce
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"SignatureInfo(signature='{self.signature}', timestamp={self.timestamp}, signature_nonce='{self.signature_nonce}')"
|
||||
|
||||
|
||||
def make_sign(uri, timestamp, signatureNonce):
|
||||
# 当前毫秒时间戳(修正:使用整数类型)
|
||||
if timestamp == 0:
|
||||
timestamp = int(time.time() * 1000)
|
||||
if signatureNonce is None:
|
||||
signatureNonce = ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(10))
|
||||
content = f"{uri}&{timestamp}&{signatureNonce}"
|
||||
print(content)
|
||||
signature = hmac.new(LIBLIB_SECRETKEY.encode('utf-8'), content.encode('utf-8'), digestmod=hashlib.sha1).digest()
|
||||
signature = base64.urlsafe_b64encode(signature).decode('utf-8').strip()
|
||||
return SignatureInfo(signature, timestamp, signatureNonce)
|
||||
|
||||
|
||||
# 请求API接口的uri地址(修正:使用相对路径,不包含域名)
|
||||
uri = f"/api/model/version/get"
|
||||
# 生成签名信息(确保在URL构建前调用)
|
||||
signature_info = make_sign(LIBLIB_URL+uri,1756799766502,'K91nkXyrCH') # 使用API_PATH而非完整URL
|
||||
|
||||
print(signature_info)
|
@@ -1,51 +1,98 @@
|
||||
import hashlib
|
||||
|
||||
import requests
|
||||
import json
|
||||
import hmac
|
||||
from hashlib import sha1
|
||||
import base64
|
||||
import time
|
||||
import uuid
|
||||
import string
|
||||
import secrets
|
||||
|
||||
from Config.Config import LIBLIB_SECRETKEY, LIBLIB_URL, LIBLIB_ACCESSKEY
|
||||
|
||||
|
||||
class SignatureInfo:
|
||||
"""签名信息封装类,对应Java的SignatureInfo类"""
|
||||
def __init__(self, signature: str, timestamp: int, signature_nonce: str):
|
||||
self.signature = signature
|
||||
self.timestamp = timestamp
|
||||
self.signature_nonce = signature_nonce
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"SignatureInfo(signature='{self.signature}', timestamp={self.timestamp}, signature_nonce='{self.signature_nonce}')"
|
||||
|
||||
|
||||
def make_sign(uri):
|
||||
"""
|
||||
生成签名
|
||||
"""
|
||||
# 当前毫秒时间戳
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
# 随机字符串
|
||||
signature_nonce = str(uuid.uuid4())
|
||||
# 拼接请求数据
|
||||
content = '&'.join((uri, timestamp, signature_nonce))
|
||||
# 生成签名
|
||||
digest = hmac.new(LIBLIB_SECRETKEY.encode(), content.encode(), sha1).digest()
|
||||
# 移除为了补全base64位数而填充的尾部等号
|
||||
sign = base64.urlsafe_b64encode(digest).rstrip(b'=').decode()
|
||||
return sign, timestamp, signature_nonce
|
||||
# 当前毫秒时间戳(修正:使用整数类型)
|
||||
timestamp = int(time.time() * 1000)
|
||||
# 生成10位字母数字随机字符串(修正:匹配Java的randomAlphanumeric)
|
||||
signature_nonce = ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(10))
|
||||
# 拼接签名内容(修正:使用Java相同的顺序和分隔符)
|
||||
content = f"{uri}&{timestamp}&{signature_nonce}"
|
||||
# HMAC-SHA1签名(修正:确保编码一致)
|
||||
signature = hmac.new(LIBLIB_SECRETKEY.encode('utf-8'), content.encode('utf-8'), digestmod=hashlib.sha1).digest()
|
||||
# Base64 URL安全编码(修正:使用URL安全编码)
|
||||
signature = base64.urlsafe_b64encode(signature).decode('utf-8').strip()
|
||||
print(f"签名调试信息:\nURI: {uri}\nTimestamp: {timestamp}\nNonce: {signature_nonce}\nContent: {content}\nSignature: {signature}")
|
||||
return SignatureInfo(signature, timestamp, signature_nonce)
|
||||
|
||||
|
||||
# 请求API接口的uri地址
|
||||
uri = f"{LIBLIB_URL}/api/model/version/get"
|
||||
Signature, timestamp, signature_nonce = make_sign(uri)
|
||||
# 请求API接口的uri地址(修正:使用相对路径,不包含域名)
|
||||
uri = f"/api/model/version/get"
|
||||
# 生成签名信息(确保在URL构建前调用)
|
||||
signature_info = make_sign(uri) # 使用API_PATH而非完整URL
|
||||
|
||||
print(Signature)
|
||||
print(timestamp)
|
||||
print(signature_nonce)
|
||||
# 构建完整URL(修正:此处才拼接基础URL)
|
||||
# API配置(确保以下常量已定义)
|
||||
LIBLIB_URL = "https://openapi.liblibai.cloud"
|
||||
API_PATH = '/api/model/version/get'
|
||||
LIBLIB_ACCESSKEY = 'sOCtVLVTNOZkRMajlhzCmg' # 从Java代码同步的AccessKey
|
||||
version_uuid = 'YOUR_VERSION_UUID' # 替换为实际UUID
|
||||
# 构建完整URL(修正:使用signature_info对象属性)
|
||||
full_url = f"{LIBLIB_URL}{API_PATH}?version_uuid={version_uuid}&AccessKey={LIBLIB_ACCESSKEY}&Signature={signature_info.signature}&Timestamp={signature_info.timestamp}&SignatureNonce={signature_info.signature_nonce}"
|
||||
|
||||
url = f"{uri}?AccessKey={LIBLIB_ACCESSKEY}&Signature={Signature}&Timestamp={timestamp}&SignatureNonce={signature_nonce}"
|
||||
|
||||
# 设置请求头
|
||||
# 定义请求头
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
# 定义请求体
|
||||
version_uuid = "4bb1335feb1e4d2eafe5a77bb93e861f"
|
||||
# 准备请求体数据
|
||||
request_body = {"version_uuid": version_uuid}
|
||||
|
||||
# 发送请求(使用正确的full_url变量)
|
||||
response = requests.post(full_url, headers=headers, json=request_body)
|
||||
|
||||
# 添加详细调试输出
|
||||
#print(f"请求URL: {url}")
|
||||
# 修正:在使用headers前定义请求头
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
# 定义version_uuid变量(请替换为实际的UUID值)
|
||||
version_uuid = "4bb1335feb1e4d2eafe5a77bb93e861f"
|
||||
|
||||
# 构建请求体
|
||||
request_body = {"version_uuid": version_uuid}
|
||||
print(f"请求头: {headers}")
|
||||
print(f"请求体: {json.dumps(request_body)}")
|
||||
|
||||
try:
|
||||
# 发送POST请求
|
||||
response = requests.post(url, headers=headers, data=json.dumps(request_body))
|
||||
response.raise_for_status() # 检查请求是否成功
|
||||
# 修改请求方法为POST并添加完整参数
|
||||
response = requests.post(LIBLIB_URL+uri, headers=headers, json=request_body)
|
||||
|
||||
# 增加详细调试输出
|
||||
print(f"完整请求URL: {LIBLIB_URL}{uri}")
|
||||
print(f"请求方法: POST")
|
||||
print(f"请求头: {headers}")
|
||||
print(f"请求体: {json.dumps(request_body, ensure_ascii=False)}")
|
||||
print(f"响应状态码: {response.status_code}")
|
||||
print(f"响应内容: {response.text}")
|
||||
|
||||
# 验证version_uuid有效性(请替换为实际有效的UUID)
|
||||
version_uuid = "有效的模型版本UUID"
|
||||
print(f"请求体: {json.dumps(request_body)}")
|
||||
print(f"响应状态码: {response.status_code}")
|
||||
print(f"响应内容: {response.text}") # 打印完整响应内容
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
print(result.get("code"))
|
||||
print(result.get("msg"))
|
||||
|
Reference in New Issue
Block a user