barsa 934a87330d Refactor Billing Controller to Improve Error Handling
- Replaced inline error throwing with NotFoundException in the BillingController to enhance error handling and provide clearer responses for missing WHMCS client mappings.
- Updated multiple methods to ensure consistent error management across the controller, improving maintainability and clarity in API responses.
2025-12-26 17:36:06 +09:00

80 lines
2.4 KiB
TypeScript

/**
* Encoding utilities for WHMCS helpers (domain-internal)
*
* Avoid hard Node `Buffer` dependency. Use it when available; otherwise fall back
* to pure JS UTF-8 + base64.
*/
const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function encodeUtf8Fallback(value: string): Uint8Array {
const bytes: number[] = [];
for (let i = 0; i < value.length; i++) {
let codePoint = value.charCodeAt(i);
// Handle surrogate pairs
if (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < value.length) {
const next = value.charCodeAt(i + 1);
if (next >= 0xdc00 && next <= 0xdfff) {
codePoint = ((codePoint - 0xd800) << 10) + (next - 0xdc00) + 0x10000;
i++;
}
}
if (codePoint <= 0x7f) {
bytes.push(codePoint);
} else if (codePoint <= 0x7ff) {
bytes.push(0xc0 | (codePoint >> 6));
bytes.push(0x80 | (codePoint & 0x3f));
} else if (codePoint <= 0xffff) {
bytes.push(0xe0 | (codePoint >> 12));
bytes.push(0x80 | ((codePoint >> 6) & 0x3f));
bytes.push(0x80 | (codePoint & 0x3f));
} else {
bytes.push(0xf0 | (codePoint >> 18));
bytes.push(0x80 | ((codePoint >> 12) & 0x3f));
bytes.push(0x80 | ((codePoint >> 6) & 0x3f));
bytes.push(0x80 | (codePoint & 0x3f));
}
}
return new Uint8Array(bytes);
}
function encodeUtf8(value: string): Uint8Array {
if (typeof TextEncoder !== "undefined") {
return new TextEncoder().encode(value);
}
return encodeUtf8Fallback(value);
}
export function byteLengthUtf8(value: string): number {
if (typeof Buffer !== "undefined") {
return Buffer.byteLength(value, "utf8");
}
return encodeUtf8(value).length;
}
function base64EncodeBytes(bytes: Uint8Array): string {
let out = "";
for (let i = 0; i < bytes.length; i += 3) {
const b1 = bytes[i] ?? 0;
const b2 = bytes[i + 1] ?? 0;
const b3 = bytes[i + 2] ?? 0;
const triplet = (b1 << 16) | (b2 << 8) | b3;
out += BASE64_ALPHABET[(triplet >> 18) & 0x3f];
out += BASE64_ALPHABET[(triplet >> 12) & 0x3f];
out += i + 1 < bytes.length ? BASE64_ALPHABET[(triplet >> 6) & 0x3f] : "=";
out += i + 2 < bytes.length ? BASE64_ALPHABET[triplet & 0x3f] : "=";
}
return out;
}
export function utf8ToBase64(value: string): string {
if (typeof Buffer !== "undefined") {
return Buffer.from(value, "utf8").toString("base64");
}
return base64EncodeBytes(encodeUtf8(value));
}