const jwt = require('jsonwebtoken'); // Generate secure token for transactions function generateToken(data, expiresIn = '1h') { try { const secret = process.env.JWT_SECRET || 'your-fallback-secret-key'; return jwt.sign(data, secret, { expiresIn }); } catch (error) { console.error('Token generation error:', error); return null; } } // Verify transaction token function verifyToken(token) { try { const secret = process.env.JWT_SECRET || 'your-fallback-secret-key'; return jwt.verify(token, secret); } catch (error) { console.error('Token verification error:', error); return null; } } // Format currency amount function formatCurrency(amount, currency = 'USD') { try { return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency, minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(parseFloat(amount)); } catch (error) { return `${currency} ${parseFloat(amount).toFixed(2)}`; } } // Validate email format function isValidEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } // Sanitize order data for logging function sanitizeOrderData(orderData) { const sanitized = { ...orderData }; // Remove sensitive data delete sanitized.billing?.email; delete sanitized.billing?.phone; delete sanitized.customer_id; return { id: sanitized.id, status: sanitized.status, total: sanitized.total, currency: sanitized.currency, payment_method: sanitized.payment_method, date_created: sanitized.date_created }; } // Generate reference ID function generateReferenceId(prefix = 'REF') { const timestamp = Date.now(); const random = Math.random().toString(36).substring(2, 8).toUpperCase(); return `${prefix}-${timestamp}-${random}`; } // Validate PayPal amount format function validateAmount(amount) { if (!amount) return false; const numAmount = parseFloat(amount); if (isNaN(numAmount)) return false; if (numAmount <= 0) return false; if (numAmount > 10000) return false; // Max amount check // Check decimal places (max 2) const decimalPlaces = (amount.toString().split('.')[1] || '').length; if (decimalPlaces > 2) return false; return true; } // Parse query parameters safely function parseQueryParams(req) { const { wc_order_id, total, currency, customer_email, return_url, cancel_url } = req.query; return { wc_order_id: wc_order_id ? parseInt(wc_order_id) : null, total: total ? parseFloat(total) : null, currency: currency || 'USD', customer_email: customer_email || null, return_url: return_url || `${process.env.FRONTEND_URL}/success`, cancel_url: cancel_url || `${process.env.FRONTEND_URL}/cancel` }; } // Log API request/response function logApiCall(type, endpoint, data, response) { console.log(`${type.toUpperCase()} API Call:`, { endpoint, timestamp: new Date().toISOString(), data: sanitizeLogData(data), response: sanitizeLogData(response), success: response?.success || false }); } // Sanitize data for logging (remove sensitive info) function sanitizeLogData(data) { if (!data || typeof data !== 'object') return data; const sanitized = { ...data }; const sensitiveFields = [ 'password', 'secret', 'token', 'key', 'auth', 'email', 'phone', 'address', 'credit_card' ]; sensitiveFields.forEach(field => { if (sanitized[field]) { sanitized[field] = '[REDACTED]'; } }); return sanitized; } // Error response helper function createErrorResponse(message, details = null, statusCode = 500) { const response = { success: false, error: message, timestamp: new Date().toISOString() }; if (details && process.env.NODE_ENV !== 'production') { response.details = details; } return { response, statusCode }; } // Success response helper function createSuccessResponse(data, message = null) { return { success: true, data: data, message: message, timestamp: new Date().toISOString() }; } // Retry mechanism for API calls async function retryOperation(operation, maxRetries = 3, delayMs = 1000) { let lastError; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error; console.warn(`Operation failed (attempt ${attempt}/${maxRetries}):`, error.message); if (attempt < maxRetries) { await new Promise(resolve => setTimeout(resolve, delayMs * attempt)); } } } throw lastError; } module.exports = { generateToken, verifyToken, formatCurrency, isValidEmail, sanitizeOrderData, generateReferenceId, validateAmount, parseQueryParams, logApiCall, sanitizeLogData, createErrorResponse, createSuccessResponse, retryOperation };