11package org .springframework .ai .hunyuan .api .auth ;
22
3+ import org .slf4j .Logger ;
4+ import org .slf4j .LoggerFactory ;
35import org .springframework .ai .hunyuan .api .HunYuanApi ;
46import org .springframework .ai .hunyuan .api .HunYuanConstants ;
57import org .springframework .ai .model .ModelOptionsUtils ;
1820import javax .xml .bind .DatatypeConverter ;
1921
2022import static org .springframework .ai .hunyuan .api .HunYuanConstants .CT_JSON ;
21-
23+ /**
24+ * The HunYuanAuthApi class is responsible for handling authentication-related operations
25+ * for the HunYuan API. It provides methods to generate necessary headers and signatures
26+ * required for authenticated requests.
27+ * @author Your Name
28+ */
2229public class HunYuanAuthApi {
30+
31+ private static final Logger logger = LoggerFactory .getLogger (HunYuanAuthApi .class );
32+
2333 private final static Charset UTF8 = StandardCharsets .UTF_8 ;
2434
2535 private final String secretId ;
2636
2737 private final String secretKey ;
2838
39+ /**
40+ * Constructs a HunYuanAuthApi instance with the specified secret ID and secret key.
41+ * @param secretId The secret ID used for authentication.
42+ * @param secretKey The secret key used for authentication.
43+ */
2944 public HunYuanAuthApi (String secretId , String secretKey ) {
3045 this .secretId = secretId ;
3146 this .secretKey = secretKey ;
3247 }
3348
49+ /**
50+ * Generates an HMAC-SHA256 signature using the provided key and message.
51+ * @param key The key used for generating the HMAC-SHA256 signature.
52+ * @param msg The message to be signed.
53+ * @return The byte array of the generated HMAC-SHA256 signature.
54+ */
3455 public byte [] hmac256 (byte [] key , String msg ){
3556 Mac mac = null ;
3657 try {
@@ -43,6 +64,11 @@ public byte[] hmac256(byte[] key, String msg){
4364 return mac .doFinal (msg .getBytes (UTF8 ));
4465 }
4566
67+ /**
68+ * Computes the SHA-256 hash of the provided string and returns it as a hexadecimal string.
69+ * @param s The string to be hashed.
70+ * @return The SHA-256 hash of the input string in hexadecimal format.
71+ */
4672 public String sha256Hex (String s ) {
4773 MessageDigest md = null ;
4874 try {
@@ -54,17 +80,25 @@ public String sha256Hex(String s) {
5480 return DatatypeConverter .printHexBinary (d ).toLowerCase ();
5581 }
5682
83+ /**
84+ * Generates the HTTP headers required for making authenticated requests to the HunYuan API.
85+ * @param host The host address of the API endpoint.
86+ * @param action The action to be performed (e.g., "ChatCompletion").
87+ * @param service The service name associated with the request.
88+ * @param payload The request payload containing the necessary parameters.
89+ * @return A MultiValueMap containing the HTTP headers needed for the authenticated request.
90+ */
5791 public MultiValueMap <String , String > getHttpHeadersConsumer (String host , String action , String service , HunYuanApi .ChatCompletionRequest payload ){
5892 String version = HunYuanConstants .DEFAULT_VERSION ;
5993 String algorithm = HunYuanConstants .DEFAULT_ALGORITHM ;
6094// String timestamp = "1551113065";
6195 String timestamp = String .valueOf (System .currentTimeMillis () / 1000 );
6296 SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd" );
63- // 注意时区,否则容易出错
97+ // Pay attention to the time zone, otherwise it will be easy to make mistakes
6498 sdf .setTimeZone (TimeZone .getTimeZone ("UTC" ));
6599 String date = sdf .format (new Date (Long .valueOf (timestamp + "000" )));
66100
67- // ************* 步骤 1:拼接规范请求串 *************
101+ // ************* Step 1: Splice specification request strings *************
68102 String httpRequestMethod = "POST" ;
69103 String canonicalUri = "/" ;
70104 String canonicalQueryString = "" ;
@@ -74,22 +108,19 @@ public MultiValueMap<String, String> getHttpHeadersConsumer(String host, String
74108
75109// String payload = "{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}";
76110 String payloadString = ModelOptionsUtils .toJsonString (payload );
77- System .out .println (payloadString );
78111 String hashedRequestPayload = sha256Hex (payloadString );
79112 String canonicalRequest = httpRequestMethod + "\n " + canonicalUri + "\n " + canonicalQueryString + "\n "
80113 + canonicalHeaders + "\n " + signedHeaders + "\n " + hashedRequestPayload ;
81- // ************* 步骤 2:拼接待签名字符串 *************
114+ // ************* Step 2: Splice the string to be signed *************
82115 String credentialScope = date + "/" + service + "/" + "tc3_request" ;
83116 String hashedCanonicalRequest = sha256Hex (canonicalRequest );
84117 String stringToSign = algorithm + "\n " + timestamp + "\n " + credentialScope + "\n " + hashedCanonicalRequest ;
85- System .out .println (stringToSign );
86- // ************* 步骤 3:计算签名 *************
118+ // ************* Step 3: Calculate the signature *************
87119 byte [] secretDate = hmac256 (("TC3" + secretKey ).getBytes (UTF8 ), date );
88120 byte [] secretService = hmac256 (secretDate , service );
89121 byte [] secretSigning = hmac256 (secretService , "tc3_request" );
90122 String signature = DatatypeConverter .printHexBinary (hmac256 (secretSigning , stringToSign )).toLowerCase ();
91- System .out .println (signature );
92- // ************* 步骤 4:拼接 Authorization *************
123+ // ************* Step 4: Splice Authorization *************
93124 String authorization = algorithm + " " + "Credential=" + secretId + "/" + credentialScope + ", "
94125 + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature ;
95126
@@ -101,17 +132,18 @@ public MultiValueMap<String, String> getHttpHeadersConsumer(String host, String
101132 headers .put ("X-TC-Timestamp" , timestamp );
102133 headers .put ("X-TC-Version" , version );
103134
104- StringBuilder sb = new StringBuilder ();
105- sb .append ("curl -X POST https://" ).append (host )
106- .append (" -H \" Authorization: " ).append (authorization ).append ("\" " )
107- .append (" -H \" Content-Type: application/json; charset=utf-8\" " )
108- .append (" -H \" Host: " ).append (host ).append ("\" " )
109- .append (" -H \" X-TC-Action: " ).append (action ).append ("\" " )
110- .append (" -H \" X-TC-Timestamp: " ).append (timestamp ).append ("\" " )
111- .append (" -H \" X-TC-Version: " ).append (version ).append ("\" " )
112- .append (" -d '" ).append (payloadString ).append ("'" );
113- System .out .println (sb .toString ());
114-
135+ if (logger .isDebugEnabled ()){
136+ StringBuilder sb = new StringBuilder ();
137+ sb .append ("curl -X POST https://" ).append (host )
138+ .append (" -H \" Authorization: " ).append (authorization ).append ("\" " )
139+ .append (" -H \" Content-Type: application/json; charset=utf-8\" " )
140+ .append (" -H \" Host: " ).append (host ).append ("\" " )
141+ .append (" -H \" X-TC-Action: " ).append (action ).append ("\" " )
142+ .append (" -H \" X-TC-Timestamp: " ).append (timestamp ).append ("\" " )
143+ .append (" -H \" X-TC-Version: " ).append (version ).append ("\" " )
144+ .append (" -d '" ).append (payloadString ).append ("'" );
145+ logger .debug (sb .toString ());
146+ }
115147 return CollectionUtils .toMultiValueMap (
116148 headers .entrySet ().stream ().collect (Collectors .toMap (Map .Entry ::getKey , e -> List .of (e .getValue ()))));
117149 }
0 commit comments