initial code

This commit is contained in:
2026-01-09 13:17:13 +07:00
commit d56d1c193b
68 changed files with 6529 additions and 0 deletions

81
src/utils/signer.ts Normal file
View File

@@ -0,0 +1,81 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { v4 as uuidv4 } from "uuid";
import CryptoJS from "crypto-js";
import { ENV } from "../constants/env";
/* =========================
HELPERS (COPY POSTMAN)
========================= */
export function parseQueryParamsManual(url: string) {
const result: Record<string, any> = {};
const queryStartIndex = url.indexOf("?");
if (queryStartIndex === -1 || queryStartIndex === url.length - 1) {
return result;
}
const queryString = url.substring(queryStartIndex + 1);
const pairs = queryString.split("&");
for (const pair of pairs) {
const parts = pair.split("=");
if (parts.length === 2) {
const key = decodeURIComponent(parts[0].replace(/\+/g, " "));
const value = decodeURIComponent(parts[1].replace(/\+/g, " "));
result[key] = value;
}
}
return result;
}
export function sortKeysDeep(obj: any): any {
if (Array.isArray(obj)) {
return obj.map(sortKeysDeep);
}
if (obj !== null && typeof obj === "object") {
return Object.keys(obj)
.sort()
.reduce((acc: any, key) => {
acc[key] = sortKeysDeep(obj[key]);
return acc;
}, {});
}
return obj;
}
/* =========================
SIGNATURE
========================= */
export interface SignatureResult {
timestamp: number;
nonce: string;
signature: string;
}
export function generateSignature(rawBody: any): SignatureResult {
const timestamp = Math.floor(Date.now() / 1000);
const nonce = uuidv4();
const body = sortKeysDeep(rawBody ?? {});
const payload = JSON.stringify({
timestamp,
nonce,
body: JSON.stringify(body), // ⚠️ STRINGIFY GANDA (WAJIB)
});
const hash = CryptoJS.HmacSHA256(payload, ENV.secretKey);
return {
timestamp,
nonce,
signature: CryptoJS.enc.Hex.stringify(hash),
};
}