UNPKG

storenest-commerce

Version:

Complete e-commerce SDK for Storenest platform with React components, multi-language support, secure checkout, and enterprise-grade security

170 lines (169 loc) 6.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDebugMode = exports.setDebugMode = exports.getSecretKey = exports.setSecretKey = exports.getProxyUrl = exports.setProxyUrl = exports.getApiKey = exports.setApiKey = exports.getApiBaseUrl = exports.setApiBaseUrl = void 0; exports.formatPrice = formatPrice; exports.getOrCreateUserId = getOrCreateUserId; exports.generateNonce = generateNonce; exports.generateApiToken = generateApiToken; // Secure configuration storage using closure const config = (() => { let apiBaseUrl = ''; let apiKey = null; let proxyUrl = null; let secretKey = null; let debugMode = false; return { setApiBaseUrl: (url) => { apiBaseUrl = url; }, getApiBaseUrl: () => apiBaseUrl, setApiKey: (key) => { apiKey = key; }, getApiKey: () => apiKey, setProxyUrl: (url) => { proxyUrl = url; }, getProxyUrl: () => proxyUrl, setSecretKey: (key) => { secretKey = key; }, getSecretKey: () => secretKey, setDebugMode: (debug) => { debugMode = debug; }, getDebugMode: () => debugMode, }; })(); function formatPrice(price, locale = 'hr-HR', currency = 'EUR') { return price.toLocaleString(locale, { style: 'currency', currency, }); } function getOrCreateUserId(storageKey = 'userId') { if (typeof window === 'undefined') return null; let userId = window.localStorage.getItem(storageKey); if (!userId) { userId = 'guest-' + generateSecureRandomString(9); window.localStorage.setItem(storageKey, userId); } return userId; } // Generate cryptographically secure random string function generateSecureRandomString(length) { // Try Node.js crypto first (for server-side) if (typeof require !== 'undefined') { try { const crypto = require('crypto'); const randomBytes = crypto.randomBytes(length); const result = Array.from(randomBytes, (byte) => byte.toString(36)).join('').substring(0, length); return result; } catch (error) { // Node.js crypto failed, continue to Web Crypto API } } // Try Web Crypto API (for browsers) try { if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { const array = new Uint8Array(length); window.crypto.getRandomValues(array); const result = Array.from(array, byte => byte.toString(36)).join('').substring(0, length); return result; } } catch (error) { // Web Crypto API failed, continue to fallback } // Final fallback - WARNING: Less secure if (config.getDebugMode()) { console.warn('⚠️ Storenest Commerce: Using fallback random generation. This is less secure than cryptographic random generation.'); } let result = ''; const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } // Generate a nonce for unpredictability using crypto-secure random function generateNonce() { const randomPart = generateSecureRandomString(16); const timestamp = Date.now().toString(36); const nonce = `${randomPart}${timestamp}`; return nonce; } // Generate a secure token for API requests using Web Crypto API async function generateApiToken(apiKey, requestBody) { const timestamp = Date.now().toString(); const nonce = generateNonce(); // Create signature using SHA-256 hash of apiKey:timestamp:nonce:bodyHash const bodyHash = requestBody ? await generateBodyHash(requestBody) : ''; const dataToSign = bodyHash ? `${apiKey}:${timestamp}:${nonce}:${bodyHash}` : `${apiKey}:${timestamp}:${nonce}`; const signature = await generateSecureSignature(dataToSign); return { timestamp, signature, nonce }; } // Generate SHA-256 hash of request body async function generateBodyHash(body) { const encoder = new TextEncoder(); const data = encoder.encode(body); const hashBuffer = await crypto.subtle.digest('SHA-256', data); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); } // Generate secure signature using Web Crypto API async function generateSecureSignature(data) { try { // Try Node.js crypto first (for server-side) if (typeof require !== 'undefined') { try { const crypto = require('crypto'); const hash = crypto.createHash('sha256'); hash.update(data); const result = hash.digest('hex'); return result; } catch (error) { // Node.js crypto failed, continue to Web Crypto API } } // Use Web Crypto API if available (modern browsers) if (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) { const encoder = new TextEncoder(); const dataBuffer = encoder.encode(data); const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer); const hashArray = Array.from(new Uint8Array(hashBuffer)); const result = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); return result; } // Fallback for older browsers or server-side (less secure but functional) if (config.getDebugMode()) { console.warn('⚠️ Storenest Commerce: Using fallback hash function. This is less secure than SHA-256.'); } const result = fallbackHash(data); return result; } catch (error) { // If Web Crypto API fails, use fallback if (config.getDebugMode()) { console.warn('⚠️ Storenest Commerce: Using fallback hash function due to crypto API failure.'); } const result = fallbackHash(data); return result; } } // Fallback hash function (less secure but functional) function fallbackHash(str) { let hash = 0; if (str.length === 0) return hash.toString(); for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash).toString(16); } // Export config functions exports.setApiBaseUrl = config.setApiBaseUrl; exports.getApiBaseUrl = config.getApiBaseUrl; exports.setApiKey = config.setApiKey; exports.getApiKey = config.getApiKey; exports.setProxyUrl = config.setProxyUrl; exports.getProxyUrl = config.getProxyUrl; exports.setSecretKey = config.setSecretKey; exports.getSecretKey = config.getSecretKey; exports.setDebugMode = config.setDebugMode; exports.getDebugMode = config.getDebugMode;