@dropp.cc/payment-sdk 1.0.28 โ†’ 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"dropp-payment-sdk.esm.js","sources":["../src/constants.js","../src/logger.js","../src/utils.js","../src/messageHandler.js","../src/modalManager.js","../src/DroppPaymentSDK.js","../src/index.js"],"sourcesContent":["/**\n * Constants for Dropp Payment SDK\n */\n\n// Message types from payment app to SDK\nexport const MESSAGE_TYPES = {\n READY: 'DROPP_SDK_READY',\n PAYMENT_SUCCESS: 'PAYMENT_SUCCESS',\n PAYMENT_FAILED: 'PAYMENT_FAILED',\n PAYMENT_CANCELLED: 'PAYMENT_CANCELLED',\n ACCOUNT_EVENT: 'ACCOUNT_EVENT',\n PAGE_EVENT: 'PAGE_EVENT',\n ACCOUNT_STATUS: 'ACCOUNT_STATUS',\n CLOSE_WEBVIEW: 'CLOSE_WEBVIEW',\n AUTO_CLOSE_WEBVIEW: 'AUTO_CLOSE_WEBVIEW',\n PAYMENT_PAGE_LOADED: 'PAYMENT_PAGE_LOADED',\n PAGE_LOADED: 'PAGE_LOADED'\n};\n\n// Message types from SDK to payment app\nexport const SDK_MESSAGE_TYPES = {\n INIT: 'DROPP_SDK_INIT',\n CLOSE: 'DROPP_SDK_CLOSE'\n};\n\n// Environment configurations\nexport const ENVIRONMENTS = {\n PRODUCTION: 'production',\n QA: 'qa',\n SANDBOX: 'sandbox'\n};\n\n// Payment app URLs by environment\nexport const PAYMENT_APP_URLS = {\n [ENVIRONMENTS.PRODUCTION]: 'https://wv.dropp.cc',\n [ENVIRONMENTS.QA]: 'https://wv.qa.dropp.cc', // Assuming local QA server\n [ENVIRONMENTS.SANDBOX]: 'https://wv.sandbox.dropp.cc'\n};\n\n// Allowed origins for message validation (by environment)\nexport const ALLOWED_ORIGINS = {\n [ENVIRONMENTS.PRODUCTION]: ['https://wv.dropp.cc'],\n [ENVIRONMENTS.QA]: ['https://wv.qa.dropp.cc'], // Match QA server origin\n [ENVIRONMENTS.SANDBOX]: ['https://wv.sandbox.dropp.cc']\n};\n\n// Timeouts\nexport const TIMEOUTS = {\n INIT: 30000, // 30 seconds for app to load and send READY\n PAYMENT: 600000, // 10 minutes max for payment completion\n CLOSE_DELAY: 10000 // 10 seconds delay before closing modal after success/failure\n};\n\n// Payment types\nexport const PAYMENT_TYPES = {\n STANDARD: 'standard',\n PREAUTH: 'preauth',\n RECURRING: 'recurring'\n};\n\n// Error codes\nexport const ERROR_CODES = {\n INIT_TIMEOUT: 'INIT_TIMEOUT',\n PAYMENT_TIMEOUT: 'PAYMENT_TIMEOUT',\n INVALID_CONFIG: 'INVALID_CONFIG',\n ALREADY_OPEN: 'ALREADY_OPEN',\n ORIGIN_MISMATCH: 'ORIGIN_MISMATCH',\n MESSAGE_VALIDATION_FAILED: 'MESSAGE_VALIDATION_FAILED',\n IFRAME_BLOCKED: 'IFRAME_BLOCKED',\n UNKNOWN_ERROR: 'UNKNOWN_ERROR'\n};\n\n// SDK version\nexport const SDK_VERSION = '1.0.2';\n\n// CSS z-index for modal\nexport const MODAL_Z_INDEX = 999999;\n","/**\n * Logger utility for Dropp Payment SDK\n * Logging is disabled by default and can be enabled explicitly.\n */\n\nclass Logger {\n constructor(environment, options = {}) {\n this.environment = environment;\n this.forceEnabled = !!options.enabled;\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Determine if logging should be enabled\n * @private\n */\n _shouldEnableLogging() {\n return this.forceEnabled;\n }\n\n /**\n * Update environment and recalculate logging state\n */\n setEnvironment(environment, options = {}) {\n this.environment = environment;\n if (typeof options.enabled === 'boolean') {\n this.forceEnabled = options.enabled;\n }\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Explicitly enable or disable logging.\n */\n setEnabled(enabled) {\n this.forceEnabled = !!enabled;\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Log info messages\n */\n log(...args) {\n if (this.enabled) {\n console.log(...args);\n }\n }\n\n /**\n * Log warning messages\n */\n warn(...args) {\n if (this.enabled) {\n console.warn(...args);\n }\n }\n\n /**\n * Log error messages\n */\n error(...args) {\n if (this.enabled) {\n console.error(...args);\n }\n }\n\n /**\n * Log debug messages\n */\n debug(...args) {\n if (this.enabled) {\n console.debug(...args);\n }\n }\n\n /**\n * Log info messages\n */\n info(...args) {\n if (this.enabled) {\n console.info(...args);\n }\n }\n}\n\n// Create singleton instance with default environment\nconst logger = new Logger('qa', { enabled: false });\n\nexport default logger;\n","/**\n * Utility functions for Dropp Payment SDK\n */\n\nimport logger from './logger.js';\nimport { PAYMENT_TYPES } from './constants.js';\n\nconst SUPPORTED_CURRENCIES = ['USD', 'HBAR', 'USDC'];\n\nconst RECURRING_FREQUENCY_VALUES = [\n 'NONE',\n 'HALF_HOURLY',\n 'HOURLY',\n 'DAILY',\n 'WEEKLY',\n 'MONTHLY',\n 'YEARLY'\n];\n\nconst PAYMENT_TYPE_VALUES = [\n PAYMENT_TYPES.STANDARD,\n PAYMENT_TYPES.PREAUTH,\n PAYMENT_TYPES.RECURRING\n];\n\nfunction isPositiveNumber(value) {\n const num = typeof value === 'number' ? value : parseFloat(value);\n return typeof num === 'number' && !Number.isNaN(num) && num > 0;\n}\n\nfunction isPositiveInteger(value) {\n const num = typeof value === 'number' ? value : parseInt(value, 10);\n return Number.isInteger(num) && num > 0;\n}\n\nfunction isIpV4(value) {\n return /^(\\d{1,3}\\.){3}\\d{1,3}$/.test(value);\n}\n\nfunction isPrivateOrLoopbackHost(hostname) {\n if (!hostname) {\n return false;\n }\n\n const normalized = hostname.trim().toLowerCase();\n if (\n normalized === 'localhost' ||\n normalized === '127.0.0.1' ||\n normalized === '::1' ||\n normalized.endsWith('.local')\n ) {\n return true;\n }\n\n if (!isIpV4(normalized)) {\n return false;\n }\n\n const octets = normalized.split('.').map(part => Number(part));\n if (octets.some(octet => Number.isNaN(octet) || octet < 0 || octet > 255)) {\n return false;\n }\n\n const [a, b] = octets;\n // RFC1918 private ranges + loopback + link-local\n if (a === 10 || a === 127) {\n return true;\n }\n if (a === 172 && b >= 16 && b <= 31) {\n return true;\n }\n if (a === 192 && b === 168) {\n return true;\n }\n if (a === 169 && b === 254) {\n return true;\n }\n\n return false;\n}\n\nfunction isValidCallbackUrl(url, options = {}) {\n const {\n isProduction = false,\n allowLocalCallbacksInNonProd = false\n } = options;\n\n if (typeof url !== 'string' || !url.trim()) {\n return false;\n }\n\n try {\n const parsed = new URL(url.trim());\n const isHttps = parsed.protocol === 'https:';\n const isHttp = parsed.protocol === 'http:';\n\n if (!isHttp && !isHttps) {\n return false;\n }\n\n const isPrivateOrLoopback = isPrivateOrLoopbackHost(parsed.hostname);\n if (isPrivateOrLoopback) {\n return !isProduction && allowLocalCallbacksInNonProd;\n }\n\n if (isProduction) {\n return isHttps;\n }\n\n // Non-production can allow HTTP for public hosts by default.\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidIsoDateTime(value) {\n if (typeof value !== 'string' || !value.trim()) {\n return false;\n }\n const date = new Date(value.trim());\n return !Number.isNaN(date.getTime());\n}\n\nfunction isValidJsonObject(value) {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n\n try {\n JSON.stringify(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId() {\n return `dropp-sdk-${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n}\n\n/**\n * Base64-encode a UTF-8 string.\n */\nexport function encodeBase64Utf8(value) {\n const input = typeof value === 'string' ? value : String(value ?? '');\n\n // Prefer browser-native TextEncoder path to support full Unicode safely.\n if (typeof TextEncoder !== 'undefined') {\n const bytes = new TextEncoder().encode(input);\n let binary = '';\n bytes.forEach(byte => {\n binary += String.fromCharCode(byte);\n });\n\n return btoa(binary);\n }\n\n // Fallback for very old runtimes.\n return btoa(unescape(encodeURIComponent(input)));\n}\n\n/**\n * Base64url-encode a UTF-8 string without padding.\n */\nexport function encodeBase64UrlUtf8(value) {\n return encodeBase64Utf8(value)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Build payment URL with base64 payload (matching Android SDK pattern)\n */\nexport async function buildPaymentUrl(baseUrl, route, params, sdkVersion, authOptions = {}) {\n try {\n const { serverAuthToken = '' } = authOptions;\n\n // Create JSON payload\n const payload = {};\n Object.keys(params).forEach(key => {\n const value = params[key];\n if (value !== null && value !== undefined) {\n payload[key] = value;\n }\n });\n \n logger.log('[buildPaymentUrl] Building payment URL payload');\n \n // Base64url encode payload (UTF-8 safe, no padding)\n const jsonString = JSON.stringify(payload);\n const base64Payload = encodeBase64UrlUtf8(jsonString);\n \n const timestamp = Date.now().toString();\n const queryParams = new URLSearchParams({\n pay: base64Payload,\n sdkTs: timestamp,\n sdkVersion,\n platform: 'web'\n });\n\n if (serverAuthToken) {\n queryParams.set('authToken', serverAuthToken);\n }\n\n const url = `${baseUrl}/#${route}?${queryParams.toString()}`;\n \n return url;\n } catch (error) {\n logger.error('Error building payment URL:', error);\n throw error;\n }\n}\n\n/**\n * Validate payment configuration for standard, preauth, and recurring payments\n */\nexport function validateConfig(config = {}, options = {}) {\n const errors = [];\n const paymentType = config.paymentType || PAYMENT_TYPES.STANDARD;\n const isProduction = (options.environment || '').toLowerCase() === 'production';\n const allowLocalCallbacksInNonProd = !!options.allowLocalCallbacksInNonProd;\n const normalizedCurrency =\n typeof config.currency === 'string' ? config.currency.trim().toUpperCase() : '';\n\n if (!PAYMENT_TYPE_VALUES.includes(paymentType)) {\n errors.push(\n `paymentType must be one of: ${PAYMENT_TYPE_VALUES.join(', ')}`\n );\n }\n\n if (config.amount === undefined || config.amount === null || config.amount === '') {\n errors.push('amount is required');\n } else if (!isPositiveNumber(config.amount)) {\n errors.push('amount must be a positive number');\n }\n\n if (!config.currency || typeof config.currency !== 'string' || !config.currency.trim()) {\n errors.push('currency is required');\n } else if (!SUPPORTED_CURRENCIES.includes(normalizedCurrency)) {\n errors.push(`currency must be one of: ${SUPPORTED_CURRENCIES.join(', ')}`);\n }\n\n if (!config.itemName || typeof config.itemName !== 'string' || !config.itemName.trim()) {\n errors.push('itemName is required');\n }\n\n if (paymentType === PAYMENT_TYPES.STANDARD) {\n if (config.displayItems !== undefined && !isValidJsonObject(config.displayItems)) {\n errors.push('displayItems must be a valid JSON object for standard payments');\n }\n\n if (config.metaData !== undefined && !isValidJsonObject(config.metaData)) {\n errors.push('metaData must be a valid JSON object for standard payments');\n }\n }\n\n if (paymentType === PAYMENT_TYPES.PREAUTH) {\n if (normalizedCurrency && normalizedCurrency !== 'USD') {\n errors.push('currency must be USD for preauth payments');\n }\n\n if (!config.callbackUrl || !String(config.callbackUrl).trim()) {\n errors.push('callbackUrl (signing URL) is required for preauth payments');\n } else if (!isValidCallbackUrl(config.callbackUrl, {\n isProduction,\n allowLocalCallbacksInNonProd\n })) {\n errors.push(\n isProduction\n ? 'callbackUrl must be HTTPS in production and cannot target loopback/private hosts'\n : 'callbackUrl must be a valid HTTP/HTTPS URL and cannot target loopback/private hosts unless explicitly enabled'\n );\n }\n\n if (\n config.authHoldTimeInSeconds === undefined ||\n config.authHoldTimeInSeconds === null ||\n config.authHoldTimeInSeconds === ''\n ) {\n errors.push('authHoldTimeInSeconds is required for preauth payments');\n } else if (!isPositiveInteger(config.authHoldTimeInSeconds)) {\n errors.push('authHoldTimeInSeconds must be a positive integer (seconds)');\n }\n }\n\n if (paymentType === PAYMENT_TYPES.RECURRING) {\n if (!config.callbackUrl || !String(config.callbackUrl).trim()) {\n errors.push('callbackUrl (signing URL) is required for recurring payments');\n } else if (!isValidCallbackUrl(config.callbackUrl, {\n isProduction,\n allowLocalCallbacksInNonProd\n })) {\n errors.push(\n isProduction\n ? 'callbackUrl must be HTTPS in production and cannot target loopback/private hosts'\n : 'callbackUrl must be a valid HTTP/HTTPS URL and cannot target loopback/private hosts unless explicitly enabled'\n );\n }\n\n const frequency = (config.frequency || config.recurringInterval || '')\n .toString()\n .trim()\n .toUpperCase();\n\n if (!frequency) {\n errors.push('frequency is required for recurring payments');\n } else if (!RECURRING_FREQUENCY_VALUES.includes(frequency)) {\n errors.push(\n `frequency must be one of: ${RECURRING_FREQUENCY_VALUES.join(', ')}`\n );\n }\n\n if (!config.recurringEndDate || !String(config.recurringEndDate).trim()) {\n errors.push('recurringEndDate (expiry) is required for recurring payments');\n } else if (!isValidIsoDateTime(config.recurringEndDate)) {\n errors.push('recurringEndDate must be a valid ISO date-time string');\n } else if (new Date(config.recurringEndDate.trim()) <= new Date()) {\n errors.push('recurringEndDate must be in the future');\n }\n }\n\n return {\n valid: errors.length === 0,\n errors\n };\n}\n\n/**\n * Create error object\n */\nexport function createError(code, message, details = {}) {\n return {\n code,\n message,\n details,\n timestamp: new Date().toISOString(),\n toString() {\n return this.message || 'Dropp SDK error';\n }\n };\n}\n\n/**\n * Deep clone object\n */\nexport function deepClone(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * Check if running in browser environment\n */\nexport function isBrowser() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Sanitize HTML to prevent XSS\n */\nexport function sanitizeHTML(str) {\n if (!str) return '';\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\n/**\n * Format amount for display\n */\nexport function formatAmount(amount, currency) {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD'\n }).format(amount);\n } catch (error) {\n return `${amount} ${currency}`;\n }\n}\n","/**\n * Secure Message Handler for SDK โ†” Payment App Communication\n * \n * Implements:\n * - Origin validation\n * - Message schema validation\n * - Session correlation\n * - Anti-spoofing protection\n */\n\nimport { MESSAGE_TYPES, SDK_MESSAGE_TYPES, ALLOWED_ORIGINS } from './constants.js';\nimport { generateSessionId } from './utils.js';\nimport logger from './logger.js';\n\nexport class MessageHandler {\n constructor(environment, onMessage, allowedOrigins = null) {\n this.environment = environment;\n this.onMessage = onMessage;\n this.sessionId = generateSessionId();\n logger.log('[MessageHandler] Session initialized');\n this.iframe = null;\n this.allowedOrigins =\n allowedOrigins?.length > 0\n ? allowedOrigins\n : ALLOWED_ORIGINS[environment] || [];\n this.messageListener = null;\n this.pendingMessages = new Map(); // Track correlation IDs for request/response\n }\n\n /**\n * Initialize message listener\n */\n init(iframe) {\n this.iframe = iframe;\n this.messageListener = this._handleMessage.bind(this);\n window.addEventListener('message', this.messageListener);\n }\n\n /**\n * Clean up message listener\n */\n destroy() {\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n this.iframe = null;\n this.pendingMessages.clear();\n }\n\n /**\n * Handle incoming postMessage events\n * @private\n */\n _handleMessage(event) {\n logger.log('[MessageHandler] Received postMessage event');\n\n // Ignore messages from self (parent window)\n if (event.source === window) {\n logger.log('[MessageHandler] Ignoring message from self');\n return;\n }\n\n // 1. Validate origin\n if (!this._validateOrigin(event.origin)) {\n logger.warn('[Dropp SDK] Rejected message from untrusted origin:', event.origin);\n return;\n }\n\n // 2. Validate event source\n if (!this.iframe || event.source !== this.iframe.contentWindow) {\n logger.warn('[Dropp SDK] Rejected message from unexpected source', {\n eventOrigin: event.origin\n });\n return;\n }\n\n // 3. Validate message structure\n const message = event.data;\n if (!this._validateMessageStructure(message)) {\n logger.warn('[Dropp SDK] Rejected message with invalid structure');\n return;\n }\n\n // 4. Validate session ID (if present)\n if (message.sessionId && message.sessionId !== this.sessionId) {\n logger.warn('[Dropp SDK] Rejected message with invalid session ID');\n return;\n }\n\n // 5. Process valid message\n logger.log('[MessageHandler] Message passed validation');\n this._processMessage(message);\n }\n\n /**\n * Validate message origin against allowed list\n * @private\n */\n _validateOrigin(origin) {\n // In development/testing, allow localhost\n if (origin.startsWith('http://localhost:') || origin.startsWith('http://127.0.0.1:')) {\n return true;\n }\n\n // Enforce exact scheme + host + port origin match.\n return this.allowedOrigins.includes(origin);\n }\n\n /**\n * Validate message structure and type\n * @private\n */\n _validateMessageStructure(message) {\n if (!message || typeof message !== 'object') {\n return false;\n }\n\n // Must have a type field\n if (!message.type || typeof message.type !== 'string') {\n return false;\n }\n\n // Must be a known message type from payment app\n const validTypes = Object.values(MESSAGE_TYPES);\n if (!validTypes.includes(message.type)) {\n return false;\n }\n\n // ACCOUNT_STATUS from hosted status page may not include timestamp.\n if (message.type !== MESSAGE_TYPES.ACCOUNT_STATUS && !message.timestamp) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Process validated message\n * @private\n */\n _processMessage(message) {\n logger.log('[Dropp SDK] Received message:', message.type);\n\n // Invoke callback\n if (this.onMessage) {\n this.onMessage(message);\n }\n }\n\n /**\n * Send message to payment app\n */\n sendToPaymentApp(type, data = {}) {\n if (!this.iframe || !this.iframe.contentWindow) {\n logger.error('[Dropp SDK] Cannot send message: iframe not ready');\n return false;\n }\n\n const message = {\n type,\n data,\n sessionId: this.sessionId,\n timestamp: new Date().toISOString(),\n sdkVersion: '1.0.0'\n };\n\n // Get target origin from allowed origins\n const targetOrigin = this.allowedOrigins[0] || '*';\n\n try {\n this.iframe.contentWindow.postMessage(message, targetOrigin);\n logger.log('[Dropp SDK] Sent message:', type);\n return true;\n } catch (error) {\n logger.error('[Dropp SDK] Error sending message:', error);\n return false;\n }\n }\n\n /**\n * Send init message to payment app\n */\n sendInit(config) {\n return this.sendToPaymentApp(SDK_MESSAGE_TYPES.INIT, {\n mode: 'sdk',\n config\n });\n }\n\n /**\n * Send close request to payment app\n */\n sendClose() {\n return this.sendToPaymentApp(SDK_MESSAGE_TYPES.CLOSE, {});\n }\n\n /**\n * Get session ID\n */\n getSessionId() {\n return this.sessionId;\n }\n}\n","/**\n * Modal Manager - Creates and manages the payment modal UI\n * \n * Responsibilities:\n * - Create modal overlay and container\n * - Manage modal lifecycle (open/close/destroy)\n * - Handle focus trapping\n * - Clean up DOM and event listeners\n * - Responsive design\n */\n\nimport { MODAL_Z_INDEX } from './constants.js';\nimport logger from './logger.js';\n\nexport class ModalManager {\n constructor(onClose) {\n this.onClose = onClose;\n this.overlay = null;\n this.container = null;\n this.iframe = null;\n this.closeButton = null;\n this.isOpen = false;\n this.escapeListener = null;\n }\n\n /**\n * Create and show modal\n */\n open() {\n if (this.isOpen) {\n logger.warn('[Dropp SDK] Modal is already open');\n return null;\n }\n\n this._createModal();\n this._attachEventListeners();\n this._show();\n\n this.isOpen = true;\n return this.iframe;\n }\n\n /**\n * Close and cleanup modal\n */\n close() {\n logger.log('[ModalManager] ๐Ÿšฆ close() called, isOpen:', this.isOpen);\n \n if (!this.isOpen) {\n logger.log('[ModalManager] โš ๏ธ Modal is not open, skipping close');\n return;\n }\n\n logger.log('[ModalManager] ๐Ÿšฆ Hiding modal...');\n this._hide();\n logger.log('[ModalManager] ๐Ÿšฆ Removing event listeners...');\n this._removeEventListeners();\n logger.log('[ModalManager] ๐Ÿšฆ Destroying modal...');\n this._destroyModal();\n\n this.isOpen = false;\n logger.log('[ModalManager] โœ… Modal close sequence initiated');\n }\n\n /**\n * Create modal DOM elements\n * @private\n */\n _createModal() {\n // Create overlay\n this.overlay = document.createElement('div');\n this.overlay.id = 'dropp-payment-overlay';\n this._applyOverlayStyles(this.overlay);\n\n // Create container\n this.container = document.createElement('div');\n this.container.id = 'dropp-payment-container';\n this._applyContainerStyles(this.container);\n\n // Close button removed - will be rendered by chrome app instead\n\n // Create iframe\n this.iframe = document.createElement('iframe');\n this.iframe.id = 'dropp-payment-iframe';\n this.iframe.setAttribute('allow', 'payment');\n this.iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');\n this.iframe.setAttribute('referrerpolicy', 'no-referrer');\n this.iframe.setAttribute('title', 'Dropp Payment');\n this._applyIframeStyles(this.iframe);\n\n // Assemble modal\n this.container.appendChild(this.iframe);\n this.overlay.appendChild(this.container);\n\n // Add to DOM\n document.body.appendChild(this.overlay);\n }\n\n /**\n * Apply styles to overlay\n * @private\n */\n _applyOverlayStyles(element) {\n Object.assign(element.style, {\n position: 'fixed',\n inset: '0',\n width: '100vw',\n height: '100vh',\n margin: '0',\n padding: '20px',\n boxSizing: 'border-box',\n backgroundColor: 'rgba(0, 0, 0, 0.6)',\n zIndex: MODAL_Z_INDEX.toString(),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n opacity: '0',\n transition: 'opacity 0.3s ease',\n backdropFilter: 'blur(4px)',\n overflow: 'auto'\n });\n }\n\n /**\n * Apply styles to container\n * @private\n */\n _applyContainerStyles(element) {\n const isMobile = window.innerWidth < 768;\n this._isMobile = isMobile;\n\n Object.assign(element.style, {\n position: 'relative',\n flex: '0 0 auto',\n alignSelf: 'center',\n margin: 'auto',\n width: '100%',\n maxWidth: isMobile ? '100%' : '400px',\n height: isMobile ? '100%' : 'auto',\n minHeight: isMobile ? '100%' : '800px',\n maxHeight: isMobile ? '100%' : 'min(1000px, calc(100vh - 40px))',\n backgroundColor: '#ffffff',\n borderRadius: isMobile ? '0' : '16px',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)',\n overflow: 'hidden',\n transform: 'scale(0.95)',\n transition: 'transform 0.3s ease, opacity 0.3s ease',\n display: 'flex',\n flexDirection: 'column'\n });\n }\n\n _getContainerTransform(scale) {\n return `scale(${scale})`;\n }\n\n /**\n * Apply styles to close button\n * @private\n */\n _applyCloseButtonStyles(element) {\n Object.assign(element.style, {\n position: 'absolute',\n top: '16px',\n right: '16px',\n zIndex: '10',\n width: '40px',\n height: '40px',\n border: 'none',\n borderRadius: '50%',\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\n color: '#333',\n fontSize: '28px',\n lineHeight: '1',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n transition: 'all 0.2s ease',\n fontFamily: 'Arial, sans-serif',\n padding: '0'\n });\n\n // Hover effect\n element.addEventListener('mouseenter', () => {\n Object.assign(element.style, {\n backgroundColor: '#f5f5f5',\n transform: 'scale(1.1)'\n });\n });\n\n element.addEventListener('mouseleave', () => {\n Object.assign(element.style, {\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\n transform: 'scale(1)'\n });\n });\n }\n\n /**\n * Apply styles to iframe\n * @private\n */\n _applyIframeStyles(element) {\n const isMobile = this._isMobile;\n Object.assign(element.style, {\n width: '100%',\n flex: '1 1 auto',\n minHeight: isMobile ? '100%' : 'min(520px, calc(90vh - 40px))',\n height: isMobile ? '100%' : 'min(520px, calc(90vh - 40px))',\n border: 'none',\n display: 'block'\n });\n }\n\n /**\n * Show modal with animation\n * @private\n */\n _show() {\n // Prevent body scroll\n document.body.style.overflow = 'hidden';\n\n // Trigger animation\n requestAnimationFrame(() => {\n if (this.overlay) {\n this.overlay.style.opacity = '1';\n }\n if (this.container) {\n this.container.style.transform = this._getContainerTransform(1);\n }\n });\n }\n\n /**\n * Hide modal with animation\n * @private\n */\n _hide() {\n logger.log('[ModalManager] ๐ŸŽญ _hide() called');\n if (this.overlay) {\n this.overlay.style.opacity = '0';\n logger.log('[ModalManager] ๐ŸŽญ Overlay opacity set to 0');\n }\n if (this.container) {\n this.container.style.transform = this._getContainerTransform(0.95);\n logger.log('[ModalManager] ๐ŸŽญ Container transform set to scale(0.95)');\n }\n\n // Restore body scroll\n document.body.style.overflow = '';\n logger.log('[ModalManager] ๐ŸŽญ Body scroll restored');\n }\n\n /**\n * Destroy modal DOM elements\n * @private\n */\n _destroyModal() {\n logger.log('[ModalManager] ๐Ÿ—‘๏ธ _destroyModal() called, waiting 300ms for animation');\n // Wait for animation to complete\n setTimeout(() => {\n logger.log('[ModalManager] ๐Ÿ—‘๏ธ Animation complete, removing from DOM');\n if (this.overlay && this.overlay.parentNode) {\n this.overlay.parentNode.removeChild(this.overlay);\n logger.log('[ModalManager] ๐Ÿ—‘๏ธ Overlay removed from DOM');\n }\n this.overlay = null;\n this.container = null;\n this.iframe = null;\n this.closeButton = null;\n logger.log('[ModalManager] โœ… Modal destroyed');\n }, 300);\n }\n\n /**\n * Attach event listeners\n * @private\n */\n _attachEventListeners() {\n // Close button removed - will be handled by chrome app\n // Close button click\n // if (this.closeButton) {\n // this.closeButton.addEventListener('click', this._handleCloseClick.bind(this));\n // }\n\n // Backdrop click disabled for payment security\n // Users must use close button or complete/cancel payment\n // if (this.overlay) {\n // this.overlay.addEventListener('click', this._handleOverlayClick.bind(this));\n // }\n\n // Escape key disabled for payment security\n // Users must use close button or complete/cancel payment\n // this.escapeListener = this._handleEscapeKey.bind(this);\n // document.addEventListener('keydown', this.escapeListener);\n }\n\n /**\n * Remove event listeners\n * @private\n */\n _removeEventListeners() {\n if (this.escapeListener) {\n document.removeEventListener('keydown', this.escapeListener);\n this.escapeListener = null;\n }\n }\n\n /**\n * Handle close button click\n * @private\n */\n _handleCloseClick(event) {\n event.stopPropagation();\n if (this.onClose) {\n this.onClose('user_closed');\n }\n }\n\n /**\n * Handle overlay click (backdrop)\n * @private\n */\n _handleOverlayClick(event) {\n // Only close if clicking directly on overlay (not container)\n if (event.target === this.overlay) {\n if (this.onClose) {\n this.onClose('user_closed');\n }\n }\n }\n\n /**\n * Handle escape key press\n * @private\n */\n _handleEscapeKey(event) {\n if (event.key === 'Escape' && this.isOpen) {\n if (this.onClose) {\n this.onClose('user_closed');\n }\n }\n }\n\n /**\n * Get iframe element\n */\n getIframe() {\n return this.iframe;\n }\n\n /**\n * Check if modal is open\n */\n getIsOpen() {\n return this.isOpen;\n }\n}\n","/**\n * Dropp Payment SDK - Main SDK Class\n * \n * Public API for integrating Dropp payments into web applications\n */\n\nimport { \n ENVIRONMENTS, \n PAYMENT_APP_URLS,\n ALLOWED_ORIGINS,\n MESSAGE_TYPES, \n ERROR_CODES, \n TIMEOUTS, \n PAYMENT_TYPES,\n SDK_VERSION\n} from './constants.js';\nimport { MessageHandler } from './messageHandler.js';\nimport { ModalManager } from './modalManager.js';\nimport { \n buildPaymentUrl, \n encodeBase64UrlUtf8,\n validateConfig, \n createError, \n isBrowser \n} from './utils.js';\nimport logger from './logger.js';\n\nconst SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS = [\n 'fundnow',\n 'linkbank',\n 'linkcard',\n 'redeemnow',\n 'fundcrypto',\n 'transferusdc',\n 'usdchistory',\n 'redeemcrypto',\n 'manageaccounts',\n 'transactions',\n 'merchantlist',\n 'favorites',\n 'offers',\n 'profile',\n 'pinchange',\n 'unlinkaccount',\n 'accountsettings',\n 'aboutus'\n];\n\nexport class DroppPaymentSDK {\n /**\n * Create SDK instance\n * @param {Object} config - SDK configuration\n * @param {string} config.merchantId - Merchant Hedera account ID (required, e.g., '0.0.123456')\n * @param {string} config.apiKey - API Key (required)\n * @param {string} config.environment - Environment: 'production', 'qa', or 'sandbox'\n * @param {Function} [config.getServerAuthToken] - Optional async callback that returns a server-issued auth token\n * @param {boolean} [config.requireServerAuthToken] - Require server auth token (defaults to true in production)\n * @param {boolean} [config.allowLocalCallbacksInNonProd] - Allow loopback/private callback URLs in non-production\n */\n constructor(config = {}) {\n if (!isBrowser()) {\n throw new Error('Dropp Payment SDK can only be used in a browser environment');\n }\n\n // Validate required credentials\n if (!config.merchantId || !config.apiKey) {\n throw new Error('merchantId and apiKey are required to initialize SDK');\n }\n\n // Store credentials\n this.merchantId = config.merchantId;\n this.apiKey = config.apiKey;\n\n this.environment = config.environment || ENVIRONMENTS.QA;\n this.baseUrl =\n config.paymentAppUrl ||\n config.baseUrl ||\n PAYMENT_APP_URLS[this.environment];\n\n // Initialization state\n this.isInitialized = false;\n this.initializationPromise = null;\n\n this.getServerAuthToken =\n typeof config.getServerAuthToken === 'function'\n ? config.getServerAuthToken\n : null;\n this.requireServerAuthToken =\n typeof config.requireServerAuthToken === 'boolean'\n ? config.requireServerAuthToken\n : this.environment === ENVIRONMENTS.PRODUCTION;\n this.allowLocalCallbacksInNonProd = !!config.allowLocalCallbacksInNonProd;\n\n if (config.allowedOrigins?.length) {\n this.allowedOrigins = config.allowedOrigins;\n } else {\n try {\n // Derive allowed origin from the effective payment URL to keep a\n // single source of truth for iframe loading and postMessage validation.\n this.allowedOrigins = [new URL(this.baseUrl).origin];\n } catch {\n this.allowedOrigins = ALLOWED_ORIGINS[this.environment] || [];\n }\n }\n\n // State\n this.isOpen = false;\n this.currentSession = null;\n this.currentFlowType = null;\n this.statusSession = null;\n this.hiddenIframe = null;\n this.statusTimeout = null;\n this.initTimeout = null;\n this.paymentTimeout = null;\n this.hostAppDomain = null;\n this.onAccountChanged = null;\n this.onPageFailed = null;\n\n // Managers\n this.messageHandler = null;\n this.modalManager = null;\n\n // Set logger environment\n logger.setEnvironment(this.environment, { enabled: !!config.debugLogging });\n logger.log(`[Dropp SDK] Initialized v${SDK_VERSION} - Environment: ${this.environment}`);\n }\n\n /**\n * Open payment modal\n * @param {Object} options - Payment options\n * @param {number} options.amount - Payment amount (required)\n * @param {string} options.currency - Currency code (required)\n * @param {string} options.itemName - Item/service name (required)\n * @param {string} options.description - Payment description\n * @param {string} options.invoiceId - Invoice ID\n * @param {string} options.paymentType - Payment type: 'standard', 'preauth', or 'recurring'\n * @param {string} options.thumbnail - Product image URL\n * @param {number} options.authHoldTimeInSeconds - For preauth: hold time in seconds\n * @param {string} options.callbackUrl - Server callback URL\n * @param {boolean} [options.acceptPaymentDelay=false] - Allow delayed payment acceptance for standard payments (sent only when true)\n * @param {string} [options.serverAuthToken] - Server-issued short-lived token bound to payment context\n * @param {Function} options.onSuccess - Callback for successful payment\n * @param {Function} options.onFailure - Callback for failed payment\n * @param {Function} options.onCancel - Callback for cancelled payment\n * @param {Function} options.onClose - Callback for modal close\n * @returns {Promise<PaymentResult>}\n */\n pay(options = {}) {\n return new Promise((resolve, reject) => {\n // Block while any SDK flow is in progress (including status checks).\n if (this.isOpen || this.currentFlowType) {\n const error = createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A payment session is already in progress',\n {\n currentSession: this.currentSession,\n currentFlowType: this.currentFlowType\n }\n );\n reject(error);\n return;\n }\n\n (async () => {\n try {\n await this.initialize();\n\n // Validate payment configuration\n const validation = validateConfig(options, {\n environment: this.environment,\n allowLocalCallbacksInNonProd: this.allowLocalCallbacksInNonProd\n });\n if (!validation.valid) {\n const error = createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Invalid payment configuration',\n { errors: validation.errors }\n );\n reject(error);\n return;\n }\n\n // Store callbacks from options\n this.onSuccess = options.onSuccess || null;\n this.onFailure = options.onFailure || null;\n this.onCancel = options.onCancel || null;\n this.onClose = options.onClose || null;\n\n // Store resolve/reject for later\n this.currentSession = {\n resolve,\n reject,\n options,\n startTime: Date.now()\n };\n\n await this._initializePayment(options);\n } catch (error) {\n const isInitValidationError =\n error && error.code === ERROR_CODES.INVALID_CONFIG;\n const sdkError = isInitValidationError\n ? error\n : createError(\n ERROR_CODES.UNKNOWN_ERROR,\n 'Failed to initialize payment',\n { originalError: error?.message || String(error) }\n );\n\n reject(sdkError);\n this._cleanup();\n }\n })();\n });\n }\n\n /**\n * Initialize and validate merchant credentials with Dropp backend.\n * @returns {Promise<{status: string, code: string, message: string}>}\n */\n async initialize() {\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n\n this.initializationPromise = (async () => {\n this.hostAppDomain = this._detectHostAppDomain();\n if (!this.hostAppDomain) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unable to detect host app domain for SDK validation'\n );\n }\n\n await this._validateInitializationCredentials();\n this.isInitialized = true;\n return {\n status: 'success',\n code: 'INITIALIZED',\n message: 'Dropp SDK initialized successfully'\n };\n })().catch(error => {\n this.isInitialized = false;\n this.initializationPromise = null;\n throw error;\n });\n\n return this.initializationPromise;\n }\n\n /**\n * Resolve validation endpoint from configured base URL.\n * @private\n */\n _getValidationUrl() {\n const validationUrls = {\n [ENVIRONMENTS.QA]: 'https://bc0qfqi8c9.execute-api.us-east-1.amazonaws.com/QA-test-app-sdk-gateway-stage/sdk/payer/webview/validateSdk',\n [ENVIRONMENTS.SANDBOX]: 'https://76xbxsi4kf.execute-api.us-east-1.amazonaws.com/sandbox/sdk/payer/webview/validateSdk',\n [ENVIRONMENTS.PRODUCTION]: 'https://api.dropp.cc/payer/webview/validateSdk'\n };\n\n return (\n validationUrls[this.environment] ||\n validationUrls[ENVIRONMENTS.QA]\n );\n }\n\n /**\n * Detect host app domain from runtime browser context.\n * @private\n */\n _detectHostAppDomain() {\n if (typeof window === 'undefined' || !window.location) {\n return undefined;\n }\n\n return window.location.hostname || undefined;\n }\n\n /**\n * Build auth token for hosted page routes.\n * @private\n */\n _getHostedPageAuthToken() {\n const key = typeof this.apiKey === 'string' ? this.apiKey.trim() : '';\n const merchantAccount =\n typeof this.merchantId === 'string' ? this.merchantId.trim() : '';\n if (!key) {\n return '';\n }\n\n try {\n const authPayload = JSON.stringify({\n apikey: key,\n merchantAccount\n });\n return encodeBase64UrlUtf8(authPayload);\n } catch {\n return '';\n }\n }\n\n /**\n * Build an actionable validation error message from backend response.\n * @private\n */\n _formatValidationFailureMessage(baseMessage, status, responseBody) {\n const parts = [baseMessage];\n\n if (Number.isFinite(status)) {\n parts.push(`httpStatus=${status}`);\n }\n\n const responseCodeRaw = responseBody?.responseCode;\n const responseCode = Number(responseCodeRaw);\n if (!Number.isNaN(responseCode)) {\n parts.push(`responseCode=${responseCode}`);\n }\n\n let reason = '';\n if (Array.isArray(responseBody?.errors) && responseBody.errors.length > 0) {\n const firstError = responseBody.errors[0];\n if (typeof firstError === 'string') {\n reason = firstError;\n } else if (firstError && typeof firstError.message === 'string') {\n reason = firstError.message;\n } else {\n reason = JSON.stringify(firstError);\n }\n } else if (typeof responseBody?.message === 'string' && responseBody.message.trim()) {\n reason = responseBody.message.trim();\n }\n\n if (reason) {\n parts.push(`reason=${reason}`);\n }\n\n return parts.join(' | ');\n }\n\n /**\n * Validate merchant credentials and app package before any payment flow.\n * @private\n */\n async _validateInitializationCredentials() {\n const validationUrl = this._getValidationUrl();\n const merchantDomain = this.hostAppDomain;\n\n if (!merchantDomain) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unable to resolve host app domain for SDK validation'\n );\n }\n\n const headers = {\n accept: 'application/json, text/plain, */*',\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n 'x-app-package': merchantDomain,\n 'dropp-user-agent': 'WEB'\n };\n\n headers['dropp-merchant-domain'] = merchantDomain;\n\n let response;\n let responseBody = null;\n try {\n response = await fetch(validationUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({ id: this.merchantId })\n });\n } catch (error) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unable to validate merchant credentials',\n {\n endpoint: validationUrl,\n originalError: error?.message || String(error)\n }\n );\n }\n\n try {\n responseBody = await response.json();\n } catch {\n responseBody = null;\n }\n\n if (!response.ok) {\n const message = this._formatValidationFailureMessage(\n 'Merchant validation failed for merchantId/apiKey/domain',\n response.status,\n responseBody\n );\n\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n message,\n {\n endpoint: validationUrl,\n status: response.status,\n response: responseBody\n }\n );\n }\n\n const responseCode = Number(responseBody?.responseCode);\n const errors = responseBody?.errors;\n const hasNoErrors = !Array.isArray(errors) || errors.length === 0;\n const isValidationSuccess = responseBody && responseCode === 0 && hasNoErrors;\n\n if (!isValidationSuccess) {\n const message = this._formatValidationFailureMessage(\n 'Merchant validation returned an unsuccessful response',\n response.status,\n responseBody\n );\n\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n message,\n {\n endpoint: validationUrl,\n status: response.status,\n response: responseBody\n }\n );\n }\n\n logger.log('[Dropp SDK] Merchant credentials validated successfully');\n }\n\n /**\n * Close payment modal programmatically\n */\n closePayment() {\n if (this.isOpen) {\n if (this.currentFlowType === 'page') {\n this._cleanup();\n return;\n }\n this._handleCancel('sdk_close');\n }\n }\n\n /**\n * Open the dashboard/home page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @param {string[]} [options.modules] - Optional sidebar module IDs for firsttimeflow route\n * @returns {Promise<{status: string, route: string}>}\n */\n dashboard(options = {}) {\n return this._openHostedPage('/firsttimeflow', options);\n }\n\n /**\n * Open a specific supported module page in the Dropp modal.\n * @param {string} moduleId - Supported firsttimeflow item module ID\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n open(moduleId, options = {}) {\n const normalizedModuleId = typeof moduleId === 'string' ? moduleId.trim() : '';\n\n if (!normalizedModuleId) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'moduleId is required for Dropp.open(moduleId)',\n { moduleId }\n );\n }\n\n if (!SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS.includes(normalizedModuleId)) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unsupported moduleId passed to Dropp.open(moduleId)',\n {\n moduleId: normalizedModuleId,\n supportedModuleIds: [...SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS]\n }\n );\n }\n\n const route = normalizedModuleId === 'about' ? '/aboutus' : `/${normalizedModuleId}`;\n return this._openHostedPage(route, options);\n }\n\n /**\n * Open the unlink account page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n unlinkAccount(options = {}) {\n return this._openHostedPage('/unlink', options);\n }\n\n /**\n * Open the transactions page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n transactions(options = {}) {\n return this._openHostedPage('/transactions', options);\n }\n\n /**\n * Open the offers page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n offers(options = {}) {\n return this._openHostedPage('/offers', options);\n }\n\n /**\n * Get account status using a hidden iframe flow.\n * @returns {Promise<{type: string, data: {linked: boolean, method: string}}>} \n */\n status() {\n return new Promise((resolve, reject) => {\n if (this.isOpen || this.currentFlowType) {\n reject(\n createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A Dropp session is already in progress',\n { currentSession: this.currentSession, currentFlowType: this.currentFlowType }\n )\n );\n return;\n }\n\n (async () => {\n try {\n // Lock immediately to prevent races while initialize() is in-flight.\n this.currentFlowType = 'status';\n\n await this.initialize();\n this.currentSession = null;\n this.onSuccess = null;\n this.onFailure = null;\n this.onCancel = null;\n this.onClose = null;\n\n this.messageHandler = new MessageHandler(\n this.environment,\n this._handleMessage.bind(this),\n this.allowedOrigins\n );\n\n const iframe = document.createElement('iframe');\n iframe.id = 'dropp-status-iframe';\n iframe.setAttribute('allow', 'payment');\n iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');\n iframe.setAttribute('referrerpolicy', 'no-referrer');\n iframe.setAttribute('title', 'Dropp Account Status');\n\n Object.assign(iframe.style, {\n position: 'absolute',\n width: '1px',\n height: '1px',\n border: '0',\n opacity: '0',\n pointerEvents: 'none',\n visibility: 'hidden'\n });\n\n document.body.appendChild(iframe);\n this.hiddenIframe = iframe;\n\n this.messageHandler.init(iframe);\n\n const queryParams = new URLSearchParams({\n sdkMode: 'true',\n sessionId: this.messageHandler.getSessionId(),\n sdkVersion: SDK_VERSION,\n platform: 'web',\n merchantDomain: this.hostAppDomain\n });\n\n const hostedAuthToken = this._getHostedPageAuthToken();\n if (hostedAuthToken) {\n queryParams.set('auth', hostedAuthToken);\n }\n\n const normalizedBaseUrl = this.baseUrl.replace(/\\/+$/, '');\n iframe.src = `${normalizedBaseUrl}/#/status?${queryParams.toString()}`;\n\n this.statusSession = {\n resolve,\n reject,\n startTime: Date.now()\n };\n\n this.statusTimeout = setTimeout(() => {\n const error = createError(\n ERROR_CODES.INIT_TIMEOUT,\n 'Account status request timed out',\n {\n type: 'status',\n sessionDuration: this.statusSession\n ? Date.now() - this.statusSession.startTime\n : 0\n }\n );\n\n if (this.statusSession) {\n this.statusSession.reject(error);\n }\n\n this._cleanup();\n }, TIMEOUTS.INIT);\n } catch (error) {\n reject(\n createError(\n ERROR_CODES.UNKNOWN_ERROR,\n 'Failed to get account status',\n { originalError: error?.message || String(error) }\n )\n );\n this._cleanup();\n }\n })();\n });\n }\n\n /**\n * Initialize payment session\n * @private\n */\n async _initializePayment(options) {\n logger.log('[Dropp SDK] Initializing payment session');\n this.currentFlowType = 'payment';\n\n // Create message handler\n this.messageHandler = new MessageHandler(\n this.environment,\n this._handleMessage.bind(this),\n this.allowedOrigins\n );\n\n // Create modal manager\n this.modalManager = new ModalManager(\n this._handleModalClose.bind(this)\n );\n\n // Open modal and get iframe\n const iframe = this.modalManager.open();\n if (!iframe) {\n throw new Error('Failed to create modal iframe');\n }\n\n // Initialize message handler with iframe\n this.messageHandler.init(iframe);\n\n // Determine payment route based on type\n const paymentType = options.paymentType || PAYMENT_TYPES.STANDARD;\n let route = '/payViaUrl';\n if (paymentType === PAYMENT_TYPES.PREAUTH) {\n route = '/preAuthPayment';\n } else if (paymentType === PAYMENT_TYPES.RECURRING) {\n route = '/recurringPayment';\n }\n\n // Build payment parameters (matching Android SDK)\n // For recurring payments with frequency NONE, use maxAmount instead of fixAmount\n const recurringFrequency = paymentType === PAYMENT_TYPES.RECURRING \n ? (options.frequency || options.recurringInterval || '').toString().trim().toUpperCase()\n : '';\n const isRecurringNone = paymentType === PAYMENT_TYPES.RECURRING && recurringFrequency === 'NONE';\n const detectedAppUrl =\n options.appUrl ||\n (typeof window !== 'undefined' && window.location ? window.location.href : undefined);\n \n const params = {\n merchantAccount: this.merchantId,\n amount: paymentType === PAYMENT_TYPES.PREAUTH ? undefined : options.amount,\n maxAmount: (paymentType === PAYMENT_TYPES.PREAUTH || isRecurringNone) ? options.amount : undefined,\n fixAmount: (paymentType === PAYMENT_TYPES.RECURRING && !isRecurringNone) ? options.amount : undefined,\n acceptPaymentDelay:\n paymentType === PAYMENT_TYPES.STANDARD && options.acceptPaymentDelay === true\n ? true\n : undefined,\n currency: options.currency,\n itemName: options.itemName,\n description: options.description,\n invoiceId: options.invoiceId || `INV-${Date.now()}`,\n invoiceType: paymentType === PAYMENT_TYPES.PREAUTH ? 'PREAUTH' : undefined,\n apiKey: this.apiKey,\n packageName: this.hostAppDomain,\n merchantDomain: this.hostAppDomain,\n sdkVersion: SDK_VERSION,\n platform: 'web',\n appUrl: detectedAppUrl,\n sessionId: this.messageHandler.getSessionId() // Include SDK session ID for message validation\n };\n\n if (paymentType === PAYMENT_TYPES.STANDARD) {\n const resolvedDisplayItem =\n options.displayItem !== undefined ? options.displayItem : options.displayItems;\n const resolvedMetaData =\n options.metaData !== undefined ? options.metaData : options.metadata;\n\n if (resolvedDisplayItem !== undefined) {\n // Send both spellings for backward compatibility across page parsers.\n params.displayItem = resolvedDisplayItem;\n params.displayItems = resolvedDisplayItem;\n }\n\n if (resolvedMetaData !== undefined) {\n // Send both spellings for backward compatibility across page parsers.\n params.metaData = resolvedMetaData;\n params.metadata = resolvedMetaData;\n }\n }\n \n logger.log('[Dropp SDK] Including SDK session context in payment params');\n\n // Add optional parameters\n if (options.successURL) params.successURL = options.successURL;\n if (options.failureURL) params.failureURL = options.failureURL;\n \n // Recurring payment specific fields\n if (paymentType === PAYMENT_TYPES.RECURRING) {\n const frequency = options.frequency || options.recurringInterval;\n if (frequency) params.frequency = frequency;\n if (options.recurringEndDate) params.expiry = options.recurringEndDate;\n }\n \n // Pre-auth specific fields\n if (paymentType === PAYMENT_TYPES.PREAUTH && options.authHoldTimeInSeconds) {\n params.authHoldTimeInSeconds = options.authHoldTimeInSeconds;\n }\n \n // Callback URL for server-side submission\n if (options.callbackUrl) {\n params.url = options.callbackUrl;\n params.submitToCallBack = 'post';\n }\n\n const authContext = {\n sessionId: params.sessionId,\n merchantAccount: this.merchantId,\n amount: options.amount,\n paymentType,\n invoiceId: params.invoiceId,\n expiry: options.recurringEndDate || null,\n issuedAt: Date.now()\n };\n\n let serverAuthToken =\n typeof options.serverAuthToken === 'string'\n ? options.serverAuthToken.trim()\n : '';\n\n if (!serverAuthToken && this.getServerAuthToken) {\n try {\n const tokenFromCallback = await this.getServerAuthToken(authContext);\n serverAuthToken = typeof tokenFromCallback === 'string'\n ? tokenFromCallback.trim()\n : '';\n } catch (error) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Failed to obtain server auth token',\n {\n originalError: error?.message || String(error)\n }\n );\n }\n }\n\n if (this.requireServerAuthToken && !serverAuthToken) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'serverAuthToken is required. Provide options.serverAuthToken or config.getServerAuthToken.',\n {\n environment: this.environment,\n paymentType,\n invoiceId: params.invoiceId\n }\n );\n }\n\n // Build payment URL with base64 payload and optional server-issued auth token.\n const paymentUrl = await buildPaymentUrl(\n this.baseUrl,\n route,\n params,\n SDK_VERSION,\n { serverAuthToken }\n );\n\n logger.log('[Dropp SDK] Loading payment flow iframe');\n\n // Load payment app in iframe\n iframe.src = paymentUrl;\n\n this.isOpen = true;\n\n // Set initialization timeout\n this.initTimeout = setTimeout(() => {\n this._handleTimeout('init');\n }, TIMEOUTS.INIT);\n\n // Set payment timeout\n this.paymentTimeout = setTimeout(() => {\n this._handleTimeout('payment');\n }, TIMEOUTS.PAYMENT);\n }\n\n /**\n * Open a hosted Dropp page in the modal.\n * @private\n */\n async _openHostedPage(route, options = {}) {\n if (this.currentFlowType === 'status') {\n throw createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A Dropp session is already in progress',\n { currentSession: this.currentSession, currentFlowType: this.currentFlowType, route }\n );\n }\n\n if (this.isOpen) {\n if (this.currentFlowType === 'page') {\n this._cleanup();\n } else {\n throw createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A Dropp session is already in progress',\n { currentSession: this.currentSession, route }\n );\n }\n }\n\n await this.initialize();\n\n this.currentFlowType = 'page';\n this.currentSession = null;\n this.onSuccess = null;\n this.onFailure = typeof options.onFailed === 'function' ? options.onFailed : null;\n this.onCancel = typeof options.onCancel === 'function' ? options.onCancel : null;\n this.onClose = typeof options.onClose === 'function' ? options.onClose : null;\n this.onAccountChanged =\n typeof options.onAccountChanged === 'function' ? options.onAccountChanged : null;\n this.onPageFailed =\n typeof options.onPageFailed === 'function' ? options.onPageFailed : this.onFailure;\n\n this.messageHandler = new MessageHandler(\n this.environment,\n this._handleMessage.bind(this),\n this.allowedOrigins\n );\n\n this.modalManager = new ModalManager(\n this._handleModalClose.bind(this)\n );\n\n const iframe = this.modalManager.open();\n if (!iframe) {\n throw new Error('Failed to create modal iframe');\n }\n\n this.messageHandler.init(iframe);\n\n const queryParams = new URLSearchParams({\n sdkMode: 'true',\n sessionId: this.messageHandler.getSessionId(),\n sdkVersion: SDK_VERSION,\n platform: 'web',\n merchantDomain: this.hostAppDomain\n });\n\n const hostedAuthToken = this._getHostedPageAuthToken();\n if (hostedAuthToken) {\n queryParams.set('auth', hostedAuthToken);\n }\n\n // firsttimeflow-only sidebar filtering config.\n if (route === '/firsttimeflow' && Array.isArray(options.modules)) {\n const modules = options.modules\n .map(module => (typeof module === 'string' ? module.trim() : ''))\n .filter(Boolean);\n\n if (modules.length > 0) {\n queryParams.set('modules', modules.join(','));\n }\n }\n\n const normalizedBaseUrl = this.baseUrl.replace(/\\/+$/, '');\n iframe.src = `${normalizedBaseUrl}/#${route}?${queryParams.toString()}`;\n this.isOpen = true;\n\n logger.log('[Dropp SDK] Hosted page opened', { route });\n\n return {\n status: 'opened',\n route\n };\n }\n\n /**\n * Handle messages from payment app\n * @private\n */\n _handleMessage(message) {\n const { type, data } = message;\n\n switch (type) {\n case MESSAGE_TYPES.READY:\n this._handleReady(data);\n break;\n\n case MESSAGE_TYPES.PAGE_LOADED:\n this._handlePageLoaded(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_PAGE_LOADED:\n this._handlePageLoaded(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_SUCCESS:\n this._handleSuccess(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_FAILED:\n this._handleFailure(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_CANCELLED:\n this._handleCancel('user_cancelled');\n break;\n\n case MESSAGE_TYPES.ACCOUNT_STATUS:\n this._handleAccountStatus(data);\n break;\n\n case MESSAGE_TYPES.ACCOUNT_EVENT:\n this._handleAccountEvent(data);\n break;\n\n case MESSAGE_TYPES.PAGE_EVENT:\n this._handlePageEvent(data);\n break;\n\n case MESSAGE_TYPES.AUTO_CLOSE_WEBVIEW:\n // Auto-close from payment app after success/failure countdown\n // Just close the modal without triggering callbacks (already called)\n logger.log('[Dropp SDK] AUTO_CLOSE_WEBVIEW received - closing modal');\n this._cleanup();\n logger.log('[Dropp SDK] Cleanup completed');\n break;\n\n case MESSAGE_TYPES.CLOSE_WEBVIEW:\n // Manual close request from chrome app\n logger.log('[Dropp SDK] CLOSE_WEBVIEW received from app - closing modal');\n if (this.currentFlowType === 'status' && this.statusSession) {\n const error = createError(\n ERROR_CODES.UNKNOWN_ERROR,\n 'Account status request was closed before response was received',\n {\n type: 'status',\n sessionDuration: Date.now() - this.statusSession.startTime\n }\n );\n this.statusSession.reject(error);\n this._cleanup();\n break;\n }\n this._handleCancel('app_close');\n break;\n\n default:\n logger.warn('[Dropp SDK] Unknown message type:', type);\n }\n }\n\n /**\n * Handle ready message from payment app\n * @private\n */\n _handleReady(data) {\n logger.log('[Dropp SDK] Payment app ready');\n \n // Clear init timeout\n if (this.initTimeout) {\n clearTimeout(this.initTimeout);\n this.initTimeout = null;\n }\n\n // Send init message to payment app\n // Filter out non-serializable data (functions) from options\n if (this.messageHandler && this.currentSession) {\n const serializableOptions = {};\n Object.keys(this.currentSession.options).forEach(key => {\n const value = this.currentSession.options[key];\n // Only include serializable values (exclude functions)\n if (typeof value !== 'function') {\n serializableOptions[key] = value;\n }\n });\n \n logger.log('[Dropp SDK] Sending init config to payment app');\n this.messageHandler.sendInit(serializableOptions);\n }\n }\n\n /**\n * Handle page loaded message\n * @private\n */\n _handlePageLoaded(data) {\n logger.log('[Dropp SDK] Payment page loaded');\n }\n\n /**\n * Resolve account/page delegate action from bridge payload.\n * @private\n */\n _getBridgeAction(data = {}) {\n if (!data || typeof data !== 'object') {\n return '';\n }\n\n if (typeof data.action === 'string') {\n return data.action;\n }\n\n if (data.result && typeof data.result === 'object' && typeof data.result.action === 'string') {\n return data.result.action;\n }\n\n return '';\n }\n\n /**\n * Resolve failure message safely.\n * @private\n */\n _getSafeFailureMessage(data = {}, fallback = 'Request failed') {\n if (data && typeof data.message === 'string' && data.message.trim()) {\n return data.message.trim();\n }\n\n if (\n data &&\n data.result &&\n typeof data.result === 'object' &&\n typeof data.result.message === 'string' &&\n data.result.message.trim()\n ) {\n return data.result.message.trim();\n }\n\n return fallback;\n }\n\n /**\n * Resolve result object safely.\n * @private\n */\n _getSafeResult(data = {}) {\n if (data && data.result && typeof data.result === 'object') {\n return data.result;\n }\n\n return {};\n }\n\n /**\n * Handle unified account delegate events.\n * @private\n */\n _handleAccountEvent(data) {\n const action = this._getBridgeAction(data);\n const result = this._getSafeResult(data);\n\n if (action === 'onAccountChanged') {\n if (this.onAccountChanged) {\n this.onAccountChanged({\n linked: result.linked === true,\n rawData: result.rawData\n });\n }\n return;\n }\n\n if (action === 'onCancel') {\n if (this.onCancel) {\n this.onCancel();\n }\n return;\n }\n\n if (action === 'onFailed') {\n const message = this._getSafeFailureMessage(data, 'Account request failed');\n if (this.onFailure) {\n this.onFailure(message);\n }\n return;\n }\n\n logger.warn('[Dropp SDK] Unknown ACCOUNT_EVENT action:', action);\n }\n\n /**\n * Handle page delegate events.\n * @private\n */\n _handlePageEvent(data) {\n const action = this._getBridgeAction(data);\n\n if (action === 'onFailed') {\n const message = this._getSafeFailureMessage(data, 'Page request failed');\n if (this.onPageFailed) {\n this.onPageFailed(message);\n }\n return;\n }\n\n logger.warn('[Dropp SDK] Unknown PAGE_EVENT action:', action);\n }\n\n /**\n * Handle account status response\n * @private\n */\n _handleAccountStatus(data) {\n logger.log('[Dropp SDK] Account status received');\n\n if (!this.statusSession) {\n logger.warn('[Dropp SDK] ACCOUNT_STATUS received without active status session');\n return;\n }\n\n this.statusSession.resolve({\n type: MESSAGE_TYPES.ACCOUNT_STATUS,\n data\n });\n\n this._cleanup();\n }\n\n /**\n * Handle successful payment\n * @private\n */\n _handleSuccess(data) {\n logger.log('[Dropp SDK] Payment successful');\n\n const result = {\n status: 'success',\n ...data,\n sessionDuration: Date.now() - this.currentSession.startTime\n };\n\n // Resolve promise\n if (this.currentSession) {\n this.currentSession.resolve(result);\n }\n\n // Invoke callback\n if (this.onSuccess) {\n this.onSuccess(result);\n }\n\n // Note: Modal will be closed by AUTO_CLOSE_WEBVIEW message from payment app\n // after the countdown completes (no need for timeout here)\n }\n\n /**\n * Handle failed payment\n * @private\n */\n _handleFailure(data) {\n logger.log('[Dropp SDK] Payment failed');\n\n const result = {\n status: 'failed',\n ...data,\n sessionDuration: Date.now() - this.currentSession.startTime\n };\n\n // Resolve promise (not reject - failed payment is still a valid result)\n if (this.currentSession) {\n this.currentSession.resolve(result);\n }\n\n // Invoke callback\n if (this.onFailure) {\n this.onFailure(result);\n }\n\n // Note: Modal will be closed by AUTO_CLOSE_WEBVIEW message from payment app\n // after the countdown completes (no need for timeout here)\n }\n\n /**\n * Handle cancelled payment\n * @private\n */\n _handleCancel(reason) {\n logger.log('[Dropp SDK] Payment cancelled');\n\n if (this.currentFlowType === 'page') {\n if (this.onCancel) {\n this.onCancel();\n }\n this._cleanup();\n return;\n }\n\n const result = {\n status: 'cancelled',\n reason,\n sessionDuration: this.currentSession ? Date.now() - this.currentSession.startTime : 0\n };\n\n // Resolve promise (not reject - cancellation is a valid result)\n if (this.currentSession) {\n this.currentSession.resolve(result);\n }\n\n // Invoke callback\n if (this.onCancel) {\n this.onCancel(result);\n }\n\n // Close immediately\n this._cleanup();\n }\n\n /**\n * Handle modal close by user\n * @private\n */\n _handleModalClose(reason) {\n logger.log('[Dropp SDK] Modal closed by user');\n if (this.currentFlowType === 'page') {\n this._cleanup();\n return;\n }\n this._handleCancel(reason);\n }\n\n /**\n * Handle timeout\n * @private\n */\n _handleTimeout(type) {\n logger.error('[Dropp SDK] Timeout:', type);\n\n const errorCode = type === 'init' ? ERROR_CODES.INIT_TIMEOUT : ERROR_CODES.PAYMENT_TIMEOUT;\n const errorMessage = type === 'init' \n ? 'Payment app failed to load within timeout period'\n : 'Payment session timed out';\n\n const error = createError(errorCode, errorMessage, {\n type,\n sessionDuration: this.currentSession ? Date.now() - this.currentSession.startTime : 0\n });\n\n // Reject promise\n if (this.currentSession) {\n this.currentSession.reject(error);\n }\n\n // Invoke failure callback\n if (this.onFailure) {\n this.onFailure({ status: 'failed', error });\n }\n\n this._cleanup();\n }\n\n /**\n * Cleanup resources\n * @private\n */\n _cleanup() {\n logger.log('[Dropp SDK] ๐Ÿงน Cleaning up session - starting cleanup');\n\n // Clear timeouts\n if (this.initTimeout) {\n clearTimeout(this.initTimeout);\n this.initTimeout = null;\n }\n\n if (this.paymentTimeout) {\n clearTimeout(this.paymentTimeout);\n this.paymentTimeout = null;\n }\n\n if (this.statusTimeout) {\n clearTimeout(this.statusTimeout);\n this.statusTimeout = null;\n }\n\n // Destroy managers\n if (this.messageHandler) {\n logger.log('[Dropp SDK] ๐Ÿงน Destroying message handler');\n this.messageHandler.destroy();\n this.messageHandler = null;\n }\n\n if (this.modalManager) {\n logger.log('[Dropp SDK] ๐Ÿงน Closing modal manager');\n this.modalManager.close();\n logger.log('[Dropp SDK] ๐Ÿงน Modal manager closed');\n this.modalManager = null;\n }\n\n if (this.hiddenIframe && this.hiddenIframe.parentNode) {\n this.hiddenIframe.parentNode.removeChild(this.hiddenIframe);\n }\n this.hiddenIframe = null;\n\n // Clear state\n this.currentSession = null;\n this.statusSession = null;\n this.currentFlowType = null;\n this.isOpen = false;\n\n // Invoke onClose callback\n if (this.onClose) {\n this.onClose();\n }\n }\n\n /**\n * Get SDK version\n */\n static getVersion() {\n return SDK_VERSION;\n }\n\n /**\n * Get available environments\n */\n static getEnvironments() {\n return { ...ENVIRONMENTS };\n }\n\n /**\n * Get payment types\n */\n static getPaymentTypes() {\n return { ...PAYMENT_TYPES };\n }\n}\n\nexport default DroppPaymentSDK;\n","/**\n * Dropp Payment SDK for Web\n * \n * Main entry point - exports SDK class and factory functions\n */\n\nimport { DroppPaymentSDK } from './DroppPaymentSDK.js';\nimport { ENVIRONMENTS, PAYMENT_TYPES } from './constants.js';\n\nconst DROPP_CONTEXT_MENU_GUARD_KEY = '__droppDisableContextMenuListener__';\n\nfunction disableContextMenuOnImport() {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (window[DROPP_CONTEXT_MENU_GUARD_KEY]) {\n return;\n }\n\n const contextMenuHandler = event => {\n event.preventDefault();\n event.stopPropagation();\n };\n\n document.addEventListener('contextmenu', contextMenuHandler, true);\n window[DROPP_CONTEXT_MENU_GUARD_KEY] = true;\n}\n\ndisableContextMenuOnImport();\n\n// Export main SDK class\nexport { DroppPaymentSDK };\n\n// Export constants\nexport { ENVIRONMENTS, PAYMENT_TYPES };\n\n// Global Dropp instance\nlet globalDroppInstance = null;\n\n/**\n * Factory function to create and initialize SDK instance\n * @param {Object} config - SDK configuration\n * @param {string} config.merchantId - Merchant Hedera account ID (required, e.g., '0.0.123456')\n * @param {string} config.apiKey - API Key (required)\n * @param {string} config.packageName - Package name (required)\n * @param {string} config.environment - Environment: 'production', 'qa', or 'sandbox'\n * @returns {Promise<{status: string, code: string, message: string, sdk: DroppPaymentSDK}>}\n */\nexport async function createPaymentSDK(config) {\n globalDroppInstance = new DroppPaymentSDK(config);\n const initResult = await globalDroppInstance.initialize();\n return {\n ...initResult,\n sdk: globalDroppInstance\n };\n}\n\n/**\n * Get the global Dropp instance\n * @returns {DroppPaymentSDK|null}\n */\nexport function getDroppInstance() {\n return globalDroppInstance;\n}\n\n/**\n * Global Dropp object with pay method\n */\nexport const Dropp = {\n /**\n * Initialize SDK (sets global instance)\n * @param {Object} config - SDK configuration\n * @returns {Promise<{status: string, code: string, message: string, sdk: DroppPaymentSDK}>}\n */\n init(config) {\n return createPaymentSDK(config);\n },\n \n /**\n * Make a payment using the initialized SDK\n * @param {Object} options - Payment options\n * @returns {Promise<PaymentResult>}\n */\n pay(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.pay(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.pay(options);\n },\n\n /**\n * Open the dashboard/home page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @param {string[]} [options.modules] - Optional sidebar module IDs to show in firsttimeflow\n * @returns {Promise<{status: string, route: string}>}\n */\n dashboard(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.dashboard(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.dashboard(options);\n },\n\n /**\n * Open a supported firsttimeflow module page in the initialized SDK modal\n * @param {string} moduleId - Supported firsttimeflow item module ID\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n open(moduleId, options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.open(moduleId, options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.open(moduleId, options);\n },\n\n /**\n * Open the unlink account page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n unlinkAccount(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.unlinkAccount(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.unlinkAccount(options);\n },\n\n /**\n * Open the transactions page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n transactions(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.transactions(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.transactions(options);\n },\n\n /**\n * Open the offers page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n offers(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.offers(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.offers(options);\n },\n\n /**\n * Fetch account status via hidden iframe\n * @returns {Promise<{type: string, data: {linked: boolean, method: string}}>} \n */\n status() {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.status().');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.status();\n },\n \n /**\n * Get the current SDK instance\n * @returns {DroppPaymentSDK|null}\n */\n getInstance() {\n return globalDroppInstance;\n }\n};\n\n// Default export\nexport default {\n DroppPaymentSDK,\n createPaymentSDK,\n Dropp,\n ENVIRONMENTS,\n PAYMENT_TYPES\n};\n"],"names":["MESSAGE_TYPES","READY","PAYMENT_SUCCESS","PAYMENT_FAILED","PAYMENT_CANCELLED","ACCOUNT_EVENT","PAGE_EVENT","ACCOUNT_STATUS","CLOSE_WEBVIEW","AUTO_CLOSE_WEBVIEW","PAYMENT_PAGE_LOADED","PAGE_LOADED","SDK_MESSAGE_TYPES","ENVIRONMENTS","PRODUCTION","QA","SANDBOX","PAYMENT_APP_URLS","ALLOWED_ORIGINS","TIMEOUTS","PAYMENT_TYPES","STANDARD","PREAUTH","RECURRING","ERROR_CODES","SDK_VERSION","logger","constructor","environment","options","this","forceEnabled","enabled","_shouldEnableLogging","setEnvironment","setEnabled","log","args","console","warn","error","debug","info","SUPPORTED_CURRENCIES","RECURRING_FREQUENCY_VALUES","PAYMENT_TYPE_VALUES","isValidCallbackUrl","url","isProduction","allowLocalCallbacksInNonProd","trim","parsed","URL","isHttps","protocol","hostname","normalized","toLowerCase","endsWith","test","octets","split","map","part","Number","some","octet","isNaN","a","b","isPrivateOrLoopbackHost","isValidJsonObject","value","Array","isArray","JSON","stringify","encodeBase64UrlUtf8","input","String","TextEncoder","bytes","encode","binary","forEach","byte","fromCharCode","btoa","unescape","encodeURIComponent","encodeBase64Utf8","replace","validateConfig","config","errors","paymentType","normalizedCurrency","currency","toUpperCase","includes","push","join","undefined","amount","num","parseFloat","isPositiveNumber","itemName","displayItems","metaData","callbackUrl","authHoldTimeInSeconds","parseInt","isInteger","isPositiveInteger","frequency","recurringInterval","toString","recurringEndDate","date","Date","getTime","isValidIsoDateTime","valid","length","createError","code","message","details","timestamp","toISOString","MessageHandler","onMessage","allowedOrigins","sessionId","now","Math","random","substring","iframe","messageListener","pendingMessages","Map","init","_handleMessage","bind","window","addEventListener","destroy","removeEventListener","clear","event","source","_validateOrigin","origin","contentWindow","eventOrigin","data","_validateMessageStructure","_processMessage","startsWith","type","Object","values","sendToPaymentApp","sdkVersion","targetOrigin","postMessage","sendInit","mode","sendClose","getSessionId","ModalManager","onClose","overlay","container","closeButton","isOpen","escapeListener","open","_createModal","_attachEventListeners","_show","close","_hide","_removeEventListeners","_destroyModal","document","createElement","id","_applyOverlayStyles","_applyContainerStyles","setAttribute","_applyIframeStyles","appendChild","body","element","assign","style","position","inset","width","height","margin","padding","boxSizing","backgroundColor","zIndex","display","alignItems","justifyContent","opacity","transition","backdropFilter","overflow","isMobile","innerWidth","_isMobile","flex","alignSelf","maxWidth","minHeight","maxHeight","borderRadius","boxShadow","transform","flexDirection","_getContainerTransform","scale","_applyCloseButtonStyles","top","right","border","color","fontSize","lineHeight","cursor","fontFamily","requestAnimationFrame","setTimeout","parentNode","removeChild","_handleCloseClick","stopPropagation","_handleOverlayClick","target","_handleEscapeKey","key","getIframe","getIsOpen","SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS","DroppPaymentSDK","Error","merchantId","apiKey","baseUrl","paymentAppUrl","isInitialized","initializationPromise","getServerAuthToken","requireServerAuthToken","currentSession","currentFlowType","statusSession","hiddenIframe","statusTimeout","initTimeout","paymentTimeout","hostAppDomain","onAccountChanged","onPageFailed","messageHandler","modalManager","debugLogging","pay","Promise","resolve","reject","initialize","validation","onSuccess","onFailure","onCancel","startTime","_initializePayment","sdkError","originalError","_cleanup","_detectHostAppDomain","_validateInitializationCredentials","status","catch","_getValidationUrl","validationUrls","location","_getHostedPageAuthToken","merchantAccount","apikey","_formatValidationFailureMessage","baseMessage","responseBody","parts","isFinite","responseCodeRaw","responseCode","reason","firstError","validationUrl","merchantDomain","headers","accept","response","fetch","method","endpoint","json","ok","hasNoErrors","closePayment","_handleCancel","dashboard","_openHostedPage","moduleId","normalizedModuleId","supportedModuleIds","route","unlinkAccount","transactions","offers","pointerEvents","visibility","queryParams","URLSearchParams","sdkMode","platform","hostedAuthToken","set","normalizedBaseUrl","src","sessionDuration","_handleModalClose","recurringFrequency","isRecurringNone","detectedAppUrl","appUrl","href","params","maxAmount","fixAmount","acceptPaymentDelay","description","invoiceId","invoiceType","packageName","resolvedDisplayItem","displayItem","resolvedMetaData","metadata","successURL","failureURL","expiry","submitToCallBack","authContext","issuedAt","serverAuthToken","tokenFromCallback","paymentUrl","async","authOptions","payload","keys","base64Payload","sdkTs","buildPaymentUrl","_handleTimeout","onFailed","modules","module","filter","Boolean","_handleReady","_handlePageLoaded","_handleSuccess","_handleFailure","_handleAccountStatus","_handleAccountEvent","_handlePageEvent","clearTimeout","serializableOptions","_getBridgeAction","action","result","_getSafeFailureMessage","fallback","_getSafeResult","linked","rawData","getVersion","getEnvironments","getPaymentTypes","DROPP_CONTEXT_MENU_GUARD_KEY","preventDefault","disableContextMenuOnImport","globalDroppInstance","createPaymentSDK","sdk","getDroppInstance","Dropp","getInstance","index"],"mappings":"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"}
1
+ {"version":3,"file":"dropp-payment-sdk.esm.js","sources":["../src/constants.js","../src/logger.js","../src/utils.js","../src/messageHandler.js","../src/modalManager.js","../src/DroppPaymentSDK.js","../src/index.js"],"sourcesContent":["/**\n * Constants for Dropp Payment SDK\n */\n\n// Message types from payment app to SDK\nexport const MESSAGE_TYPES = {\n READY: 'DROPP_SDK_READY',\n PAYMENT_SUCCESS: 'PAYMENT_SUCCESS',\n PAYMENT_FAILED: 'PAYMENT_FAILED',\n PAYMENT_CANCELLED: 'PAYMENT_CANCELLED',\n ACCOUNT_EVENT: 'ACCOUNT_EVENT',\n PAGE_EVENT: 'PAGE_EVENT',\n ACCOUNT_STATUS: 'ACCOUNT_STATUS',\n CLOSE_WEBVIEW: 'CLOSE_WEBVIEW',\n AUTO_CLOSE_WEBVIEW: 'AUTO_CLOSE_WEBVIEW',\n PAYMENT_PAGE_LOADED: 'PAYMENT_PAGE_LOADED',\n PAGE_LOADED: 'PAGE_LOADED'\n};\n\n// Message types from SDK to payment app\nexport const SDK_MESSAGE_TYPES = {\n INIT: 'DROPP_SDK_INIT',\n CLOSE: 'DROPP_SDK_CLOSE'\n};\n\n// Environment configurations\nexport const ENVIRONMENTS = {\n PRODUCTION: 'production',\n QA: 'qa',\n SANDBOX: 'sandbox'\n};\n\n// Payment app URLs by environment\nexport const PAYMENT_APP_URLS = {\n [ENVIRONMENTS.PRODUCTION]: 'https://wv.dropp.cc',\n [ENVIRONMENTS.QA]: 'https://wv.qa.dropp.cc', // Assuming local QA server\n [ENVIRONMENTS.SANDBOX]: 'https://wv.sandbox.dropp.cc'\n};\n\n// Allowed origins for message validation (by environment)\nexport const ALLOWED_ORIGINS = {\n [ENVIRONMENTS.PRODUCTION]: ['https://wv.dropp.cc'],\n [ENVIRONMENTS.QA]: ['https://wv.qa.dropp.cc'], // Match QA server origin\n [ENVIRONMENTS.SANDBOX]: ['https://wv.sandbox.dropp.cc']\n};\n\n// Timeouts\nexport const TIMEOUTS = {\n INIT: 30000, // 30 seconds for app to load and send READY\n PAYMENT: 600000, // 10 minutes max for payment completion\n CLOSE_DELAY: 10000 // 10 seconds delay before closing modal after success/failure\n};\n\n// Payment types\nexport const PAYMENT_TYPES = {\n STANDARD: 'standard',\n PREAUTH: 'preauth',\n RECURRING: 'recurring'\n};\n\n// Error codes\nexport const ERROR_CODES = {\n INIT_TIMEOUT: 'INIT_TIMEOUT',\n PAYMENT_TIMEOUT: 'PAYMENT_TIMEOUT',\n INVALID_CONFIG: 'INVALID_CONFIG',\n ALREADY_OPEN: 'ALREADY_OPEN',\n ORIGIN_MISMATCH: 'ORIGIN_MISMATCH',\n MESSAGE_VALIDATION_FAILED: 'MESSAGE_VALIDATION_FAILED',\n IFRAME_BLOCKED: 'IFRAME_BLOCKED',\n UNKNOWN_ERROR: 'UNKNOWN_ERROR'\n};\n\n// SDK version\nexport const SDK_VERSION = '1.0.2';\n\n// CSS z-index for modal\nexport const MODAL_Z_INDEX = 999999;\n","/**\n * Logger utility for Dropp Payment SDK\n * Logging is disabled by default and can be enabled explicitly.\n */\n\nclass Logger {\n constructor(environment, options = {}) {\n this.environment = environment;\n this.forceEnabled = !!options.enabled;\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Determine if logging should be enabled\n * @private\n */\n _shouldEnableLogging() {\n return this.forceEnabled;\n }\n\n /**\n * Update environment and recalculate logging state\n */\n setEnvironment(environment, options = {}) {\n this.environment = environment;\n if (typeof options.enabled === 'boolean') {\n this.forceEnabled = options.enabled;\n }\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Explicitly enable or disable logging.\n */\n setEnabled(enabled) {\n this.forceEnabled = !!enabled;\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Log info messages\n */\n log(...args) {\n if (this.enabled) {\n console.log(...args);\n }\n }\n\n /**\n * Log warning messages\n */\n warn(...args) {\n if (this.enabled) {\n console.warn(...args);\n }\n }\n\n /**\n * Log error messages\n */\n error(...args) {\n if (this.enabled) {\n console.error(...args);\n }\n }\n\n /**\n * Log debug messages\n */\n debug(...args) {\n if (this.enabled) {\n console.debug(...args);\n }\n }\n\n /**\n * Log info messages\n */\n info(...args) {\n if (this.enabled) {\n console.info(...args);\n }\n }\n}\n\n// Create singleton instance with default environment\nconst logger = new Logger('qa', { enabled: false });\n\nexport default logger;\n","/**\n * Utility functions for Dropp Payment SDK\n */\n\nimport logger from './logger.js';\nimport { PAYMENT_TYPES } from './constants.js';\n\nconst SUPPORTED_CURRENCIES = ['USD', 'HBAR', 'USDC'];\n\nconst RECURRING_FREQUENCY_VALUES = [\n 'NONE',\n 'HALF_HOURLY',\n 'HOURLY',\n 'DAILY',\n 'WEEKLY',\n 'MONTHLY',\n 'YEARLY'\n];\n\nconst PAYMENT_TYPE_VALUES = [\n PAYMENT_TYPES.STANDARD,\n PAYMENT_TYPES.PREAUTH,\n PAYMENT_TYPES.RECURRING\n];\n\nconst DISPLAY_ITEM_TYPES = ['item', 'subTotal', 'otherCharges', 'discount'];\n\nconst DISPLAY_ITEM_REQUIRED_KEYS = ['label', 'value', 'type'];\n\nfunction isPositiveNumber(value) {\n const num = typeof value === 'number' ? value : parseFloat(value);\n return typeof num === 'number' && !Number.isNaN(num) && num > 0;\n}\n\nfunction isPositiveInteger(value) {\n const num = typeof value === 'number' ? value : parseInt(value, 10);\n return Number.isInteger(num) && num > 0;\n}\n\nfunction isIpV4(value) {\n return /^(\\d{1,3}\\.){3}\\d{1,3}$/.test(value);\n}\n\nfunction isPrivateOrLoopbackHost(hostname) {\n if (!hostname) {\n return false;\n }\n\n const normalized = hostname.trim().toLowerCase();\n if (\n normalized === 'localhost' ||\n normalized === '127.0.0.1' ||\n normalized === '::1' ||\n normalized.endsWith('.local')\n ) {\n return true;\n }\n\n if (!isIpV4(normalized)) {\n return false;\n }\n\n const octets = normalized.split('.').map(part => Number(part));\n if (octets.some(octet => Number.isNaN(octet) || octet < 0 || octet > 255)) {\n return false;\n }\n\n const [a, b] = octets;\n // RFC1918 private ranges + loopback + link-local\n if (a === 10 || a === 127) {\n return true;\n }\n if (a === 172 && b >= 16 && b <= 31) {\n return true;\n }\n if (a === 192 && b === 168) {\n return true;\n }\n if (a === 169 && b === 254) {\n return true;\n }\n\n return false;\n}\n\nfunction isValidCallbackUrl(url, options = {}) {\n const {\n isProduction = false,\n allowLocalCallbacksInNonProd = false\n } = options;\n\n if (typeof url !== 'string' || !url.trim()) {\n return false;\n }\n\n try {\n const parsed = new URL(url.trim());\n const isHttps = parsed.protocol === 'https:';\n const isHttp = parsed.protocol === 'http:';\n\n if (!isHttp && !isHttps) {\n return false;\n }\n\n const isPrivateOrLoopback = isPrivateOrLoopbackHost(parsed.hostname);\n if (isPrivateOrLoopback) {\n return !isProduction && allowLocalCallbacksInNonProd;\n }\n\n if (isProduction) {\n return isHttps;\n }\n\n // Non-production can allow HTTP for public hosts by default.\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidIsoDateTime(value) {\n if (typeof value !== 'string' || !value.trim()) {\n return false;\n }\n const date = new Date(value.trim());\n return !Number.isNaN(date.getTime());\n}\n\nfunction isValidJsonObject(value) {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n\n try {\n JSON.stringify(value);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction validateDisplayItemsArray(value) {\n if (!Array.isArray(value)) {\n return 'displayItems must be an array of objects with keys: label, value, type';\n }\n\n for (let i = 0; i < value.length; i += 1) {\n const item = value[i];\n\n if (!item || typeof item !== 'object' || Array.isArray(item)) {\n return `displayItems[${i}] must be a valid object`;\n }\n\n const keys = Object.keys(item);\n const hasExactKeys =\n keys.length === DISPLAY_ITEM_REQUIRED_KEYS.length &&\n DISPLAY_ITEM_REQUIRED_KEYS.every(key => Object.prototype.hasOwnProperty.call(item, key));\n\n if (!hasExactKeys) {\n return `displayItems[${i}] must contain exactly these keys: ${DISPLAY_ITEM_REQUIRED_KEYS.join(', ')}`;\n }\n\n if (typeof item.label !== 'string' || !item.label.trim()) {\n return `displayItems[${i}].label must be a non-empty string`;\n }\n\n const normalizedValue =\n typeof item.value === 'string'\n ? item.value.replace(/[$,\\s]/g, '')\n : item.value;\n const numericValue =\n typeof normalizedValue === 'number' ? normalizedValue : Number(normalizedValue);\n if (!Number.isFinite(numericValue) || numericValue < 0) {\n return `displayItems[${i}].value must be a number greater than or equal to 0`;\n }\n\n if (!DISPLAY_ITEM_TYPES.includes(item.type)) {\n return `displayItems[${i}].type must be one of: ${DISPLAY_ITEM_TYPES.join(', ')}`;\n }\n }\n\n return null;\n}\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId() {\n return `dropp-sdk-${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n}\n\n/**\n * Base64-encode a UTF-8 string.\n */\nexport function encodeBase64Utf8(value) {\n const input = typeof value === 'string' ? value : String(value ?? '');\n\n // Prefer browser-native TextEncoder path to support full Unicode safely.\n if (typeof TextEncoder !== 'undefined') {\n const bytes = new TextEncoder().encode(input);\n let binary = '';\n bytes.forEach(byte => {\n binary += String.fromCharCode(byte);\n });\n\n return btoa(binary);\n }\n\n // Fallback for very old runtimes.\n return btoa(unescape(encodeURIComponent(input)));\n}\n\n/**\n * Base64url-encode a UTF-8 string without padding.\n */\nexport function encodeBase64UrlUtf8(value) {\n return encodeBase64Utf8(value)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Build payment URL with base64 payload (matching Android SDK pattern)\n */\nexport async function buildPaymentUrl(baseUrl, route, params, sdkVersion, authOptions = {}) {\n try {\n const { serverAuthToken = '' } = authOptions;\n\n // Create JSON payload\n const payload = {};\n Object.keys(params).forEach(key => {\n const value = params[key];\n if (value !== null && value !== undefined) {\n payload[key] = value;\n }\n });\n \n logger.log('[buildPaymentUrl] Building payment URL payload');\n \n // Base64url encode payload (UTF-8 safe, no padding)\n const jsonString = JSON.stringify(payload);\n const base64Payload = encodeBase64UrlUtf8(jsonString);\n \n const timestamp = Date.now().toString();\n const queryParams = new URLSearchParams({\n pay: base64Payload,\n sdkTs: timestamp,\n sdkVersion,\n platform: 'web'\n });\n\n if (serverAuthToken) {\n queryParams.set('authToken', serverAuthToken);\n }\n\n const url = `${baseUrl}/#${route}?${queryParams.toString()}`;\n \n return url;\n } catch (error) {\n logger.error('Error building payment URL:', error);\n throw error;\n }\n}\n\n/**\n * Validate payment configuration for standard, preauth, and recurring payments\n */\nexport function validateConfig(config = {}, options = {}) {\n const errors = [];\n const paymentType = config.paymentType || PAYMENT_TYPES.STANDARD;\n const isProduction = (options.environment || '').toLowerCase() === 'production';\n const allowLocalCallbacksInNonProd = !!options.allowLocalCallbacksInNonProd;\n const normalizedCurrency =\n typeof config.currency === 'string' ? config.currency.trim().toUpperCase() : '';\n\n if (!PAYMENT_TYPE_VALUES.includes(paymentType)) {\n errors.push(\n `paymentType must be one of: ${PAYMENT_TYPE_VALUES.join(', ')}`\n );\n }\n\n if (config.amount === undefined || config.amount === null || config.amount === '') {\n errors.push('amount is required');\n } else if (!isPositiveNumber(config.amount)) {\n errors.push('amount must be a positive number');\n }\n\n if (!config.currency || typeof config.currency !== 'string' || !config.currency.trim()) {\n errors.push('currency is required');\n } else if (!SUPPORTED_CURRENCIES.includes(normalizedCurrency)) {\n errors.push(`currency must be one of: ${SUPPORTED_CURRENCIES.join(', ')}`);\n }\n\n if (!config.itemName || typeof config.itemName !== 'string' || !config.itemName.trim()) {\n errors.push('itemName is required');\n }\n\n if (paymentType === PAYMENT_TYPES.STANDARD) {\n if (config.displayItems !== undefined) {\n const displayItemsError = validateDisplayItemsArray(config.displayItems);\n if (displayItemsError) {\n errors.push(displayItemsError);\n }\n }\n\n if (config.metaData !== undefined && !isValidJsonObject(config.metaData)) {\n errors.push('metaData must be a valid JSON object for standard payments');\n }\n }\n\n if (paymentType === PAYMENT_TYPES.PREAUTH) {\n if (normalizedCurrency && normalizedCurrency !== 'USD') {\n errors.push('currency must be USD for preauth payments');\n }\n\n if (!config.callbackUrl || !String(config.callbackUrl).trim()) {\n errors.push('callbackUrl (signing URL) is required for preauth payments');\n } else if (!isValidCallbackUrl(config.callbackUrl, {\n isProduction,\n allowLocalCallbacksInNonProd\n })) {\n errors.push(\n isProduction\n ? 'callbackUrl must be HTTPS in production and cannot target loopback/private hosts'\n : 'callbackUrl must be a valid HTTP/HTTPS URL and cannot target loopback/private hosts unless explicitly enabled'\n );\n }\n\n if (\n config.authHoldTimeInSeconds === undefined ||\n config.authHoldTimeInSeconds === null ||\n config.authHoldTimeInSeconds === ''\n ) {\n errors.push('authHoldTimeInSeconds is required for preauth payments');\n } else if (!isPositiveInteger(config.authHoldTimeInSeconds)) {\n errors.push('authHoldTimeInSeconds must be a positive integer (seconds)');\n }\n }\n\n if (paymentType === PAYMENT_TYPES.RECURRING) {\n if (!config.callbackUrl || !String(config.callbackUrl).trim()) {\n errors.push('callbackUrl (signing URL) is required for recurring payments');\n } else if (!isValidCallbackUrl(config.callbackUrl, {\n isProduction,\n allowLocalCallbacksInNonProd\n })) {\n errors.push(\n isProduction\n ? 'callbackUrl must be HTTPS in production and cannot target loopback/private hosts'\n : 'callbackUrl must be a valid HTTP/HTTPS URL and cannot target loopback/private hosts unless explicitly enabled'\n );\n }\n\n const frequency = (config.frequency || config.recurringInterval || '')\n .toString()\n .trim()\n .toUpperCase();\n\n if (!frequency) {\n errors.push('frequency is required for recurring payments');\n } else if (!RECURRING_FREQUENCY_VALUES.includes(frequency)) {\n errors.push(\n `frequency must be one of: ${RECURRING_FREQUENCY_VALUES.join(', ')}`\n );\n }\n\n if (!config.recurringEndDate || !String(config.recurringEndDate).trim()) {\n errors.push('recurringEndDate (expiry) is required for recurring payments');\n } else if (!isValidIsoDateTime(config.recurringEndDate)) {\n errors.push('recurringEndDate must be a valid ISO date-time string');\n } else if (new Date(config.recurringEndDate.trim()) <= new Date()) {\n errors.push('recurringEndDate must be in the future');\n }\n }\n\n return {\n valid: errors.length === 0,\n errors\n };\n}\n\n/**\n * Create error object\n */\nexport function createError(code, message, details = {}) {\n return {\n code,\n message,\n details,\n timestamp: new Date().toISOString(),\n toString() {\n return this.message || 'Dropp SDK error';\n }\n };\n}\n\n/**\n * Deep clone object\n */\nexport function deepClone(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * Check if running in browser environment\n */\nexport function isBrowser() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Sanitize HTML to prevent XSS\n */\nexport function sanitizeHTML(str) {\n if (!str) return '';\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\n/**\n * Format amount for display\n */\nexport function formatAmount(amount, currency) {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD'\n }).format(amount);\n } catch (error) {\n return `${amount} ${currency}`;\n }\n}\n","/**\n * Secure Message Handler for SDK โ†” Payment App Communication\n * \n * Implements:\n * - Origin validation\n * - Message schema validation\n * - Session correlation\n * - Anti-spoofing protection\n */\n\nimport { MESSAGE_TYPES, SDK_MESSAGE_TYPES, ALLOWED_ORIGINS } from './constants.js';\nimport { generateSessionId } from './utils.js';\nimport logger from './logger.js';\n\nexport class MessageHandler {\n constructor(environment, onMessage, allowedOrigins = null) {\n this.environment = environment;\n this.onMessage = onMessage;\n this.sessionId = generateSessionId();\n logger.log('[MessageHandler] Session initialized');\n this.iframe = null;\n this.allowedOrigins =\n allowedOrigins?.length > 0\n ? allowedOrigins\n : ALLOWED_ORIGINS[environment] || [];\n this.messageListener = null;\n this.pendingMessages = new Map(); // Track correlation IDs for request/response\n }\n\n /**\n * Initialize message listener\n */\n init(iframe) {\n this.iframe = iframe;\n this.messageListener = this._handleMessage.bind(this);\n window.addEventListener('message', this.messageListener);\n }\n\n /**\n * Clean up message listener\n */\n destroy() {\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n this.iframe = null;\n this.pendingMessages.clear();\n }\n\n /**\n * Handle incoming postMessage events\n * @private\n */\n _handleMessage(event) {\n logger.log('[MessageHandler] Received postMessage event');\n\n // Ignore messages from self (parent window)\n if (event.source === window) {\n logger.log('[MessageHandler] Ignoring message from self');\n return;\n }\n\n // 1. Validate origin\n if (!this._validateOrigin(event.origin)) {\n logger.warn('[Dropp SDK] Rejected message from untrusted origin:', event.origin);\n return;\n }\n\n // 2. Validate event source\n if (!this.iframe || event.source !== this.iframe.contentWindow) {\n logger.warn('[Dropp SDK] Rejected message from unexpected source', {\n eventOrigin: event.origin\n });\n return;\n }\n\n // 3. Validate message structure\n const message = event.data;\n if (!this._validateMessageStructure(message)) {\n logger.warn('[Dropp SDK] Rejected message with invalid structure');\n return;\n }\n\n // 4. Validate session ID (if present)\n if (message.sessionId && message.sessionId !== this.sessionId) {\n logger.warn('[Dropp SDK] Rejected message with invalid session ID');\n return;\n }\n\n // 5. Process valid message\n logger.log('[MessageHandler] Message passed validation');\n this._processMessage(message);\n }\n\n /**\n * Validate message origin against allowed list\n * @private\n */\n _validateOrigin(origin) {\n // In development/testing, allow localhost\n if (origin.startsWith('http://localhost:') || origin.startsWith('http://127.0.0.1:')) {\n return true;\n }\n\n // Enforce exact scheme + host + port origin match.\n return this.allowedOrigins.includes(origin);\n }\n\n /**\n * Validate message structure and type\n * @private\n */\n _validateMessageStructure(message) {\n if (!message || typeof message !== 'object') {\n return false;\n }\n\n // Must have a type field\n if (!message.type || typeof message.type !== 'string') {\n return false;\n }\n\n // Must be a known message type from payment app\n const validTypes = Object.values(MESSAGE_TYPES);\n if (!validTypes.includes(message.type)) {\n return false;\n }\n\n // ACCOUNT_STATUS from hosted status page may not include timestamp.\n if (message.type !== MESSAGE_TYPES.ACCOUNT_STATUS && !message.timestamp) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Process validated message\n * @private\n */\n _processMessage(message) {\n logger.log('[Dropp SDK] Received message:', message.type);\n\n // Invoke callback\n if (this.onMessage) {\n this.onMessage(message);\n }\n }\n\n /**\n * Send message to payment app\n */\n sendToPaymentApp(type, data = {}) {\n if (!this.iframe || !this.iframe.contentWindow) {\n logger.error('[Dropp SDK] Cannot send message: iframe not ready');\n return false;\n }\n\n const message = {\n type,\n data,\n sessionId: this.sessionId,\n timestamp: new Date().toISOString(),\n sdkVersion: '1.0.0'\n };\n\n // Get target origin from allowed origins\n const targetOrigin = this.allowedOrigins[0] || '*';\n\n try {\n this.iframe.contentWindow.postMessage(message, targetOrigin);\n logger.log('[Dropp SDK] Sent message:', type);\n return true;\n } catch (error) {\n logger.error('[Dropp SDK] Error sending message:', error);\n return false;\n }\n }\n\n /**\n * Send init message to payment app\n */\n sendInit(config) {\n return this.sendToPaymentApp(SDK_MESSAGE_TYPES.INIT, {\n mode: 'sdk',\n config\n });\n }\n\n /**\n * Send close request to payment app\n */\n sendClose() {\n return this.sendToPaymentApp(SDK_MESSAGE_TYPES.CLOSE, {});\n }\n\n /**\n * Get session ID\n */\n getSessionId() {\n return this.sessionId;\n }\n}\n","/**\n * Modal Manager - Creates and manages the payment modal UI\n * \n * Responsibilities:\n * - Create modal overlay and container\n * - Manage modal lifecycle (open/close/destroy)\n * - Handle focus trapping\n * - Clean up DOM and event listeners\n * - Responsive design\n */\n\nimport { MODAL_Z_INDEX } from './constants.js';\nimport logger from './logger.js';\n\nexport class ModalManager {\n constructor(onClose) {\n this.onClose = onClose;\n this.overlay = null;\n this.container = null;\n this.iframe = null;\n this.closeButton = null;\n this.isOpen = false;\n this.escapeListener = null;\n }\n\n /**\n * Create and show modal\n */\n open() {\n if (this.isOpen) {\n logger.warn('[Dropp SDK] Modal is already open');\n return null;\n }\n\n this._createModal();\n this._attachEventListeners();\n this._show();\n\n this.isOpen = true;\n return this.iframe;\n }\n\n /**\n * Close and cleanup modal\n */\n close() {\n logger.log('[ModalManager] ๐Ÿšฆ close() called, isOpen:', this.isOpen);\n \n if (!this.isOpen) {\n logger.log('[ModalManager] โš ๏ธ Modal is not open, skipping close');\n return;\n }\n\n logger.log('[ModalManager] ๐Ÿšฆ Hiding modal...');\n this._hide();\n logger.log('[ModalManager] ๐Ÿšฆ Removing event listeners...');\n this._removeEventListeners();\n logger.log('[ModalManager] ๐Ÿšฆ Destroying modal...');\n this._destroyModal();\n\n this.isOpen = false;\n logger.log('[ModalManager] โœ… Modal close sequence initiated');\n }\n\n /**\n * Create modal DOM elements\n * @private\n */\n _createModal() {\n // Create overlay\n this.overlay = document.createElement('div');\n this.overlay.id = 'dropp-payment-overlay';\n this._applyOverlayStyles(this.overlay);\n\n // Create container\n this.container = document.createElement('div');\n this.container.id = 'dropp-payment-container';\n this._applyContainerStyles(this.container);\n\n // Close button removed - will be rendered by chrome app instead\n\n // Create iframe\n this.iframe = document.createElement('iframe');\n this.iframe.id = 'dropp-payment-iframe';\n this.iframe.setAttribute('allow', 'payment');\n this.iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');\n this.iframe.setAttribute('referrerpolicy', 'no-referrer');\n this.iframe.setAttribute('title', 'Dropp Payment');\n this._applyIframeStyles(this.iframe);\n\n // Assemble modal\n this.container.appendChild(this.iframe);\n this.overlay.appendChild(this.container);\n\n // Add to DOM\n document.body.appendChild(this.overlay);\n }\n\n /**\n * Apply styles to overlay\n * @private\n */\n _applyOverlayStyles(element) {\n Object.assign(element.style, {\n position: 'fixed',\n inset: '0',\n width: '100vw',\n height: '100vh',\n margin: '0',\n padding: '20px',\n boxSizing: 'border-box',\n backgroundColor: 'rgba(0, 0, 0, 0.6)',\n zIndex: MODAL_Z_INDEX.toString(),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n opacity: '0',\n transition: 'opacity 0.3s ease',\n backdropFilter: 'blur(4px)',\n overflow: 'auto'\n });\n }\n\n /**\n * Apply styles to container\n * @private\n */\n _applyContainerStyles(element) {\n const isMobile = window.innerWidth < 768;\n this._isMobile = isMobile;\n\n Object.assign(element.style, {\n position: 'relative',\n flex: '0 0 auto',\n alignSelf: 'center',\n margin: 'auto',\n width: '100%',\n maxWidth: isMobile ? '100%' : '400px',\n height: isMobile ? '100%' : 'auto',\n minHeight: isMobile ? '100%' : '800px',\n maxHeight: isMobile ? '100%' : 'min(1000px, calc(100vh - 40px))',\n backgroundColor: '#ffffff',\n borderRadius: isMobile ? '0' : '16px',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)',\n overflow: 'hidden',\n transform: 'scale(0.95)',\n transition: 'transform 0.3s ease, opacity 0.3s ease',\n display: 'flex',\n flexDirection: 'column'\n });\n }\n\n _getContainerTransform(scale) {\n return `scale(${scale})`;\n }\n\n /**\n * Apply styles to close button\n * @private\n */\n _applyCloseButtonStyles(element) {\n Object.assign(element.style, {\n position: 'absolute',\n top: '16px',\n right: '16px',\n zIndex: '10',\n width: '40px',\n height: '40px',\n border: 'none',\n borderRadius: '50%',\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\n color: '#333',\n fontSize: '28px',\n lineHeight: '1',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n transition: 'all 0.2s ease',\n fontFamily: 'Arial, sans-serif',\n padding: '0'\n });\n\n // Hover effect\n element.addEventListener('mouseenter', () => {\n Object.assign(element.style, {\n backgroundColor: '#f5f5f5',\n transform: 'scale(1.1)'\n });\n });\n\n element.addEventListener('mouseleave', () => {\n Object.assign(element.style, {\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\n transform: 'scale(1)'\n });\n });\n }\n\n /**\n * Apply styles to iframe\n * @private\n */\n _applyIframeStyles(element) {\n const isMobile = this._isMobile;\n Object.assign(element.style, {\n width: '100%',\n flex: '1 1 auto',\n minHeight: isMobile ? '100%' : 'min(520px, calc(90vh - 40px))',\n height: isMobile ? '100%' : 'min(520px, calc(90vh - 40px))',\n border: 'none',\n display: 'block'\n });\n }\n\n /**\n * Show modal with animation\n * @private\n */\n _show() {\n // Prevent body scroll\n document.body.style.overflow = 'hidden';\n\n // Trigger animation\n requestAnimationFrame(() => {\n if (this.overlay) {\n this.overlay.style.opacity = '1';\n }\n if (this.container) {\n this.container.style.transform = this._getContainerTransform(1);\n }\n });\n }\n\n /**\n * Hide modal with animation\n * @private\n */\n _hide() {\n logger.log('[ModalManager] ๐ŸŽญ _hide() called');\n if (this.overlay) {\n this.overlay.style.opacity = '0';\n logger.log('[ModalManager] ๐ŸŽญ Overlay opacity set to 0');\n }\n if (this.container) {\n this.container.style.transform = this._getContainerTransform(0.95);\n logger.log('[ModalManager] ๐ŸŽญ Container transform set to scale(0.95)');\n }\n\n // Restore body scroll\n document.body.style.overflow = '';\n logger.log('[ModalManager] ๐ŸŽญ Body scroll restored');\n }\n\n /**\n * Destroy modal DOM elements\n * @private\n */\n _destroyModal() {\n logger.log('[ModalManager] ๐Ÿ—‘๏ธ _destroyModal() called, waiting 300ms for animation');\n // Wait for animation to complete\n setTimeout(() => {\n logger.log('[ModalManager] ๐Ÿ—‘๏ธ Animation complete, removing from DOM');\n if (this.overlay && this.overlay.parentNode) {\n this.overlay.parentNode.removeChild(this.overlay);\n logger.log('[ModalManager] ๐Ÿ—‘๏ธ Overlay removed from DOM');\n }\n this.overlay = null;\n this.container = null;\n this.iframe = null;\n this.closeButton = null;\n logger.log('[ModalManager] โœ… Modal destroyed');\n }, 300);\n }\n\n /**\n * Attach event listeners\n * @private\n */\n _attachEventListeners() {\n // Close button removed - will be handled by chrome app\n // Close button click\n // if (this.closeButton) {\n // this.closeButton.addEventListener('click', this._handleCloseClick.bind(this));\n // }\n\n // Backdrop click disabled for payment security\n // Users must use close button or complete/cancel payment\n // if (this.overlay) {\n // this.overlay.addEventListener('click', this._handleOverlayClick.bind(this));\n // }\n\n // Escape key disabled for payment security\n // Users must use close button or complete/cancel payment\n // this.escapeListener = this._handleEscapeKey.bind(this);\n // document.addEventListener('keydown', this.escapeListener);\n }\n\n /**\n * Remove event listeners\n * @private\n */\n _removeEventListeners() {\n if (this.escapeListener) {\n document.removeEventListener('keydown', this.escapeListener);\n this.escapeListener = null;\n }\n }\n\n /**\n * Handle close button click\n * @private\n */\n _handleCloseClick(event) {\n event.stopPropagation();\n if (this.onClose) {\n this.onClose('user_closed');\n }\n }\n\n /**\n * Handle overlay click (backdrop)\n * @private\n */\n _handleOverlayClick(event) {\n // Only close if clicking directly on overlay (not container)\n if (event.target === this.overlay) {\n if (this.onClose) {\n this.onClose('user_closed');\n }\n }\n }\n\n /**\n * Handle escape key press\n * @private\n */\n _handleEscapeKey(event) {\n if (event.key === 'Escape' && this.isOpen) {\n if (this.onClose) {\n this.onClose('user_closed');\n }\n }\n }\n\n /**\n * Get iframe element\n */\n getIframe() {\n return this.iframe;\n }\n\n /**\n * Check if modal is open\n */\n getIsOpen() {\n return this.isOpen;\n }\n}\n","/**\n * Dropp Payment SDK - Main SDK Class\n * \n * Public API for integrating Dropp payments into web applications\n */\n\nimport { \n ENVIRONMENTS, \n PAYMENT_APP_URLS,\n ALLOWED_ORIGINS,\n MESSAGE_TYPES, \n ERROR_CODES, \n TIMEOUTS, \n PAYMENT_TYPES,\n SDK_VERSION\n} from './constants.js';\nimport { MessageHandler } from './messageHandler.js';\nimport { ModalManager } from './modalManager.js';\nimport { \n buildPaymentUrl, \n encodeBase64UrlUtf8,\n validateConfig, \n createError, \n isBrowser \n} from './utils.js';\nimport logger from './logger.js';\n\nconst SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS = [\n 'fundnow',\n 'linkbank',\n 'linkcard',\n 'redeemnow',\n 'fundcrypto',\n 'transferusdc',\n 'usdchistory',\n 'redeemcrypto',\n 'manageaccounts',\n 'transactions',\n 'merchantlist',\n 'favorites',\n 'offers',\n 'profile',\n 'pinchange',\n 'unlinkaccount',\n 'accountsettings',\n 'aboutus'\n];\n\nexport class DroppPaymentSDK {\n /**\n * Create SDK instance\n * @param {Object} config - SDK configuration\n * @param {string} config.merchantId - Merchant Hedera account ID (required, e.g., '0.0.123456')\n * @param {string} config.apiKey - API Key (required)\n * @param {string} config.environment - Environment: 'production', 'qa', or 'sandbox'\n * @param {Function} [config.getServerAuthToken] - Optional async callback that returns a server-issued auth token\n * @param {boolean} [config.requireServerAuthToken] - Require server auth token (defaults to true in production)\n * @param {boolean} [config.allowLocalCallbacksInNonProd] - Allow loopback/private callback URLs in non-production\n */\n constructor(config = {}) {\n if (!isBrowser()) {\n throw new Error('Dropp Payment SDK can only be used in a browser environment');\n }\n\n // Validate required credentials\n if (!config.merchantId || !config.apiKey) {\n throw new Error('merchantId and apiKey are required to initialize SDK');\n }\n\n // Store credentials\n this.merchantId = config.merchantId;\n this.apiKey = config.apiKey;\n\n this.environment = config.environment || ENVIRONMENTS.QA;\n this.baseUrl =\n config.paymentAppUrl ||\n config.baseUrl ||\n PAYMENT_APP_URLS[this.environment];\n\n // Initialization state\n this.isInitialized = false;\n this.initializationPromise = null;\n\n this.getServerAuthToken =\n typeof config.getServerAuthToken === 'function'\n ? config.getServerAuthToken\n : null;\n this.requireServerAuthToken =\n typeof config.requireServerAuthToken === 'boolean'\n ? config.requireServerAuthToken\n : this.environment === ENVIRONMENTS.PRODUCTION;\n this.allowLocalCallbacksInNonProd = !!config.allowLocalCallbacksInNonProd;\n\n if (config.allowedOrigins?.length) {\n this.allowedOrigins = config.allowedOrigins;\n } else {\n try {\n // Derive allowed origin from the effective payment URL to keep a\n // single source of truth for iframe loading and postMessage validation.\n this.allowedOrigins = [new URL(this.baseUrl).origin];\n } catch {\n this.allowedOrigins = ALLOWED_ORIGINS[this.environment] || [];\n }\n }\n\n // State\n this.isOpen = false;\n this.currentSession = null;\n this.currentFlowType = null;\n this.statusSession = null;\n this.hiddenIframe = null;\n this.statusTimeout = null;\n this.initTimeout = null;\n this.paymentTimeout = null;\n this.hostAppDomain = null;\n this.onAccountChanged = null;\n this.onPageFailed = null;\n\n // Managers\n this.messageHandler = null;\n this.modalManager = null;\n\n // Set logger environment\n logger.setEnvironment(this.environment, { enabled: !!config.debugLogging });\n logger.log(`[Dropp SDK] Initialized v${SDK_VERSION} - Environment: ${this.environment}`);\n }\n\n /**\n * Open payment modal\n * @param {Object} options - Payment options\n * @param {number} options.amount - Payment amount (required)\n * @param {string} options.currency - Currency code (required)\n * @param {string} options.itemName - Item/service name (required)\n * @param {string} options.description - Payment description\n * @param {string} options.invoiceId - Invoice ID\n * @param {string} options.paymentType - Payment type: 'standard', 'preauth', or 'recurring'\n * @param {string} options.thumbnail - Product image URL\n * @param {number} options.authHoldTimeInSeconds - For preauth: hold time in seconds\n * @param {string} options.callbackUrl - Server callback URL\n * @param {boolean} [options.acceptPaymentDelay=false] - Allow delayed payment acceptance for standard payments (sent only when true)\n * @param {string} [options.serverAuthToken] - Server-issued short-lived token bound to payment context\n * @param {Function} options.onSuccess - Callback for successful payment\n * @param {Function} options.onFailure - Callback for failed payment\n * @param {Function} options.onCancel - Callback for cancelled payment\n * @param {Function} options.onClose - Callback for modal close\n * @returns {Promise<PaymentResult>}\n */\n pay(options = {}) {\n return new Promise((resolve, reject) => {\n // Block while any SDK flow is in progress (including status checks).\n if (this.isOpen || this.currentFlowType) {\n const error = createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A payment session is already in progress',\n {\n currentSession: this.currentSession,\n currentFlowType: this.currentFlowType\n }\n );\n reject(error);\n return;\n }\n\n (async () => {\n try {\n await this.initialize();\n\n // Validate payment configuration\n const validation = validateConfig(options, {\n environment: this.environment,\n allowLocalCallbacksInNonProd: this.allowLocalCallbacksInNonProd\n });\n if (!validation.valid) {\n const validationMessage =\n validation.errors.length > 0\n ? `Invalid payment configuration: ${validation.errors.join(' | ')}`\n : 'Invalid payment configuration';\n const error = createError(\n ERROR_CODES.INVALID_CONFIG,\n validationMessage,\n { errors: validation.errors }\n );\n reject(error);\n return;\n }\n\n // Store callbacks from options\n this.onSuccess = options.onSuccess || null;\n this.onFailure = options.onFailure || null;\n this.onCancel = options.onCancel || null;\n this.onClose = options.onClose || null;\n\n // Store resolve/reject for later\n this.currentSession = {\n resolve,\n reject,\n options,\n startTime: Date.now()\n };\n\n await this._initializePayment(options);\n } catch (error) {\n const isInitValidationError =\n error && error.code === ERROR_CODES.INVALID_CONFIG;\n const sdkError = isInitValidationError\n ? error\n : createError(\n ERROR_CODES.UNKNOWN_ERROR,\n 'Failed to initialize payment',\n { originalError: error?.message || String(error) }\n );\n\n reject(sdkError);\n this._cleanup();\n }\n })();\n });\n }\n\n /**\n * Initialize and validate merchant credentials with Dropp backend.\n * @returns {Promise<{status: string, code: string, message: string}>}\n */\n async initialize() {\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n\n this.initializationPromise = (async () => {\n this.hostAppDomain = this._detectHostAppDomain();\n if (!this.hostAppDomain) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unable to detect host app domain for SDK validation'\n );\n }\n\n await this._validateInitializationCredentials();\n this.isInitialized = true;\n return {\n status: 'success',\n code: 'INITIALIZED',\n message: 'Dropp SDK initialized successfully'\n };\n })().catch(error => {\n this.isInitialized = false;\n this.initializationPromise = null;\n throw error;\n });\n\n return this.initializationPromise;\n }\n\n /**\n * Resolve validation endpoint from configured base URL.\n * @private\n */\n _getValidationUrl() {\n const validationUrls = {\n [ENVIRONMENTS.QA]: 'https://bc0qfqi8c9.execute-api.us-east-1.amazonaws.com/QA-test-app-sdk-gateway-stage/sdk/payer/webview/validateSdk',\n [ENVIRONMENTS.SANDBOX]: 'https://76xbxsi4kf.execute-api.us-east-1.amazonaws.com/sandbox/sdk/payer/webview/validateSdk',\n [ENVIRONMENTS.PRODUCTION]: 'https://api.dropp.cc/payer/webview/validateSdk'\n };\n\n return (\n validationUrls[this.environment] ||\n validationUrls[ENVIRONMENTS.QA]\n );\n }\n\n /**\n * Detect host app domain from runtime browser context.\n * @private\n */\n _detectHostAppDomain() {\n if (typeof window === 'undefined' || !window.location) {\n return undefined;\n }\n\n return window.location.hostname || undefined;\n }\n\n /**\n * Build auth token for hosted page routes.\n * @private\n */\n _getHostedPageAuthToken() {\n const key = typeof this.apiKey === 'string' ? this.apiKey.trim() : '';\n const merchantAccount =\n typeof this.merchantId === 'string' ? this.merchantId.trim() : '';\n if (!key) {\n return '';\n }\n\n try {\n const authPayload = JSON.stringify({\n apikey: key,\n merchantAccount\n });\n return encodeBase64UrlUtf8(authPayload);\n } catch {\n return '';\n }\n }\n\n /**\n * Build an actionable validation error message from backend response.\n * @private\n */\n _formatValidationFailureMessage(baseMessage, status, responseBody) {\n const parts = [baseMessage];\n\n if (Number.isFinite(status)) {\n parts.push(`httpStatus=${status}`);\n }\n\n const responseCodeRaw = responseBody?.responseCode;\n const responseCode = Number(responseCodeRaw);\n if (!Number.isNaN(responseCode)) {\n parts.push(`responseCode=${responseCode}`);\n }\n\n let reason = '';\n if (Array.isArray(responseBody?.errors) && responseBody.errors.length > 0) {\n const firstError = responseBody.errors[0];\n if (typeof firstError === 'string') {\n reason = firstError;\n } else if (firstError && typeof firstError.message === 'string') {\n reason = firstError.message;\n } else {\n reason = JSON.stringify(firstError);\n }\n } else if (typeof responseBody?.message === 'string' && responseBody.message.trim()) {\n reason = responseBody.message.trim();\n }\n\n if (reason) {\n parts.push(`reason=${reason}`);\n }\n\n return parts.join(' | ');\n }\n\n /**\n * Validate merchant credentials and app package before any payment flow.\n * @private\n */\n async _validateInitializationCredentials() {\n const validationUrl = this._getValidationUrl();\n const merchantDomain = this.hostAppDomain;\n\n if (!merchantDomain) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unable to resolve host app domain for SDK validation'\n );\n }\n\n const headers = {\n accept: 'application/json, text/plain, */*',\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n 'x-app-package': merchantDomain,\n 'dropp-user-agent': 'WEB'\n };\n\n headers['dropp-merchant-domain'] = merchantDomain;\n\n let response;\n let responseBody = null;\n try {\n response = await fetch(validationUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({ id: this.merchantId })\n });\n } catch (error) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unable to validate merchant credentials',\n {\n endpoint: validationUrl,\n originalError: error?.message || String(error)\n }\n );\n }\n\n try {\n responseBody = await response.json();\n } catch {\n responseBody = null;\n }\n\n if (!response.ok) {\n const message = this._formatValidationFailureMessage(\n 'Merchant validation failed for merchantId/apiKey/domain',\n response.status,\n responseBody\n );\n\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n message,\n {\n endpoint: validationUrl,\n status: response.status,\n response: responseBody\n }\n );\n }\n\n const responseCode = Number(responseBody?.responseCode);\n const errors = responseBody?.errors;\n const hasNoErrors = !Array.isArray(errors) || errors.length === 0;\n const isValidationSuccess = responseBody && responseCode === 0 && hasNoErrors;\n\n if (!isValidationSuccess) {\n const message = this._formatValidationFailureMessage(\n 'Merchant validation returned an unsuccessful response',\n response.status,\n responseBody\n );\n\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n message,\n {\n endpoint: validationUrl,\n status: response.status,\n response: responseBody\n }\n );\n }\n\n logger.log('[Dropp SDK] Merchant credentials validated successfully');\n }\n\n /**\n * Close payment modal programmatically\n */\n closePayment() {\n if (this.isOpen) {\n if (this.currentFlowType === 'page') {\n this._cleanup();\n return;\n }\n this._handleCancel('sdk_close');\n }\n }\n\n /**\n * Open the dashboard/home page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @param {string[]} [options.modules] - Optional sidebar module IDs for firsttimeflow route\n * @returns {Promise<{status: string, route: string}>}\n */\n dashboard(options = {}) {\n return this._openHostedPage('/firsttimeflow', options);\n }\n\n /**\n * Open a specific supported module page in the Dropp modal.\n * @param {string} moduleId - Supported firsttimeflow item module ID\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n open(moduleId, options = {}) {\n const normalizedModuleId = typeof moduleId === 'string' ? moduleId.trim() : '';\n\n if (!normalizedModuleId) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'moduleId is required for Dropp.open(moduleId)',\n { moduleId }\n );\n }\n\n if (!SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS.includes(normalizedModuleId)) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Unsupported moduleId passed to Dropp.open(moduleId)',\n {\n moduleId: normalizedModuleId,\n supportedModuleIds: [...SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS]\n }\n );\n }\n\n const route = normalizedModuleId === 'about' ? '/aboutus' : `/${normalizedModuleId}`;\n return this._openHostedPage(route, options);\n }\n\n /**\n * Open the unlink account page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n unlinkAccount(options = {}) {\n return this._openHostedPage('/unlink', options);\n }\n\n /**\n * Open the transactions page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n transactions(options = {}) {\n return this._openHostedPage('/transactions', options);\n }\n\n /**\n * Open the offers page in the Dropp modal.\n * @param {Object} [options] - Hosted page options\n * @param {Function} [options.onClose] - Callback for modal close\n * @returns {Promise<{status: string, route: string}>}\n */\n offers(options = {}) {\n return this._openHostedPage('/offers', options);\n }\n\n /**\n * Get account status using a hidden iframe flow.\n * @returns {Promise<{type: string, data: {linked: boolean, method: string}}>} \n */\n status() {\n return new Promise((resolve, reject) => {\n if (this.isOpen || this.currentFlowType) {\n reject(\n createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A Dropp session is already in progress',\n { currentSession: this.currentSession, currentFlowType: this.currentFlowType }\n )\n );\n return;\n }\n\n (async () => {\n try {\n // Lock immediately to prevent races while initialize() is in-flight.\n this.currentFlowType = 'status';\n\n await this.initialize();\n this.currentSession = null;\n this.onSuccess = null;\n this.onFailure = null;\n this.onCancel = null;\n this.onClose = null;\n\n this.messageHandler = new MessageHandler(\n this.environment,\n this._handleMessage.bind(this),\n this.allowedOrigins\n );\n\n const iframe = document.createElement('iframe');\n iframe.id = 'dropp-status-iframe';\n iframe.setAttribute('allow', 'payment');\n iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups');\n iframe.setAttribute('referrerpolicy', 'no-referrer');\n iframe.setAttribute('title', 'Dropp Account Status');\n\n Object.assign(iframe.style, {\n position: 'absolute',\n width: '1px',\n height: '1px',\n border: '0',\n opacity: '0',\n pointerEvents: 'none',\n visibility: 'hidden'\n });\n\n document.body.appendChild(iframe);\n this.hiddenIframe = iframe;\n\n this.messageHandler.init(iframe);\n\n const queryParams = new URLSearchParams({\n sdkMode: 'true',\n sessionId: this.messageHandler.getSessionId(),\n sdkVersion: SDK_VERSION,\n platform: 'web',\n merchantDomain: this.hostAppDomain\n });\n\n const hostedAuthToken = this._getHostedPageAuthToken();\n if (hostedAuthToken) {\n queryParams.set('auth', hostedAuthToken);\n }\n\n const normalizedBaseUrl = this.baseUrl.replace(/\\/+$/, '');\n iframe.src = `${normalizedBaseUrl}/#/status?${queryParams.toString()}`;\n\n this.statusSession = {\n resolve,\n reject,\n startTime: Date.now()\n };\n\n this.statusTimeout = setTimeout(() => {\n const error = createError(\n ERROR_CODES.INIT_TIMEOUT,\n 'Account status request timed out',\n {\n type: 'status',\n sessionDuration: this.statusSession\n ? Date.now() - this.statusSession.startTime\n : 0\n }\n );\n\n if (this.statusSession) {\n this.statusSession.reject(error);\n }\n\n this._cleanup();\n }, TIMEOUTS.INIT);\n } catch (error) {\n reject(\n createError(\n ERROR_CODES.UNKNOWN_ERROR,\n 'Failed to get account status',\n { originalError: error?.message || String(error) }\n )\n );\n this._cleanup();\n }\n })();\n });\n }\n\n /**\n * Initialize payment session\n * @private\n */\n async _initializePayment(options) {\n logger.log('[Dropp SDK] Initializing payment session');\n this.currentFlowType = 'payment';\n\n // Create message handler\n this.messageHandler = new MessageHandler(\n this.environment,\n this._handleMessage.bind(this),\n this.allowedOrigins\n );\n\n // Create modal manager\n this.modalManager = new ModalManager(\n this._handleModalClose.bind(this)\n );\n\n // Open modal and get iframe\n const iframe = this.modalManager.open();\n if (!iframe) {\n throw new Error('Failed to create modal iframe');\n }\n\n // Initialize message handler with iframe\n this.messageHandler.init(iframe);\n\n // Determine payment route based on type\n const paymentType = options.paymentType || PAYMENT_TYPES.STANDARD;\n let route = '/payViaUrl';\n if (paymentType === PAYMENT_TYPES.PREAUTH) {\n route = '/preAuthPayment';\n } else if (paymentType === PAYMENT_TYPES.RECURRING) {\n route = '/recurringPayment';\n }\n\n // Build payment parameters (matching Android SDK)\n // For recurring payments with frequency NONE, use maxAmount instead of fixAmount\n const recurringFrequency = paymentType === PAYMENT_TYPES.RECURRING \n ? (options.frequency || options.recurringInterval || '').toString().trim().toUpperCase()\n : '';\n const isRecurringNone = paymentType === PAYMENT_TYPES.RECURRING && recurringFrequency === 'NONE';\n const detectedAppUrl =\n options.appUrl ||\n (typeof window !== 'undefined' && window.location ? window.location.href : undefined);\n \n const params = {\n merchantAccount: this.merchantId,\n amount: paymentType === PAYMENT_TYPES.PREAUTH ? undefined : options.amount,\n maxAmount: (paymentType === PAYMENT_TYPES.PREAUTH || isRecurringNone) ? options.amount : undefined,\n fixAmount: (paymentType === PAYMENT_TYPES.RECURRING && !isRecurringNone) ? options.amount : undefined,\n acceptPaymentDelay:\n paymentType === PAYMENT_TYPES.STANDARD && options.acceptPaymentDelay === true\n ? true\n : undefined,\n currency: options.currency,\n itemName: options.itemName,\n description: options.description,\n invoiceId: options.invoiceId || `INV-${Date.now()}`,\n invoiceType: paymentType === PAYMENT_TYPES.PREAUTH ? 'PREAUTH' : undefined,\n apiKey: this.apiKey,\n packageName: this.hostAppDomain,\n merchantDomain: this.hostAppDomain,\n sdkVersion: SDK_VERSION,\n platform: 'web',\n appUrl: detectedAppUrl,\n sessionId: this.messageHandler.getSessionId() // Include SDK session ID for message validation\n };\n\n if (paymentType === PAYMENT_TYPES.STANDARD) {\n if (options.displayItems !== undefined) {\n params.displayItems = options.displayItems;\n }\n if (options.metaData !== undefined) {\n params.metaData = options.metaData;\n }\n }\n \n logger.log('[Dropp SDK] Including SDK session context in payment params');\n\n // Add optional parameters\n if (options.successURL) params.successURL = options.successURL;\n if (options.failureURL) params.failureURL = options.failureURL;\n \n // Recurring payment specific fields\n if (paymentType === PAYMENT_TYPES.RECURRING) {\n const frequency = options.frequency || options.recurringInterval;\n if (frequency) params.frequency = frequency;\n if (options.recurringEndDate) params.expiry = options.recurringEndDate;\n }\n \n // Pre-auth specific fields\n if (paymentType === PAYMENT_TYPES.PREAUTH && options.authHoldTimeInSeconds) {\n params.authHoldTimeInSeconds = options.authHoldTimeInSeconds;\n }\n \n // Callback URL for server-side submission\n if (options.callbackUrl) {\n params.url = options.callbackUrl;\n params.submitToCallBack = 'post';\n }\n\n const authContext = {\n sessionId: params.sessionId,\n merchantAccount: this.merchantId,\n amount: options.amount,\n paymentType,\n invoiceId: params.invoiceId,\n expiry: options.recurringEndDate || null,\n issuedAt: Date.now()\n };\n\n let serverAuthToken =\n typeof options.serverAuthToken === 'string'\n ? options.serverAuthToken.trim()\n : '';\n\n if (!serverAuthToken && this.getServerAuthToken) {\n try {\n const tokenFromCallback = await this.getServerAuthToken(authContext);\n serverAuthToken = typeof tokenFromCallback === 'string'\n ? tokenFromCallback.trim()\n : '';\n } catch (error) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Failed to obtain server auth token',\n {\n originalError: error?.message || String(error)\n }\n );\n }\n }\n\n if (this.requireServerAuthToken && !serverAuthToken) {\n throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'serverAuthToken is required. Provide options.serverAuthToken or config.getServerAuthToken.',\n {\n environment: this.environment,\n paymentType,\n invoiceId: params.invoiceId\n }\n );\n }\n\n // Build payment URL with base64 payload and optional server-issued auth token.\n const paymentUrl = await buildPaymentUrl(\n this.baseUrl,\n route,\n params,\n SDK_VERSION,\n { serverAuthToken }\n );\n\n logger.log('[Dropp SDK] Loading payment flow iframe');\n\n // Load payment app in iframe\n iframe.src = paymentUrl;\n\n this.isOpen = true;\n\n // Set initialization timeout\n this.initTimeout = setTimeout(() => {\n this._handleTimeout('init');\n }, TIMEOUTS.INIT);\n\n // Set payment timeout\n this.paymentTimeout = setTimeout(() => {\n this._handleTimeout('payment');\n }, TIMEOUTS.PAYMENT);\n }\n\n /**\n * Open a hosted Dropp page in the modal.\n * @private\n */\n async _openHostedPage(route, options = {}) {\n if (this.currentFlowType === 'status') {\n throw createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A Dropp session is already in progress',\n { currentSession: this.currentSession, currentFlowType: this.currentFlowType, route }\n );\n }\n\n if (this.isOpen) {\n if (this.currentFlowType === 'page') {\n this._cleanup();\n } else {\n throw createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A Dropp session is already in progress',\n { currentSession: this.currentSession, route }\n );\n }\n }\n\n await this.initialize();\n\n this.currentFlowType = 'page';\n this.currentSession = null;\n this.onSuccess = null;\n this.onFailure = typeof options.onFailed === 'function' ? options.onFailed : null;\n this.onCancel = typeof options.onCancel === 'function' ? options.onCancel : null;\n this.onClose = typeof options.onClose === 'function' ? options.onClose : null;\n this.onAccountChanged =\n typeof options.onAccountChanged === 'function' ? options.onAccountChanged : null;\n this.onPageFailed =\n typeof options.onPageFailed === 'function' ? options.onPageFailed : this.onFailure;\n\n this.messageHandler = new MessageHandler(\n this.environment,\n this._handleMessage.bind(this),\n this.allowedOrigins\n );\n\n this.modalManager = new ModalManager(\n this._handleModalClose.bind(this)\n );\n\n const iframe = this.modalManager.open();\n if (!iframe) {\n throw new Error('Failed to create modal iframe');\n }\n\n this.messageHandler.init(iframe);\n\n const queryParams = new URLSearchParams({\n sdkMode: 'true',\n sessionId: this.messageHandler.getSessionId(),\n sdkVersion: SDK_VERSION,\n platform: 'web',\n merchantDomain: this.hostAppDomain\n });\n\n const hostedAuthToken = this._getHostedPageAuthToken();\n if (hostedAuthToken) {\n queryParams.set('auth', hostedAuthToken);\n }\n\n // firsttimeflow-only sidebar filtering config.\n if (route === '/firsttimeflow' && Array.isArray(options.modules)) {\n const modules = options.modules\n .map(module => (typeof module === 'string' ? module.trim() : ''))\n .filter(Boolean);\n\n if (modules.length > 0) {\n queryParams.set('modules', modules.join(','));\n }\n }\n\n const normalizedBaseUrl = this.baseUrl.replace(/\\/+$/, '');\n iframe.src = `${normalizedBaseUrl}/#${route}?${queryParams.toString()}`;\n this.isOpen = true;\n\n logger.log('[Dropp SDK] Hosted page opened', { route });\n\n return {\n status: 'opened',\n route\n };\n }\n\n /**\n * Handle messages from payment app\n * @private\n */\n _handleMessage(message) {\n const { type, data } = message;\n\n switch (type) {\n case MESSAGE_TYPES.READY:\n this._handleReady(data);\n break;\n\n case MESSAGE_TYPES.PAGE_LOADED:\n this._handlePageLoaded(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_PAGE_LOADED:\n this._handlePageLoaded(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_SUCCESS:\n this._handleSuccess(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_FAILED:\n this._handleFailure(data);\n break;\n\n case MESSAGE_TYPES.PAYMENT_CANCELLED:\n this._handleCancel('user_cancelled');\n break;\n\n case MESSAGE_TYPES.ACCOUNT_STATUS:\n this._handleAccountStatus(data);\n break;\n\n case MESSAGE_TYPES.ACCOUNT_EVENT:\n this._handleAccountEvent(data);\n break;\n\n case MESSAGE_TYPES.PAGE_EVENT:\n this._handlePageEvent(data);\n break;\n\n case MESSAGE_TYPES.AUTO_CLOSE_WEBVIEW:\n // Auto-close from payment app after success/failure countdown\n // Just close the modal without triggering callbacks (already called)\n logger.log('[Dropp SDK] AUTO_CLOSE_WEBVIEW received - closing modal');\n this._cleanup();\n logger.log('[Dropp SDK] Cleanup completed');\n break;\n\n case MESSAGE_TYPES.CLOSE_WEBVIEW:\n // Manual close request from chrome app\n logger.log('[Dropp SDK] CLOSE_WEBVIEW received from app - closing modal');\n if (this.currentFlowType === 'status' && this.statusSession) {\n const error = createError(\n ERROR_CODES.UNKNOWN_ERROR,\n 'Account status request was closed before response was received',\n {\n type: 'status',\n sessionDuration: Date.now() - this.statusSession.startTime\n }\n );\n this.statusSession.reject(error);\n this._cleanup();\n break;\n }\n this._handleCancel('app_close');\n break;\n\n default:\n logger.warn('[Dropp SDK] Unknown message type:', type);\n }\n }\n\n /**\n * Handle ready message from payment app\n * @private\n */\n _handleReady(data) {\n logger.log('[Dropp SDK] Payment app ready');\n \n // Clear init timeout\n if (this.initTimeout) {\n clearTimeout(this.initTimeout);\n this.initTimeout = null;\n }\n\n // Send init message to payment app\n // Filter out non-serializable data (functions) from options\n if (this.messageHandler && this.currentSession) {\n const serializableOptions = {};\n Object.keys(this.currentSession.options).forEach(key => {\n const value = this.currentSession.options[key];\n // Only include serializable values (exclude functions)\n if (typeof value !== 'function') {\n serializableOptions[key] = value;\n }\n });\n \n logger.log('[Dropp SDK] Sending init config to payment app');\n this.messageHandler.sendInit(serializableOptions);\n }\n }\n\n /**\n * Handle page loaded message\n * @private\n */\n _handlePageLoaded(data) {\n logger.log('[Dropp SDK] Payment page loaded');\n }\n\n /**\n * Resolve account/page delegate action from bridge payload.\n * @private\n */\n _getBridgeAction(data = {}) {\n if (!data || typeof data !== 'object') {\n return '';\n }\n\n if (typeof data.action === 'string') {\n return data.action;\n }\n\n if (data.result && typeof data.result === 'object' && typeof data.result.action === 'string') {\n return data.result.action;\n }\n\n return '';\n }\n\n /**\n * Resolve failure message safely.\n * @private\n */\n _getSafeFailureMessage(data = {}, fallback = 'Request failed') {\n if (data && typeof data.message === 'string' && data.message.trim()) {\n return data.message.trim();\n }\n\n if (\n data &&\n data.result &&\n typeof data.result === 'object' &&\n typeof data.result.message === 'string' &&\n data.result.message.trim()\n ) {\n return data.result.message.trim();\n }\n\n return fallback;\n }\n\n /**\n * Resolve result object safely.\n * @private\n */\n _getSafeResult(data = {}) {\n if (data && data.result && typeof data.result === 'object') {\n return data.result;\n }\n\n return {};\n }\n\n /**\n * Handle unified account delegate events.\n * @private\n */\n _handleAccountEvent(data) {\n const action = this._getBridgeAction(data);\n const result = this._getSafeResult(data);\n\n if (action === 'onAccountChanged') {\n if (this.onAccountChanged) {\n this.onAccountChanged({\n linked: result.linked === true,\n rawData: result.rawData\n });\n }\n return;\n }\n\n if (action === 'onCancel') {\n if (this.onCancel) {\n this.onCancel();\n }\n return;\n }\n\n if (action === 'onFailed') {\n const message = this._getSafeFailureMessage(data, 'Account request failed');\n if (this.onFailure) {\n this.onFailure(message);\n }\n return;\n }\n\n logger.warn('[Dropp SDK] Unknown ACCOUNT_EVENT action:', action);\n }\n\n /**\n * Handle page delegate events.\n * @private\n */\n _handlePageEvent(data) {\n const action = this._getBridgeAction(data);\n\n if (action === 'onFailed') {\n const message = this._getSafeFailureMessage(data, 'Page request failed');\n if (this.onPageFailed) {\n this.onPageFailed(message);\n }\n return;\n }\n\n logger.warn('[Dropp SDK] Unknown PAGE_EVENT action:', action);\n }\n\n /**\n * Handle account status response\n * @private\n */\n _handleAccountStatus(data) {\n logger.log('[Dropp SDK] Account status received');\n\n if (!this.statusSession) {\n logger.warn('[Dropp SDK] ACCOUNT_STATUS received without active status session');\n return;\n }\n\n this.statusSession.resolve({\n type: MESSAGE_TYPES.ACCOUNT_STATUS,\n data\n });\n\n this._cleanup();\n }\n\n /**\n * Handle successful payment\n * @private\n */\n _handleSuccess(data) {\n logger.log('[Dropp SDK] Payment successful');\n\n const result = {\n status: 'success',\n ...data,\n sessionDuration: Date.now() - this.currentSession.startTime\n };\n\n // Resolve promise\n if (this.currentSession) {\n this.currentSession.resolve(result);\n }\n\n // Invoke callback\n if (this.onSuccess) {\n this.onSuccess(result);\n }\n\n // Note: Modal will be closed by AUTO_CLOSE_WEBVIEW message from payment app\n // after the countdown completes (no need for timeout here)\n }\n\n /**\n * Handle failed payment\n * @private\n */\n _handleFailure(data) {\n logger.log('[Dropp SDK] Payment failed');\n\n const result = {\n status: 'failed',\n ...data,\n sessionDuration: Date.now() - this.currentSession.startTime\n };\n\n // Resolve promise (not reject - failed payment is still a valid result)\n if (this.currentSession) {\n this.currentSession.resolve(result);\n }\n\n // Invoke callback\n if (this.onFailure) {\n this.onFailure(result);\n }\n\n // Note: Modal will be closed by AUTO_CLOSE_WEBVIEW message from payment app\n // after the countdown completes (no need for timeout here)\n }\n\n /**\n * Handle cancelled payment\n * @private\n */\n _handleCancel(reason) {\n logger.log('[Dropp SDK] Payment cancelled');\n\n if (this.currentFlowType === 'page') {\n if (this.onCancel) {\n this.onCancel();\n }\n this._cleanup();\n return;\n }\n\n const result = {\n status: 'cancelled',\n reason,\n sessionDuration: this.currentSession ? Date.now() - this.currentSession.startTime : 0\n };\n\n // Resolve promise (not reject - cancellation is a valid result)\n if (this.currentSession) {\n this.currentSession.resolve(result);\n }\n\n // Invoke callback\n if (this.onCancel) {\n this.onCancel(result);\n }\n\n // Close immediately\n this._cleanup();\n }\n\n /**\n * Handle modal close by user\n * @private\n */\n _handleModalClose(reason) {\n logger.log('[Dropp SDK] Modal closed by user');\n if (this.currentFlowType === 'page') {\n this._cleanup();\n return;\n }\n this._handleCancel(reason);\n }\n\n /**\n * Handle timeout\n * @private\n */\n _handleTimeout(type) {\n logger.error('[Dropp SDK] Timeout:', type);\n\n const errorCode = type === 'init' ? ERROR_CODES.INIT_TIMEOUT : ERROR_CODES.PAYMENT_TIMEOUT;\n const errorMessage = type === 'init' \n ? 'Payment app failed to load within timeout period'\n : 'Payment session timed out';\n\n const error = createError(errorCode, errorMessage, {\n type,\n sessionDuration: this.currentSession ? Date.now() - this.currentSession.startTime : 0\n });\n\n // Reject promise\n if (this.currentSession) {\n this.currentSession.reject(error);\n }\n\n // Invoke failure callback\n if (this.onFailure) {\n this.onFailure({ status: 'failed', error });\n }\n\n this._cleanup();\n }\n\n /**\n * Cleanup resources\n * @private\n */\n _cleanup() {\n logger.log('[Dropp SDK] ๐Ÿงน Cleaning up session - starting cleanup');\n\n // Clear timeouts\n if (this.initTimeout) {\n clearTimeout(this.initTimeout);\n this.initTimeout = null;\n }\n\n if (this.paymentTimeout) {\n clearTimeout(this.paymentTimeout);\n this.paymentTimeout = null;\n }\n\n if (this.statusTimeout) {\n clearTimeout(this.statusTimeout);\n this.statusTimeout = null;\n }\n\n // Destroy managers\n if (this.messageHandler) {\n logger.log('[Dropp SDK] ๐Ÿงน Destroying message handler');\n this.messageHandler.destroy();\n this.messageHandler = null;\n }\n\n if (this.modalManager) {\n logger.log('[Dropp SDK] ๐Ÿงน Closing modal manager');\n this.modalManager.close();\n logger.log('[Dropp SDK] ๐Ÿงน Modal manager closed');\n this.modalManager = null;\n }\n\n if (this.hiddenIframe && this.hiddenIframe.parentNode) {\n this.hiddenIframe.parentNode.removeChild(this.hiddenIframe);\n }\n this.hiddenIframe = null;\n\n // Clear state\n this.currentSession = null;\n this.statusSession = null;\n this.currentFlowType = null;\n this.isOpen = false;\n\n // Invoke onClose callback\n if (this.onClose) {\n this.onClose();\n }\n }\n\n /**\n * Get SDK version\n */\n static getVersion() {\n return SDK_VERSION;\n }\n\n /**\n * Get available environments\n */\n static getEnvironments() {\n return { ...ENVIRONMENTS };\n }\n\n /**\n * Get payment types\n */\n static getPaymentTypes() {\n return { ...PAYMENT_TYPES };\n }\n}\n\nexport default DroppPaymentSDK;\n","/**\n * Dropp Payment SDK for Web\n * \n * Main entry point - exports SDK class and factory functions\n */\n\nimport { DroppPaymentSDK } from './DroppPaymentSDK.js';\nimport { ENVIRONMENTS, PAYMENT_TYPES } from './constants.js';\n\nconst DROPP_CONTEXT_MENU_GUARD_KEY = '__droppDisableContextMenuListener__';\n\nfunction disableContextMenuOnImport() {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (window[DROPP_CONTEXT_MENU_GUARD_KEY]) {\n return;\n }\n\n const contextMenuHandler = event => {\n event.preventDefault();\n event.stopPropagation();\n };\n\n document.addEventListener('contextmenu', contextMenuHandler, true);\n window[DROPP_CONTEXT_MENU_GUARD_KEY] = true;\n}\n\ndisableContextMenuOnImport();\n\n// Export main SDK class\nexport { DroppPaymentSDK };\n\n// Export constants\nexport { ENVIRONMENTS, PAYMENT_TYPES };\n\n// Global Dropp instance\nlet globalDroppInstance = null;\n\n/**\n * Factory function to create and initialize SDK instance\n * @param {Object} config - SDK configuration\n * @param {string} config.merchantId - Merchant Hedera account ID (required, e.g., '0.0.123456')\n * @param {string} config.apiKey - API Key (required)\n * @param {string} config.packageName - Package name (required)\n * @param {string} config.environment - Environment: 'production', 'qa', or 'sandbox'\n * @returns {Promise<{status: string, code: string, message: string, sdk: DroppPaymentSDK}>}\n */\nexport async function createPaymentSDK(config) {\n globalDroppInstance = new DroppPaymentSDK(config);\n const initResult = await globalDroppInstance.initialize();\n return {\n ...initResult,\n sdk: globalDroppInstance\n };\n}\n\n/**\n * Get the global Dropp instance\n * @returns {DroppPaymentSDK|null}\n */\nexport function getDroppInstance() {\n return globalDroppInstance;\n}\n\n/**\n * Global Dropp object with pay method\n */\nexport const Dropp = {\n /**\n * Initialize SDK (sets global instance)\n * @param {Object} config - SDK configuration\n * @returns {Promise<{status: string, code: string, message: string, sdk: DroppPaymentSDK}>}\n */\n init(config) {\n return createPaymentSDK(config);\n },\n \n /**\n * Make a payment using the initialized SDK\n * @param {Object} options - Payment options\n * @returns {Promise<PaymentResult>}\n */\n pay(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.pay(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.pay(options);\n },\n\n /**\n * Open the dashboard/home page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @param {string[]} [options.modules] - Optional sidebar module IDs to show in firsttimeflow\n * @returns {Promise<{status: string, route: string}>}\n */\n dashboard(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.dashboard(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.dashboard(options);\n },\n\n /**\n * Open a supported firsttimeflow module page in the initialized SDK modal\n * @param {string} moduleId - Supported firsttimeflow item module ID\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n open(moduleId, options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.open(moduleId, options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.open(moduleId, options);\n },\n\n /**\n * Open the unlink account page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n unlinkAccount(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.unlinkAccount(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.unlinkAccount(options);\n },\n\n /**\n * Open the transactions page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n transactions(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.transactions(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.transactions(options);\n },\n\n /**\n * Open the offers page in the initialized SDK modal\n * @param {Object} [options] - Hosted page options\n * @returns {Promise<{status: string, route: string}>}\n */\n offers(options) {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.offers(options).');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.offers(options);\n },\n\n /**\n * Fetch account status via hidden iframe\n * @returns {Promise<{type: string, data: {linked: boolean, method: string}}>} \n */\n status() {\n if (!globalDroppInstance) {\n const error = new Error('Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.status().');\n error.code = 'SDK_NOT_INITIALIZED';\n throw error;\n }\n return globalDroppInstance.status();\n },\n \n /**\n * Get the current SDK instance\n * @returns {DroppPaymentSDK|null}\n */\n getInstance() {\n return globalDroppInstance;\n }\n};\n\n// Default export\nexport default {\n DroppPaymentSDK,\n createPaymentSDK,\n Dropp,\n ENVIRONMENTS,\n PAYMENT_TYPES\n};\n"],"names":["MESSAGE_TYPES","READY","PAYMENT_SUCCESS","PAYMENT_FAILED","PAYMENT_CANCELLED","ACCOUNT_EVENT","PAGE_EVENT","ACCOUNT_STATUS","CLOSE_WEBVIEW","AUTO_CLOSE_WEBVIEW","PAYMENT_PAGE_LOADED","PAGE_LOADED","SDK_MESSAGE_TYPES","ENVIRONMENTS","PRODUCTION","QA","SANDBOX","PAYMENT_APP_URLS","ALLOWED_ORIGINS","TIMEOUTS","PAYMENT_TYPES","STANDARD","PREAUTH","RECURRING","ERROR_CODES","SDK_VERSION","logger","constructor","environment","options","this","forceEnabled","enabled","_shouldEnableLogging","setEnvironment","setEnabled","log","args","console","warn","error","debug","info","SUPPORTED_CURRENCIES","RECURRING_FREQUENCY_VALUES","PAYMENT_TYPE_VALUES","DISPLAY_ITEM_TYPES","DISPLAY_ITEM_REQUIRED_KEYS","isValidCallbackUrl","url","isProduction","allowLocalCallbacksInNonProd","trim","parsed","URL","isHttps","protocol","hostname","normalized","toLowerCase","endsWith","test","octets","split","map","part","Number","some","octet","isNaN","a","b","isPrivateOrLoopbackHost","encodeBase64UrlUtf8","value","input","String","TextEncoder","bytes","encode","binary","forEach","byte","fromCharCode","btoa","unescape","encodeURIComponent","encodeBase64Utf8","replace","validateConfig","config","errors","paymentType","normalizedCurrency","currency","toUpperCase","includes","push","join","undefined","amount","num","parseFloat","isPositiveNumber","itemName","displayItems","displayItemsError","Array","isArray","i","length","item","Object","keys","every","key","prototype","hasOwnProperty","call","label","normalizedValue","numericValue","isFinite","type","validateDisplayItemsArray","metaData","JSON","stringify","isValidJsonObject","callbackUrl","authHoldTimeInSeconds","parseInt","isInteger","isPositiveInteger","frequency","recurringInterval","toString","recurringEndDate","date","Date","getTime","isValidIsoDateTime","valid","createError","code","message","details","timestamp","toISOString","MessageHandler","onMessage","allowedOrigins","sessionId","now","Math","random","substring","iframe","messageListener","pendingMessages","Map","init","_handleMessage","bind","window","addEventListener","destroy","removeEventListener","clear","event","source","_validateOrigin","origin","contentWindow","eventOrigin","data","_validateMessageStructure","_processMessage","startsWith","values","sendToPaymentApp","sdkVersion","targetOrigin","postMessage","sendInit","mode","sendClose","getSessionId","ModalManager","onClose","overlay","container","closeButton","isOpen","escapeListener","open","_createModal","_attachEventListeners","_show","close","_hide","_removeEventListeners","_destroyModal","document","createElement","id","_applyOverlayStyles","_applyContainerStyles","setAttribute","_applyIframeStyles","appendChild","body","element","assign","style","position","inset","width","height","margin","padding","boxSizing","backgroundColor","zIndex","display","alignItems","justifyContent","opacity","transition","backdropFilter","overflow","isMobile","innerWidth","_isMobile","flex","alignSelf","maxWidth","minHeight","maxHeight","borderRadius","boxShadow","transform","flexDirection","_getContainerTransform","scale","_applyCloseButtonStyles","top","right","border","color","fontSize","lineHeight","cursor","fontFamily","requestAnimationFrame","setTimeout","parentNode","removeChild","_handleCloseClick","stopPropagation","_handleOverlayClick","target","_handleEscapeKey","getIframe","getIsOpen","SUPPORTED_FIRSTTIMEFLOW_MODULE_IDS","DroppPaymentSDK","Error","merchantId","apiKey","baseUrl","paymentAppUrl","isInitialized","initializationPromise","getServerAuthToken","requireServerAuthToken","currentSession","currentFlowType","statusSession","hiddenIframe","statusTimeout","initTimeout","paymentTimeout","hostAppDomain","onAccountChanged","onPageFailed","messageHandler","modalManager","debugLogging","pay","Promise","resolve","reject","initialize","validation","validationMessage","onSuccess","onFailure","onCancel","startTime","_initializePayment","sdkError","originalError","_cleanup","_detectHostAppDomain","_validateInitializationCredentials","status","catch","_getValidationUrl","validationUrls","location","_getHostedPageAuthToken","merchantAccount","apikey","_formatValidationFailureMessage","baseMessage","responseBody","parts","responseCodeRaw","responseCode","reason","firstError","validationUrl","merchantDomain","headers","accept","response","fetch","method","endpoint","json","ok","hasNoErrors","closePayment","_handleCancel","dashboard","_openHostedPage","moduleId","normalizedModuleId","supportedModuleIds","route","unlinkAccount","transactions","offers","pointerEvents","visibility","queryParams","URLSearchParams","sdkMode","platform","hostedAuthToken","set","normalizedBaseUrl","src","sessionDuration","_handleModalClose","recurringFrequency","isRecurringNone","detectedAppUrl","appUrl","href","params","maxAmount","fixAmount","acceptPaymentDelay","description","invoiceId","invoiceType","packageName","successURL","failureURL","expiry","submitToCallBack","authContext","issuedAt","serverAuthToken","tokenFromCallback","paymentUrl","async","authOptions","payload","base64Payload","sdkTs","buildPaymentUrl","_handleTimeout","onFailed","modules","module","filter","Boolean","_handleReady","_handlePageLoaded","_handleSuccess","_handleFailure","_handleAccountStatus","_handleAccountEvent","_handlePageEvent","clearTimeout","serializableOptions","_getBridgeAction","action","result","_getSafeFailureMessage","fallback","_getSafeResult","linked","rawData","getVersion","getEnvironments","getPaymentTypes","DROPP_CONTEXT_MENU_GUARD_KEY","preventDefault","disableContextMenuOnImport","globalDroppInstance","createPaymentSDK","sdk","getDroppInstance","Dropp","getInstance","index"],"mappings":"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"}