113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
"use server";
|
||
import * as crypto from "node:crypto";
|
||
// 使用 SHA-256 和 secret 进行 HMAC 加密
|
||
function sha256(message: any, secret = "", encoding?: string) {
|
||
return crypto
|
||
.createHmac("sha256", secret)
|
||
.update(message)
|
||
.digest(encoding as any);
|
||
}
|
||
|
||
// 使用 SHA-256 进行哈希
|
||
function getHash(message: any, encoding = "hex") {
|
||
return crypto
|
||
.createHash("sha256")
|
||
.update(message)
|
||
.digest(encoding as any);
|
||
}
|
||
|
||
function getDate(timestamp: number) {
|
||
const date = new Date(timestamp * 1000);
|
||
const year = date.getUTCFullYear();
|
||
const month = ("0" + (date.getUTCMonth() + 1)).slice(-2);
|
||
const day = ("0" + date.getUTCDate()).slice(-2);
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
|
||
export async function getHeader(
|
||
payload: any,
|
||
SECRET_ID: string,
|
||
SECRET_KEY: string,
|
||
) {
|
||
// https://cloud.tencent.com/document/api/1729/105701
|
||
|
||
const endpoint = "hunyuan.tencentcloudapi.com";
|
||
const service = "hunyuan";
|
||
const region = ""; // optional
|
||
const action = "ChatCompletions";
|
||
const version = "2023-09-01";
|
||
const timestamp = Math.floor(Date.now() / 1000);
|
||
//时间处理, 获取世界时间日期
|
||
const date = getDate(timestamp);
|
||
|
||
// ************* 步骤 1:拼接规范请求串 *************
|
||
|
||
const hashedRequestPayload = getHash(payload);
|
||
const httpRequestMethod = "POST";
|
||
const contentType = "application/json";
|
||
const canonicalUri = "/";
|
||
const canonicalQueryString = "";
|
||
const canonicalHeaders =
|
||
`content-type:${contentType}\n` +
|
||
"host:" +
|
||
endpoint +
|
||
"\n" +
|
||
"x-tc-action:" +
|
||
action.toLowerCase() +
|
||
"\n";
|
||
const signedHeaders = "content-type;host;x-tc-action";
|
||
|
||
const canonicalRequest = [
|
||
httpRequestMethod,
|
||
canonicalUri,
|
||
canonicalQueryString,
|
||
canonicalHeaders,
|
||
signedHeaders,
|
||
hashedRequestPayload,
|
||
].join("\n");
|
||
|
||
// ************* 步骤 2:拼接待签名字符串 *************
|
||
const algorithm = "TC3-HMAC-SHA256";
|
||
const hashedCanonicalRequest = getHash(canonicalRequest);
|
||
const credentialScope = date + "/" + service + "/" + "tc3_request";
|
||
const stringToSign =
|
||
algorithm +
|
||
"\n" +
|
||
timestamp +
|
||
"\n" +
|
||
credentialScope +
|
||
"\n" +
|
||
hashedCanonicalRequest;
|
||
|
||
// ************* 步骤 3:计算签名 *************
|
||
const kDate = sha256(date, "TC3" + SECRET_KEY);
|
||
const kService = sha256(service, kDate);
|
||
const kSigning = sha256("tc3_request", kService);
|
||
const signature = sha256(stringToSign, kSigning, "hex");
|
||
|
||
// ************* 步骤 4:拼接 Authorization *************
|
||
const authorization =
|
||
algorithm +
|
||
" " +
|
||
"Credential=" +
|
||
SECRET_ID +
|
||
"/" +
|
||
credentialScope +
|
||
", " +
|
||
"SignedHeaders=" +
|
||
signedHeaders +
|
||
", " +
|
||
"Signature=" +
|
||
signature;
|
||
|
||
return {
|
||
Authorization: authorization,
|
||
"Content-Type": contentType,
|
||
Host: endpoint,
|
||
"X-TC-Action": action,
|
||
"X-TC-Timestamp": timestamp.toString(),
|
||
"X-TC-Version": version,
|
||
"X-TC-Region": region,
|
||
};
|
||
}
|