UNPKG

zips-react-native-sdk-test

Version:

Lightweight ZIPS Payment Gateway SDK for React Native - Complete payment solution with card payments, wallet payments (AfrMoney & ZApp), netbanking, and native UI design

193 lines (163 loc) 4.13 kB
/** * Default currency for the ZIPS payment system */ export const DEFAULT_CURRENCY = 'GMD'; /** * Get default currency */ export const getDefaultCurrency = (): string => { return DEFAULT_CURRENCY; }; /** * Format amount for display */ export const formatAmount = ( amount: number, currency: string = DEFAULT_CURRENCY ): string => { return `${currency} ${(amount / 100).toFixed(2)}`; }; /** * Format date for display */ export const formatDate = (dateString: string): string => { const date = new Date(dateString); return date.toLocaleDateString() + ' ' + date.toLocaleTimeString(); }; /** * Validate account number */ export const validateAccountNumber = (account: string): boolean => { const cleanAccount = account.replace(/\s/g, ''); return cleanAccount.length >= 10 && /^\d+$/.test(cleanAccount); }; /** * Validate card number using Luhn algorithm */ export const validateCardNumber = (cardNumber: string): boolean => { const num = cardNumber.replace(/\D/g, ''); if (num.length < 13 || num.length > 19) { return false; } let sum = 0; let shouldDouble = false; for (let i = num.length - 1; i >= 0; i--) { let digit = parseInt(num.charAt(i), 10); if (shouldDouble) { digit *= 2; if (digit > 9) { digit -= 9; } } sum += digit; shouldDouble = !shouldDouble; } return sum % 10 === 0; }; /** * Format card number with spaces */ export const formatCardNumber = (text: string): string => { const cleaned = text.replace(/\D/g, ''); const formatted = cleaned.replace(/(\d{4})(?=\d)/g, '$1 '); return formatted; }; /** * Format account number with spaces */ export const formatAccountNumber = (text: string): string => { const cleaned = text.replace(/\D/g, ''); const formatted = cleaned.replace(/(\d{4})(?=\d)/g, '$1 '); return formatted; }; /** * Validate phone number */ export const validatePhoneNumber = (phone: string): boolean => { const cleanPhone = phone.replace(/\D/g, ''); return cleanPhone.length >= 7 && cleanPhone.length <= 15; }; /** * Validate email address */ export const validateEmail = (email: string): boolean => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); }; /** * Generate UUID v4 */ export const generateUUID = (): string => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; const v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); }; /** * Delay function for retries */ export const delay = (ms: number): Promise<void> => { return new Promise((resolve) => setTimeout(resolve, ms)); }; /** * Retry function with exponential backoff */ export const retryWithBackoff = async <T>( fn: () => Promise<T>, maxRetries: number = 3, baseDelay: number = 1000 ): Promise<T> => { let lastError: Error; for (let i = 0; i < maxRetries; i++) { try { return await fn(); } catch (error) { lastError = error as Error; if (i === maxRetries - 1) { throw lastError; } const delayTime = baseDelay * Math.pow(2, i); await delay(delayTime); } } throw lastError!; }; /** * Check if error is network related */ export const isNetworkError = (error: any): boolean => { return ( error.code === 'NETWORK_ERROR' || error.message?.includes('Network Error') || error.message?.includes('Failed to fetch') ); }; /** * Sanitize input for security */ export const sanitizeInput = (input: string): string => { return input.trim().replace(/[<>\"']/g, ''); }; /** * Deep clone object */ export const deepClone = <T>(obj: T): T => { if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()) as T; } if (obj instanceof Array) { return obj.map((item) => deepClone(item)) as T; } if (typeof obj === 'object') { const cloned = {} as T; Object.keys(obj).forEach((key) => { (cloned as any)[key] = deepClone((obj as any)[key]); }); return cloned; } return obj; };