@dropp.cc/payment-sdk 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,337 @@
1
+ # Dropp Payment SDK for Web
2
+
3
+ A secure, production-ready JavaScript SDK for integrating Dropp payments into web applications.
4
+
5
+ ## Features
6
+
7
+ - ๐Ÿ”’ **Secure** - Origin validation, message authentication, session correlation
8
+ - ๐ŸŽฏ **Framework-agnostic** - Works with React, Vue, Angular.
9
+ - ๐Ÿ“ฑ **Responsive** - Optimized for desktop and mobile browsers
10
+ - โšก **Lightweight** - Minimal bundle size, no dependencies
11
+ - ๐Ÿ“ฆ **TypeScript** - Full TypeScript definitions included
12
+
13
+
14
+ ## Installation
15
+
16
+ Install the SDK using npm:
17
+
18
+ ```bash
19
+ npm install @dropp/payment-sdk
20
+ ```
21
+
22
+ ## Initialization
23
+
24
+ ### `Dropp.init(config)`
25
+
26
+ Initializes the SDK with the required configuration.
27
+
28
+ **Parameters:**
29
+
30
+ - `config` (Object):
31
+ - `merchantId` (String) **Required**: Your Dropp merchant identifier, Will get from Dropp Merchant Portal after KYC.
32
+ - `apiKey` (String) **Required**: API key issued for your merchant, Will get from Dropp Merchant Portal after KYC.
33
+ - `packageName` (String) **Required**: Your app/package name (for example, `app.dropp.cc`), will need to update in your account on the Dropp Merchant Portal.
34
+ - `environment` (String) **Required**: The environment to use. Options: `'production'`, `'qa'`, `'sandbox'`.
35
+
36
+
37
+ ### Example:
38
+
39
+ ```javascript
40
+ Dropp.init({
41
+ merchantId: 'YOUR_MERCHANT_ID',
42
+ apiKey: 'YOUR_API_KEY',
43
+ packageName: 'com.example.webapp',
44
+ environment: 'production',
45
+ });
46
+ ```
47
+
48
+ ## Payment
49
+
50
+ ### `Dropp.pay(options)`
51
+
52
+ Initiates a payment process.
53
+
54
+ **Parameters:**
55
+
56
+ - `options` (Object):
57
+ - `merchantAccount` (String) **Required**: The merchant's Hedera account ID (e.g., `'0.0.123456'`).
58
+ - `amount` (Number) **Required**: The payment amount.
59
+ - `currency` (String) **Required**: The currency code (e.g., `'USD'`, `'HBAR'`, `'USDC'`). For `paymentType: 'preauth'`, only `'USD'` is allowed.
60
+ - `itemName` (String) **Required**: The name of the item or service.
61
+ - `paymentType` (String) **Required**: The type of payment. Options: `'standard'`, `'preauth'`, `'recurring'`.
62
+ - `authHoldTimeInSeconds` (Number) **Required in Preauth Payments**: For preauth payments, the hold time in seconds.
63
+ - `callbackUrl` (String) **Required in Preauth & Recurring**: The server URL on which the PreAuth and Recurring requests will be send for signing.
64
+ - `recurringEndDate` (ISO datetime) **Optional in Recurring Payments**: The date on which the recurring authorization will expire.
65
+
66
+ ### Example:
67
+
68
+ ```javascript
69
+ Dropp.pay({
70
+ merchantAccount: '0.0.123456',
71
+ amount: 100.00,
72
+ currency: 'USD',
73
+ itemName: 'Premium Subscription',
74
+ paymentType: 'standard',
75
+ callbackUrl: 'https://example.com/callback'
76
+ });
77
+ ```
78
+
79
+ ## Environments
80
+
81
+ The SDK supports the following environments:
82
+
83
+ - `'production'`: For live transactions.
84
+ - `'qa'`: For quality assurance testing.
85
+ - `'sandbox'`: For development and testing.
86
+
87
+ Ensure you use the appropriate environment for your use case.
88
+
89
+
90
+ ```javascript
91
+ import '@dropp/payment-sdk';
92
+
93
+ Dropp.init({
94
+ merchantId: 'YOUR_MERCHANT_ID',
95
+ apiKey: 'YOUR_API_KEY',
96
+ packageName: 'com.example.webapp',
97
+ environment: 'sandbox' // For testing payments (testnet)
98
+ });
99
+
100
+ Dropp.init({
101
+ merchantId: 'YOUR_MERCHANT_ID',
102
+ apiKey: 'YOUR_API_KEY',
103
+ packageName: 'com.example.webapp',
104
+ environment: 'qa' // For QA
105
+ });
106
+
107
+ Dropp.init({
108
+ merchantId: 'YOUR_MERCHANT_ID',
109
+ apiKey: 'YOUR_API_KEY',
110
+ packageName: 'com.example.webapp',
111
+ environment: 'production' // For live payments (mainnet)
112
+ });
113
+ ```
114
+
115
+ ## Payment Examples
116
+
117
+ ### Standard Payment
118
+
119
+ ```javascript
120
+ Dropp.pay({
121
+ merchantAccount: '0.0.123456',
122
+ amount: 49.99,
123
+ currency: 'USD',
124
+ itemName: 'Premium Plan',
125
+ description: 'One-time purchase',
126
+ invoiceId: 'INV-2024-001'
127
+ });
128
+ ```
129
+
130
+ ### Pre-Authorization Payment
131
+
132
+ ```javascript
133
+ Dropp.pay({
134
+ merchantAccount: '0.0.123456',
135
+ amount: 100.00,
136
+ currency: 'USD',
137
+ itemName: 'Hotel Reservation',
138
+ description: 'Authorization hold for booking',
139
+ invoiceId: 'PREAUTH-001',
140
+ paymentType: 'preauth',
141
+ authHoldTimeInSeconds: 3600, // 1 hour hold
142
+ callbackUrl: 'https://your-server.com/payment-callback'
143
+ });
144
+ ```
145
+
146
+ ### Recurring Payment
147
+
148
+ ```javascript
149
+ Dropp.pay({
150
+ merchantAccount: '0.0.123456',
151
+ amount: 9.99,
152
+ currency: 'USD',
153
+ itemName: 'Monthly Subscription',
154
+ description: 'Recurring monthly payment',
155
+ paymentType: 'recurring',
156
+ frequency: 'monthly', // Frequency of the recurring payment
157
+ recurringEndDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(), // (optional) the date onwhich the recurring authentication will end.
158
+ callbackUrl: 'https://your-server.com/recurring-callback'
159
+ });
160
+ ```
161
+ ### React Integration
162
+
163
+ ```jsx
164
+ import { useEffect, useState } from 'react';
165
+ import { Dropp } from '@dropp/payment-sdk';
166
+
167
+ function CheckoutButton() {
168
+ const [isProcessing, setIsProcessing] = useState(false);
169
+
170
+ useEffect(() => {
171
+ Dropp.init({
172
+ merchantId: 'YOUR_MERCHANT_ID',
173
+ apiKey: 'YOUR_API_KEY',
174
+ packageName: 'com.example.webapp',
175
+ environment: 'production'
176
+ });
177
+ }, []);
178
+
179
+ const handlePayment = async () => {
180
+ setIsProcessing(true);
181
+
182
+ try {
183
+ const result = await Dropp.pay({
184
+ merchantAccount: '0.0.123456',
185
+ amount: 99.99,
186
+ currency: 'USD',
187
+ itemName: 'Product Purchase',
188
+ paymentType: 'standard'
189
+ });
190
+
191
+ if (result.status === 'success') {
192
+ alert('Payment successful!');
193
+ }
194
+ } catch (error) {
195
+ console.error('Payment error:', error);
196
+ } finally {
197
+ setIsProcessing(false);
198
+ }
199
+ };
200
+
201
+ return (
202
+ <button onClick={handlePayment} disabled={isProcessing}>
203
+ {isProcessing ? 'Processing...' : 'Pay Now'}
204
+ </button>
205
+ );
206
+ }
207
+ ```
208
+
209
+
210
+ ### Vanilla JavaScript Integration
211
+
212
+ Use this when you are not using React/Vue/Angular.
213
+
214
+ ```html
215
+ <!doctype html>
216
+ <html>
217
+ <head>
218
+ <meta charset="utf-8" />
219
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
220
+ <title>Dropp Vanilla JS Example</title>
221
+ </head>
222
+ <body>
223
+ <button id="payStandard">Pay Standard</button>
224
+ <button id="payPreauth">Pay Preauth</button>
225
+ <button id="payRecurring">Pay Recurring</button>
226
+
227
+ <script src="https://unpkg.com/@dropp/payment-sdk/dist/dropp-payment-sdk.js"></script>
228
+ <script>
229
+ const { Dropp } = window.DroppPaymentSDK;
230
+
231
+ Dropp.init({
232
+ merchantId: 'YOUR_MERCHANT_ID',
233
+ apiKey: 'YOUR_API_KEY',
234
+ packageName: 'app.dropp.cc',
235
+ environment: 'production'
236
+ });
237
+
238
+ document.getElementById('payStandard').addEventListener('click', async () => {
239
+ await Dropp.pay({
240
+ merchantAccount: '0.0.123456',
241
+ amount: 49.99,
242
+ currency: 'USD',
243
+ itemName: 'One-time Purchase',
244
+ paymentType: 'standard'
245
+ });
246
+ });
247
+
248
+ document.getElementById('payPreauth').addEventListener('click', async () => {
249
+ await Dropp.pay({
250
+ merchantAccount: '0.0.123456',
251
+ amount: 100.00,
252
+ currency: 'USD',
253
+ itemName: 'Hotel Reservation',
254
+ paymentType: 'preauth',
255
+ authHoldTimeInSeconds: 3600,
256
+ callbackUrl: 'https://your-server.com/payment-callback'
257
+ });
258
+ });
259
+
260
+ document.getElementById('payRecurring').addEventListener('click', async () => {
261
+ await Dropp.pay({
262
+ merchantAccount: '0.0.123456',
263
+ amount: 9.99,
264
+ currency: 'USD',
265
+ itemName: 'Monthly Subscription',
266
+ paymentType: 'recurring',
267
+ frequency: 'monthly',
268
+ recurringEndDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(),
269
+ callbackUrl: 'https://your-server.com/recurring-callback'
270
+ });
271
+ });
272
+ </script>
273
+ </body>
274
+ </html>
275
+ ```
276
+
277
+ ## Security
278
+
279
+ The SDK implements multiple security layers:
280
+
281
+ โœ… **Origin Validation** - Strict validation of postMessage origins
282
+ โœ… **Session Correlation** - Each session has a unique ID to prevent replay attacks
283
+ โœ… **Message Authentication** - All messages are validated for structure and content
284
+ โœ… **Iframe Sandboxing** - Payment app runs in a sandboxed iframe
285
+ โœ… **No Sensitive Data** - SDK never handles sensitive payment data directly
286
+ โœ… **Secure Communication** - All data transmission uses HTTPS
287
+
288
+ ### Security Best Practices
289
+
290
+ 1. **Never expose secrets in frontend code**
291
+ 2. **Use server-side callbacks** for payment verification
292
+ 3. **Validate payments on your backend** using the `callbackUrl`
293
+ 4. **Use invoice IDs** to track and deduplicate payments
294
+ 5. **Implement proper error handling**
295
+
296
+ ## Browser Support
297
+
298
+ - Chrome 90+
299
+ - Firefox 88+
300
+ - Safari 14+
301
+ - Edge 90+
302
+
303
+ ## Troubleshooting
304
+
305
+ ### Payment modal doesn't open
306
+
307
+ - Check browser console for errors
308
+ - Verify all required fields are provided
309
+ - Ensure `merchantAccount` format is correct (`"0.0.123456"`)
310
+
311
+ ### Messages not received
312
+
313
+ - Check that you're using the correct environment
314
+ - Verify origin validation isn't blocking legitimate messages
315
+ - Check browser console for message validation errors
316
+
317
+ ### TypeScript errors
318
+
319
+ - Ensure you have `@dropp/payment-sdk` installed
320
+ - If you use TypeScript types, import them from `@dropp/payment-sdk`
321
+
322
+ ## Support
323
+
324
+ For issues or questions:
325
+ - Email: support@dropp.cc
326
+
327
+
328
+ MIT License - see LICENSE file for details
329
+
330
+ ## Changelog
331
+
332
+ ### v1.0.0 (2026-06-01)
333
+ - Initial release
334
+ - Standard, preauth, and recurring payment support
335
+ - Secure postMessage communication
336
+ - Framework-agnostic design
337
+ - Full TypeScript definitions
@@ -0,0 +1,2 @@
1
+ const e={READY:"DROPP_SDK_READY",PAYMENT_SUCCESS:"PAYMENT_SUCCESS",PAYMENT_FAILED:"PAYMENT_FAILED",PAYMENT_CANCELLED:"PAYMENT_CANCELLED",CLOSE_WEBVIEW:"CLOSE_WEBVIEW",AUTO_CLOSE_WEBVIEW:"AUTO_CLOSE_WEBVIEW",PAYMENT_PAGE_LOADED:"PAYMENT_PAGE_LOADED"},t="DROPP_SDK_INIT",i="DROPP_SDK_CLOSE",n={PRODUCTION:"production",QA:"qa",SANDBOX:"sandbox"},s={[n.PRODUCTION]:"https://wv.pay.dropp.cc",[n.QA]:"https://wv.qa.dropp.cc",[n.SANDBOX]:"https://wv.sandbox.dropp.cc"},a={[n.PRODUCTION]:["https://pay.dropp.cc"],[n.QA]:["https://wv.qa.dropp.cc"],[n.SANDBOX]:["https://wv.sandbox.dropp.cc"]},r=3e4,o=6e5,l={STANDARD:"standard",PREAUTH:"preauth",RECURRING:"recurring"},c="INIT_TIMEOUT",d="PAYMENT_TIMEOUT",h="INVALID_CONFIG",p="ALREADY_OPEN",u="UNKNOWN_ERROR",m="1.0.0";const g=new class{constructor(e){this.environment=e,this.enabled=this._shouldEnableLogging()}_shouldEnableLogging(){const e=this.environment?.toLowerCase()||"";return"prod"!==e&&"production"!==e}setEnvironment(e){this.environment=e,this.enabled=this._shouldEnableLogging()}log(...e){this.enabled&&console.log(...e)}warn(...e){this.enabled&&console.warn(...e)}error(...e){this.enabled&&console.error(...e)}debug(...e){this.enabled&&console.debug(...e)}info(...e){this.enabled&&console.info(...e)}}("qa"),y=["USD","HBAR","USDC"],f=["NONE","HALF_HOURLY","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],D=[l.STANDARD,l.PREAUTH,l.RECURRING];function S(e){if("string"!=typeof e||!e.trim())return!1;try{const t=new URL(e.trim());return"http:"===t.protocol||"https:"===t.protocol}catch{return!1}}async function E(e,t,i,n){try{const s={};Object.keys(i).forEach(e=>{const t=i[e];null!=t&&(s[e]=t)}),g.log("[buildPaymentUrl] ๐Ÿ”‘ Payload with sessionId:",s),console.log("[buildPaymentUrl] ๐Ÿ”‘ Full payload being encoded:",s);const a=JSON.stringify(s),r=btoa(a).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"");console.log("[buildPaymentUrl] ๐Ÿ”‘ Base64 payload:",r);const o=Date.now().toString(),l=await async function(e,t,i){try{const n=`${e}.${i}`,s=`${t}.${i}`,a=new TextEncoder,r=a.encode(n),o=a.encode(s),l=await crypto.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),c=await crypto.subtle.sign("HMAC",l,o);return btoa(String.fromCharCode(...new Uint8Array(c))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}catch(e){return g.error("Error generating SDK auth:",e),""}}(i.merchantAccount,r,o),c=`${e}/#${t}?pay=${r}&sdkAuth=${l}&sdkTs=${o}&sdkVersion=${n}&platform=web`;return console.log("[buildPaymentUrl] ๐Ÿ”‘ Final URL:",c),c}catch(e){throw g.error("Error building payment URL:",e),e}}function v(e={}){const t=[],i=e.paymentType||l.STANDARD,n="string"==typeof e.currency?e.currency.trim().toUpperCase():"";if(D.includes(i)||t.push(`paymentType must be one of: ${D.join(", ")}`),void 0===e.amount||null===e.amount||""===e.amount?t.push("amount is required"):function(e){const t="number"==typeof e?e:parseFloat(e);return"number"==typeof t&&!Number.isNaN(t)&&t>0}(e.amount)||t.push("amount must be a positive number"),e.currency&&"string"==typeof e.currency&&e.currency.trim()?y.includes(n)||t.push(`currency must be one of: ${y.join(", ")}`):t.push("currency is required"),e.itemName&&"string"==typeof e.itemName&&e.itemName.trim()||t.push("itemName is required"),i===l.PREAUTH&&(n&&"USD"!==n&&t.push("currency must be USD for preauth payments"),e.callbackUrl&&String(e.callbackUrl).trim()?S(e.callbackUrl)||t.push("callbackUrl must be a valid HTTP or HTTPS URL"):t.push("callbackUrl (signing URL) is required for preauth payments"),void 0===e.authHoldTimeInSeconds||null===e.authHoldTimeInSeconds||""===e.authHoldTimeInSeconds?t.push("authHoldTimeInSeconds is required for preauth payments"):function(e){const t="number"==typeof e?e:parseInt(e,10);return Number.isInteger(t)&&t>0}(e.authHoldTimeInSeconds)||t.push("authHoldTimeInSeconds must be a positive integer (seconds)")),i===l.RECURRING){e.callbackUrl&&String(e.callbackUrl).trim()?S(e.callbackUrl)||t.push("callbackUrl must be a valid HTTP or HTTPS URL"):t.push("callbackUrl (signing URL) is required for recurring payments");const i=(e.frequency||e.recurringInterval||"").toString().trim().toUpperCase();i?f.includes(i)||t.push(`frequency must be one of: ${f.join(", ")}`):t.push("frequency is required for recurring payments"),e.recurringEndDate&&String(e.recurringEndDate).trim()?!function(e){if("string"!=typeof e||!e.trim())return!1;const t=new Date(e.trim());return!Number.isNaN(t.getTime())}(e.recurringEndDate)?t.push("recurringEndDate must be a valid ISO date-time string"):new Date(e.recurringEndDate.trim())<=new Date&&t.push("recurringEndDate must be in the future"):t.push("recurringEndDate (expiry) is required for recurring payments")}return{valid:0===t.length,errors:t}}function w(e,t,i={}){return{code:e,message:t,details:i,timestamp:(new Date).toISOString(),toString(){return this.message||"Dropp SDK error"}}}class b{constructor(e,t,i=null){this.environment=e,this.onMessage=t,this.sessionId=`dropp-sdk-${Date.now()}-${Math.random().toString(36).substring(2,15)}`,g.log("[MessageHandler] ๐Ÿ”‘ Generated sessionId:",this.sessionId),console.log("[MessageHandler] ๐Ÿ”‘ Generated sessionId:",this.sessionId),this.iframe=null,this.allowedOrigins=i?.length>0?i:a[e]||[],this.messageListener=null,this.pendingMessages=new Map}init(e){this.iframe=e,this.messageListener=this._handleMessage.bind(this),window.addEventListener("message",this.messageListener)}destroy(){this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.iframe=null,this.pendingMessages.clear()}_handleMessage(e){if(g.log("[MessageHandler DEBUG] Received message:",{origin:e.origin,source:e.source,iframeContentWindow:this.iframe?.contentWindow,sourceMatches:e.source===this.iframe?.contentWindow,data:e.data}),e.source===window)return void g.log("[MessageHandler DEBUG] Ignoring message from self");if(!this._validateOrigin(e.origin))return void g.warn("[Dropp SDK] Rejected message from untrusted origin:",e.origin);if(!this.iframe||e.source!==this.iframe.contentWindow)return void g.warn("[Dropp SDK] Rejected message from unexpected source",{hasIframe:!!this.iframe,hasContentWindow:!!this.iframe?.contentWindow,sourceMatches:e.source===this.iframe?.contentWindow,eventOrigin:e.origin,expectedOrigin:this.allowedOrigins});const t=e.data;this._validateMessageStructure(t)?t.sessionId&&t.sessionId!==this.sessionId?g.warn("[Dropp SDK] Rejected message with invalid session ID",{expected:this.sessionId,received:t.sessionId}):(g.log("[MessageHandler DEBUG] โœ… Message passed all validation, processing:",t.type),this._processMessage(t)):g.warn("[Dropp SDK] Rejected message with invalid structure:",t)}_validateOrigin(e){return!(!e.startsWith("http://localhost:")&&!e.startsWith("http://127.0.0.1:"))||this.allowedOrigins.some(t=>e===t||e.startsWith(t))}_validateMessageStructure(t){if(!t||"object"!=typeof t)return!1;if(!t.type||"string"!=typeof t.type)return!1;return!!Object.values(e).includes(t.type)&&!!t.timestamp}_processMessage(e){g.log("[Dropp SDK] Received message:",e.type,e),this.onMessage&&this.onMessage(e)}sendToPaymentApp(e,t={}){if(!this.iframe||!this.iframe.contentWindow)return g.error("[Dropp SDK] Cannot send message: iframe not ready"),!1;const i={type:e,data:t,sessionId:this.sessionId,timestamp:(new Date).toISOString(),sdkVersion:"1.0.0"},n=this.allowedOrigins[0]||"*";try{return this.iframe.contentWindow.postMessage(i,n),g.log("[Dropp SDK] Sent message:",e,i),!0}catch(e){return g.error("[Dropp SDK] Error sending message:",e),!1}}sendInit(e){return this.sendToPaymentApp(t,{mode:"sdk",config:e})}sendClose(){return this.sendToPaymentApp(i,{})}getSessionId(){return this.sessionId}}class _{constructor(e){this.onClose=e,this.overlay=null,this.container=null,this.iframe=null,this.closeButton=null,this.isOpen=!1,this.escapeListener=null}open(){return this.isOpen?(g.warn("[Dropp SDK] Modal is already open"),null):(this._createModal(),this._attachEventListeners(),this._show(),this.isOpen=!0,this.iframe)}close(){g.log("[ModalManager] ๐Ÿšฆ close() called, isOpen:",this.isOpen),this.isOpen?(g.log("[ModalManager] ๐Ÿšฆ Hiding modal..."),this._hide(),g.log("[ModalManager] ๐Ÿšฆ Removing event listeners..."),this._removeEventListeners(),g.log("[ModalManager] ๐Ÿšฆ Destroying modal..."),this._destroyModal(),this.isOpen=!1,g.log("[ModalManager] โœ… Modal close sequence initiated")):g.log("[ModalManager] โš ๏ธ Modal is not open, skipping close")}_createModal(){this.overlay=document.createElement("div"),this.overlay.id="dropp-payment-overlay",this._applyOverlayStyles(this.overlay),this.container=document.createElement("div"),this.container.id="dropp-payment-container",this._applyContainerStyles(this.container),this.iframe=document.createElement("iframe"),this.iframe.id="dropp-payment-iframe",this.iframe.setAttribute("allow","payment"),this.iframe.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"),this.iframe.setAttribute("title","Dropp Payment"),this._applyIframeStyles(this.iframe),this.container.appendChild(this.iframe),this.overlay.appendChild(this.container),document.body.appendChild(this.overlay)}_applyOverlayStyles(e){Object.assign(e.style,{position:"fixed",inset:"0",width:"100vw",height:"100vh",margin:"0",padding:"20px",boxSizing:"border-box",backgroundColor:"rgba(0, 0, 0, 0.6)",zIndex:999999..toString(),display:"flex",alignItems:"center",justifyContent:"center",opacity:"0",transition:"opacity 0.3s ease",backdropFilter:"blur(4px)",overflow:"auto"})}_applyContainerStyles(e){const t=window.innerWidth<768;this._isMobile=t,Object.assign(e.style,{position:"relative",flex:"0 0 auto",alignSelf:"center",margin:"auto",width:"100%",maxWidth:t?"100%":"400px",height:t?"100%":"auto",minHeight:t?"100%":"800px",maxHeight:t?"100%":"min(1000px, calc(100vh - 40px))",backgroundColor:"#ffffff",borderRadius:t?"0":"16px",boxShadow:"0 20px 60px rgba(0, 0, 0, 0.3)",overflow:"hidden",transform:"scale(0.95)",transition:"transform 0.3s ease, opacity 0.3s ease",display:"flex",flexDirection:"column"})}_getContainerTransform(e){return`scale(${e})`}_applyCloseButtonStyles(e){Object.assign(e.style,{position:"absolute",top:"16px",right:"16px",zIndex:"10",width:"40px",height:"40px",border:"none",borderRadius:"50%",backgroundColor:"rgba(255, 255, 255, 0.9)",color:"#333",fontSize:"28px",lineHeight:"1",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.15)",transition:"all 0.2s ease",fontFamily:"Arial, sans-serif",padding:"0"}),e.addEventListener("mouseenter",()=>{Object.assign(e.style,{backgroundColor:"#f5f5f5",transform:"scale(1.1)"})}),e.addEventListener("mouseleave",()=>{Object.assign(e.style,{backgroundColor:"rgba(255, 255, 255, 0.9)",transform:"scale(1)"})})}_applyIframeStyles(e){const t=this._isMobile;Object.assign(e.style,{width:"100%",flex:"1 1 auto",minHeight:t?"100%":"min(520px, calc(90vh - 40px))",height:t?"100%":"min(520px, calc(90vh - 40px))",border:"none",display:"block"})}_show(){document.body.style.overflow="hidden",requestAnimationFrame(()=>{this.overlay&&(this.overlay.style.opacity="1"),this.container&&(this.container.style.transform=this._getContainerTransform(1))})}_hide(){g.log("[ModalManager] ๐ŸŽญ _hide() called"),this.overlay&&(this.overlay.style.opacity="0",g.log("[ModalManager] ๐ŸŽญ Overlay opacity set to 0")),this.container&&(this.container.style.transform=this._getContainerTransform(.95),g.log("[ModalManager] ๐ŸŽญ Container transform set to scale(0.95)")),document.body.style.overflow="",g.log("[ModalManager] ๐ŸŽญ Body scroll restored")}_destroyModal(){g.log("[ModalManager] ๐Ÿ—‘๏ธ _destroyModal() called, waiting 300ms for animation"),setTimeout(()=>{g.log("[ModalManager] ๐Ÿ—‘๏ธ Animation complete, removing from DOM"),this.overlay&&this.overlay.parentNode&&(this.overlay.parentNode.removeChild(this.overlay),g.log("[ModalManager] ๐Ÿ—‘๏ธ Overlay removed from DOM")),this.overlay=null,this.container=null,this.iframe=null,this.closeButton=null,g.log("[ModalManager] โœ… Modal destroyed")},300)}_attachEventListeners(){}_removeEventListeners(){this.escapeListener&&(document.removeEventListener("keydown",this.escapeListener),this.escapeListener=null)}_handleCloseClick(e){e.stopPropagation(),this.onClose&&this.onClose("user_closed")}_handleOverlayClick(e){e.target===this.overlay&&this.onClose&&this.onClose("user_closed")}_handleEscapeKey(e){"Escape"===e.key&&this.isOpen&&this.onClose&&this.onClose("user_closed")}getIframe(){return this.iframe}getIsOpen(){return this.isOpen}}class I{constructor(e={}){if("undefined"==typeof window||"undefined"==typeof document)throw new Error("Dropp Payment SDK can only be used in a browser environment");if(!e.merchantId||!e.apiKey||!e.packageName)throw new Error("merchantId, apiKey, and packageName are required to initialize SDK");if(this.merchantId=e.merchantId,this.apiKey=e.apiKey,this.packageName=e.packageName,this.environment=e.environment||n.QA,this.baseUrl=s[this.environment],this.isInitialized=!1,this.initializationPromise=null,e.allowedOrigins?.length)this.allowedOrigins=e.allowedOrigins;else if(e.paymentAppUrl||e.baseUrl)try{this.allowedOrigins=[new URL(this.baseUrl).origin]}catch{this.allowedOrigins=a[this.environment]||[]}else this.allowedOrigins=a[this.environment]||[];this.isOpen=!1,this.currentSession=null,this.initTimeout=null,this.paymentTimeout=null,this.messageHandler=null,this.modalManager=null,g.setEnvironment(this.environment),g.log(`[Dropp SDK] Initialized v${m} - Merchant: ${this.merchantId}, Environment: ${this.environment}`)}pay(e={}){return new Promise((t,i)=>{if(this.isOpen){const e=w(p,"A payment session is already in progress",{currentSession:this.currentSession});return void i(e)}(async()=>{try{await this.initialize();const n=v(e);if(!n.valid){const e=w(h,"Invalid payment configuration",{errors:n.errors});return void i(e)}this.onSuccess=e.onSuccess||null,this.onFailure=e.onFailure||null,this.onCancel=e.onCancel||null,this.onClose=e.onClose||null,this.currentSession={resolve:t,reject:i,options:e,startTime:Date.now()},await this._initializePayment(e)}catch(e){const t=e&&e.code===h?e:w(u,"Failed to initialize payment",{originalError:e?.message||String(e)});i(t),this._cleanup()}})()})}async initialize(){return this.initializationPromise||(this.initializationPromise=(async()=>(await this._validateInitializationCredentials(),this.isInitialized=!0,{status:"success",code:"INITIALIZED",message:"Dropp SDK initialized successfully"}))().catch(e=>{throw this.isInitialized=!1,this.initializationPromise=null,e})),this.initializationPromise}_getValidationUrl(){const e={[n.QA]:"https://main.qa.dropp.cc/payer/webview/validate",[n.SANDBOX]:"https://sandbox.dropp.cc/payer/webview/validate",[n.PRODUCTION]:"https://pay.dropp.cc/payer/webview/validate"};return e[this.environment]||e[n.QA]}async _validateInitializationCredentials(){const e=this._getValidationUrl();let t,i=null;try{t=await fetch(e,{method:"POST",headers:{accept:"application/json, text/plain, */*","content-type":"application/json","x-api-key":this.apiKey,"x-app-package":this.packageName},body:JSON.stringify({id:this.merchantId})})}catch(t){throw w(h,"Unable to validate merchant credentials",{endpoint:e,originalError:t?.message||String(t)})}try{i=await t.json()}catch{i=null}if(!t.ok)throw w(h,"Merchant validation failed for merchantId/apiKey/packageName",{endpoint:e,status:t.status,response:i});const n=Number(i?.responseCode),s=i?.errors,a=!Array.isArray(s)||0===s.length;if(!(i&&0===n&&a))throw w(h,"Merchant validation returned an unsuccessful response",{endpoint:e,status:t.status,response:i});g.log("[Dropp SDK] Merchant credentials validated successfully")}closePayment(){this.isOpen&&this._handleCancel("sdk_close")}async _initializePayment(e){g.log("[Dropp SDK] Initializing payment:",e),this.messageHandler=new b(this.environment,this._handleMessage.bind(this),this.allowedOrigins),this.modalManager=new _(this._handleModalClose.bind(this));const t=this.modalManager.open();if(!t)throw new Error("Failed to create modal iframe");this.messageHandler.init(t);const i=e.paymentType||l.STANDARD;let n="/payViaUrl";i===l.PREAUTH?n="/preAuthPayment":i===l.RECURRING&&(n="/recurringPayment");const s=i===l.RECURRING?(e.frequency||e.recurringInterval||"").toString().trim().toUpperCase():"",a=i===l.RECURRING&&"NONE"===s,c=e.appUrl||("undefined"!=typeof window&&window.location?window.location.href:void 0),d={merchantAccount:this.merchantId,amount:i===l.PREAUTH?void 0:e.amount,maxAmount:i===l.PREAUTH||a?e.amount:void 0,fixAmount:i!==l.RECURRING||a?void 0:e.amount,currency:e.currency,itemName:e.itemName,description:e.description,invoiceId:e.invoiceId||`INV-${Date.now()}`,invoiceType:i===l.PREAUTH?"PREAUTH":void 0,apiKey:this.apiKey,packageName:this.packageName,sdkVersion:m,platform:"web",appUrl:c,sessionId:this.messageHandler.getSessionId()};if(g.log("[Dropp SDK] ๐Ÿ”‘ Including sessionId in payment params:",d.sessionId),e.successURL&&(d.successURL=e.successURL),e.failureURL&&(d.failureURL=e.failureURL),i===l.RECURRING){const t=e.frequency||e.recurringInterval;t&&(d.frequency=t),e.recurringEndDate&&(d.expiry=e.recurringEndDate)}i===l.PREAUTH&&e.authHoldTimeInSeconds&&(d.authHoldTimeInSeconds=e.authHoldTimeInSeconds),e.callbackUrl&&(d.url=e.callbackUrl,d.submitToCallBack="post");const h=await E(this.baseUrl,n,d,m);g.log("[Dropp SDK] Loading payment URL:",h),t.src=h,this.isOpen=!0,this.initTimeout=setTimeout(()=>{this._handleTimeout("init")},r),this.paymentTimeout=setTimeout(()=>{this._handleTimeout("payment")},o)}_handleMessage(t){const{type:i,data:n}=t;switch(i){case e.READY:this._handleReady(n);break;case e.PAYMENT_PAGE_LOADED:this._handlePageLoaded(n);break;case e.PAYMENT_SUCCESS:this._handleSuccess(n);break;case e.PAYMENT_FAILED:this._handleFailure(n);break;case e.PAYMENT_CANCELLED:this._handleCancel("user_cancelled");break;case e.AUTO_CLOSE_WEBVIEW:g.log("[Dropp SDK] ๐Ÿ”” AUTO_CLOSE_WEBVIEW received - closing modal now"),this._cleanup(),g.log("[Dropp SDK] โœ… _cleanup() called");break;case e.CLOSE_WEBVIEW:g.log("[Dropp SDK] ๐Ÿ“ฑ CLOSE_WEBVIEW received from chrome app - closing modal"),this._handleCancel("app_close");break;default:g.warn("[Dropp SDK] Unknown message type:",i)}}_handleReady(e){if(g.log("[Dropp SDK] Payment app ready"),this.initTimeout&&(clearTimeout(this.initTimeout),this.initTimeout=null),this.messageHandler&&this.currentSession){const e={};Object.keys(this.currentSession.options).forEach(t=>{const i=this.currentSession.options[t];"function"!=typeof i&&(e[t]=i)}),g.log("[Dropp SDK] Sending serializable init config:",e),this.messageHandler.sendInit(e)}}_handlePageLoaded(e){g.log("[Dropp SDK] Payment page loaded")}_handleSuccess(e){g.log("[Dropp SDK] Payment successful:",e);const t={status:"success",...e,sessionDuration:Date.now()-this.currentSession.startTime};this.currentSession&&this.currentSession.resolve(t),this.onSuccess&&this.onSuccess(t)}_handleFailure(e){g.log("[Dropp SDK] Payment failed:",e);const t={status:"failed",...e,sessionDuration:Date.now()-this.currentSession.startTime};this.currentSession&&this.currentSession.resolve(t),this.onFailure&&this.onFailure(t)}_handleCancel(e){g.log("[Dropp SDK] Payment cancelled:",e);const t={status:"cancelled",reason:e,sessionDuration:this.currentSession?Date.now()-this.currentSession.startTime:0};this.currentSession&&this.currentSession.resolve(t),this.onCancel&&this.onCancel(t),this._cleanup()}_handleModalClose(e){g.log("[Dropp SDK] Modal closed by user:",e),this._handleCancel(e)}_handleTimeout(e){g.error("[Dropp SDK] Timeout:",e);const t=w("init"===e?c:d,"init"===e?"Payment app failed to load within timeout period":"Payment session timed out",{type:e,sessionDuration:this.currentSession?Date.now()-this.currentSession.startTime:0});this.currentSession&&this.currentSession.reject(t),this.onFailure&&this.onFailure({status:"failed",error:t}),this._cleanup()}_cleanup(){g.log("[Dropp SDK] ๐Ÿงน Cleaning up session - starting cleanup"),this.initTimeout&&(clearTimeout(this.initTimeout),this.initTimeout=null),this.paymentTimeout&&(clearTimeout(this.paymentTimeout),this.paymentTimeout=null),this.messageHandler&&(g.log("[Dropp SDK] ๐Ÿงน Destroying message handler"),this.messageHandler.destroy(),this.messageHandler=null),this.modalManager&&(g.log("[Dropp SDK] ๐Ÿงน Closing modal manager"),this.modalManager.close(),g.log("[Dropp SDK] ๐Ÿงน Modal manager closed"),this.modalManager=null),this.currentSession=null,this.isOpen=!1,this.onClose&&this.onClose()}static getVersion(){return m}static getEnvironments(){return{...n}}static getPaymentTypes(){return{...l}}}let T=null;async function M(e){T=new I(e);return{...await T.initialize(),sdk:T}}function C(){return T}const O={init:e=>M(e),pay(e){if(!T){const e=new Error("Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.pay(options).");throw e.code="SDK_NOT_INITIALIZED",e}return T.pay(e)},getInstance:()=>T};var A={DroppPaymentSDK:I,createPaymentSDK:M,Dropp:O,ENVIRONMENTS:n,PAYMENT_TYPES:l};export{O as Dropp,I as DroppPaymentSDK,n as ENVIRONMENTS,l as PAYMENT_TYPES,M as createPaymentSDK,A as default,C as getDroppInstance};
2
+ //# sourceMappingURL=dropp-payment-sdk.esm.js.map
@@ -0,0 +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 CLOSE_WEBVIEW: 'CLOSE_WEBVIEW',\n AUTO_CLOSE_WEBVIEW: 'AUTO_CLOSE_WEBVIEW',\n PAYMENT_PAGE_LOADED: 'PAYMENT_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.pay.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://pay.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.0';\n\n// SDK authentication credentials (default values, can be overridden in config)\nexport const DEFAULT_API_KEY = '<4b3a6dd3e007847d237cb206891cxxxx>';\nexport const DEFAULT_PACKAGE_NAME = '<app.dropp.com>';\n\n// CSS z-index for modal\nexport const MODAL_Z_INDEX = 999999;\n","/**\n * Logger utility for Dropp Payment SDK\n * Conditionally logs based on environment - enabled for qa/sandbox, disabled for prod\n */\n\nclass Logger {\n constructor(environment) {\n this.environment = environment;\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Determine if logging should be enabled based on environment\n * @private\n */\n _shouldEnableLogging() {\n const env = this.environment?.toLowerCase() || '';\n // Enable logging for qa, sandbox, dev, or local environments\n // Disable for prod/production\n return env !== 'prod' && env !== 'production';\n }\n\n /**\n * Update environment and recalculate logging state\n */\n setEnvironment(environment) {\n this.environment = environment;\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');\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 isValidHttpUrl(url) {\n if (typeof url !== 'string' || !url.trim()) {\n return false;\n }\n try {\n const parsed = new URL(url.trim());\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\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\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 * Generate HMAC-SHA256 signature for SDK authentication\n */\nexport async function generateSdkAuth(merchantAccount, base64Payload, timestamp) {\n try {\n const key = `${merchantAccount}.${timestamp}`;\n const message = `${base64Payload}.${timestamp}`;\n \n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const messageData = encoder.encode(message);\n \n // Import key for HMAC\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n \n // Generate HMAC\n const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);\n \n // Convert to base64 (URL-safe)\n const base64 = btoa(String.fromCharCode(...new Uint8Array(signature)))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n \n return base64;\n } catch (error) {\n logger.error('Error generating SDK auth:', error);\n return '';\n }\n}\n\n/**\n * Build payment URL with base64 payload (matching Android SDK pattern)\n */\nexport async function buildPaymentUrl(baseUrl, route, params, sdkVersion) {\n try {\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] ๐Ÿ”‘ Payload with sessionId:', payload);\n console.log('[buildPaymentUrl] ๐Ÿ”‘ Full payload being encoded:', payload);\n \n // Base64 encode payload (URL-safe, no padding)\n const jsonString = JSON.stringify(payload);\n const base64Payload = btoa(jsonString)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n \n console.log('[buildPaymentUrl] ๐Ÿ”‘ Base64 payload:', base64Payload);\n \n // Generate SDK authentication\n const timestamp = Date.now().toString();\n const sdkAuth = await generateSdkAuth(params.merchantAccount, base64Payload, timestamp);\n \n // Build URL with base64 payload\n const url = `${baseUrl}/#${route}?pay=${base64Payload}&sdkAuth=${sdkAuth}&sdkTs=${timestamp}&sdkVersion=${sdkVersion}&platform=web`;\n \n console.log('[buildPaymentUrl] ๐Ÿ”‘ Final URL:', url);\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 = {}) {\n const errors = [];\n const paymentType = config.paymentType || PAYMENT_TYPES.STANDARD;\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.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 (!isValidHttpUrl(config.callbackUrl)) {\n errors.push('callbackUrl must be a valid HTTP or HTTPS URL');\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 (!isValidHttpUrl(config.callbackUrl)) {\n errors.push('callbackUrl must be a valid HTTP or HTTPS URL');\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, ERROR_CODES } 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] ๐Ÿ”‘ Generated sessionId:', this.sessionId);\n console.log('[MessageHandler] ๐Ÿ”‘ Generated sessionId:', this.sessionId);\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 DEBUG] Received message:', {\n origin: event.origin,\n source: event.source,\n iframeContentWindow: this.iframe?.contentWindow,\n sourceMatches: event.source === this.iframe?.contentWindow,\n data: event.data\n });\n\n // Ignore messages from self (parent window)\n if (event.source === window) {\n logger.log('[MessageHandler DEBUG] 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 hasIframe: !!this.iframe,\n hasContentWindow: !!this.iframe?.contentWindow,\n sourceMatches: event.source === this.iframe?.contentWindow,\n eventOrigin: event.origin,\n expectedOrigin: this.allowedOrigins\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:', message);\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 expected: this.sessionId,\n received: message.sessionId\n });\n return;\n }\n\n // 5. Process valid message\n logger.log('[MessageHandler DEBUG] โœ… Message passed all validation, processing:', message.type);\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 return this.allowedOrigins.some(allowedOrigin => {\n return origin === allowedOrigin || origin.startsWith(allowedOrigin);\n });\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 // Must have timestamp\n if (!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, message);\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, message);\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 allow-popups-to-escape-sandbox');\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 validateConfig, \n createError, \n isBrowser \n} from './utils.js';\nimport logger from './logger.js';\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.packageName - Package name (required)\n * @param {string} config.environment - Environment: 'production', 'qa', or 'sandbox'\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 || !config.packageName) {\n throw new Error('merchantId, apiKey, and packageName are required to initialize SDK');\n }\n\n // Store credentials\n this.merchantId = config.merchantId;\n this.apiKey = config.apiKey;\n this.packageName = config.packageName;\n\n this.environment = config.environment || ENVIRONMENTS.QA;\n this.baseUrl =\n PAYMENT_APP_URLS[this.environment];\n\n // Initialization state\n this.isInitialized = false;\n this.initializationPromise = null;\n\n if (config.allowedOrigins?.length) {\n this.allowedOrigins = config.allowedOrigins;\n } else if (config.paymentAppUrl || config.baseUrl) {\n try {\n this.allowedOrigins = [new URL(this.baseUrl).origin];\n } catch {\n this.allowedOrigins = ALLOWED_ORIGINS[this.environment] || [];\n }\n } else {\n this.allowedOrigins = ALLOWED_ORIGINS[this.environment] || [];\n }\n\n // State\n this.isOpen = false;\n this.currentSession = null;\n this.initTimeout = null;\n this.paymentTimeout = null;\n\n // Managers\n this.messageHandler = null;\n this.modalManager = null;\n\n // Set logger environment\n logger.setEnvironment(this.environment);\n logger.log(`[Dropp SDK] Initialized v${SDK_VERSION} - Merchant: ${this.merchantId}, 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 {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 // Check if already open\n if (this.isOpen) {\n const error = createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A payment session is already in progress',\n { currentSession: this.currentSession }\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 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 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://main.qa.dropp.cc/payer/webview/validate',\n [ENVIRONMENTS.SANDBOX]: 'https://sandbox.dropp.cc/payer/webview/validate',\n [ENVIRONMENTS.PRODUCTION]: 'https://pay.dropp.cc/payer/webview/validate'\n };\n\n return (\n validationUrls[this.environment] ||\n validationUrls[ENVIRONMENTS.QA]\n );\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\n let response;\n let responseBody = null;\n try {\n response = await fetch(validationUrl, {\n method: 'POST',\n headers: {\n accept: 'application/json, text/plain, */*',\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n 'x-app-package': this.packageName\n },\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 throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Merchant validation failed for merchantId/apiKey/packageName',\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 throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Merchant validation returned an unsuccessful response',\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 this._handleCancel('sdk_close');\n }\n }\n\n /**\n * Initialize payment session\n * @private\n */\n async _initializePayment(options) {\n logger.log('[Dropp SDK] Initializing payment:', options);\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 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.packageName,\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 logger.log('[Dropp SDK] ๐Ÿ”‘ Including sessionId in payment params:', params.sessionId);\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 // Build payment URL with base64 payload (matching Android SDK pattern)\n const paymentUrl = await buildPaymentUrl(this.baseUrl, route, params, SDK_VERSION);\n\n logger.log('[Dropp SDK] Loading payment URL:', paymentUrl);\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 * 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.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.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 now');\n this._cleanup();\n logger.log('[Dropp SDK] โœ… _cleanup() called');\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 chrome app - closing modal');\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 serializable init config:', serializableOptions);\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 * Handle successful payment\n * @private\n */\n _handleSuccess(data) {\n logger.log('[Dropp SDK] Payment successful:', data);\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:', data);\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:', reason);\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:', reason);\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 // 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 // Clear state\n this.currentSession = 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\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 * 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","CLOSE_WEBVIEW","AUTO_CLOSE_WEBVIEW","PAYMENT_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","this","enabled","_shouldEnableLogging","env","toLowerCase","setEnvironment","log","args","console","warn","error","debug","info","SUPPORTED_CURRENCIES","RECURRING_FREQUENCY_VALUES","PAYMENT_TYPE_VALUES","isValidHttpUrl","url","trim","parsed","URL","protocol","async","buildPaymentUrl","baseUrl","route","params","sdkVersion","payload","Object","keys","forEach","key","value","jsonString","JSON","stringify","base64Payload","btoa","replace","timestamp","Date","now","toString","sdkAuth","merchantAccount","message","encoder","TextEncoder","keyData","encode","messageData","cryptoKey","crypto","subtle","importKey","name","hash","signature","sign","String","fromCharCode","Uint8Array","generateSdkAuth","validateConfig","config","errors","paymentType","normalizedCurrency","currency","toUpperCase","includes","push","join","undefined","amount","num","parseFloat","Number","isNaN","isPositiveNumber","itemName","callbackUrl","authHoldTimeInSeconds","parseInt","isInteger","isPositiveInteger","frequency","recurringInterval","recurringEndDate","date","getTime","isValidIsoDateTime","valid","length","createError","code","details","toISOString","MessageHandler","onMessage","allowedOrigins","sessionId","Math","random","substring","iframe","messageListener","pendingMessages","Map","init","_handleMessage","bind","window","addEventListener","destroy","removeEventListener","clear","event","origin","source","iframeContentWindow","contentWindow","sourceMatches","data","_validateOrigin","hasIframe","hasContentWindow","eventOrigin","expectedOrigin","_validateMessageStructure","expected","received","type","_processMessage","startsWith","some","allowedOrigin","values","sendToPaymentApp","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","DroppPaymentSDK","Error","merchantId","apiKey","packageName","isInitialized","initializationPromise","paymentAppUrl","currentSession","initTimeout","paymentTimeout","messageHandler","modalManager","pay","options","Promise","resolve","reject","initialize","validation","onSuccess","onFailure","onCancel","startTime","_initializePayment","sdkError","originalError","_cleanup","_validateInitializationCredentials","status","catch","_getValidationUrl","validationUrls","validationUrl","response","responseBody","fetch","method","headers","accept","endpoint","json","ok","responseCode","hasNoErrors","Array","isArray","closePayment","_handleCancel","_handleModalClose","recurringFrequency","isRecurringNone","detectedAppUrl","appUrl","location","href","maxAmount","fixAmount","description","invoiceId","invoiceType","platform","successURL","failureURL","expiry","submitToCallBack","paymentUrl","src","_handleTimeout","_handleReady","_handlePageLoaded","_handleSuccess","_handleFailure","clearTimeout","serializableOptions","result","sessionDuration","reason","getVersion","getEnvironments","getPaymentTypes","globalDroppInstance","createPaymentSDK","sdk","getDroppInstance","Dropp","getInstance","index"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DroppPaymentSDK={})}(this,function(e){"use strict";const t={READY:"DROPP_SDK_READY",PAYMENT_SUCCESS:"PAYMENT_SUCCESS",PAYMENT_FAILED:"PAYMENT_FAILED",PAYMENT_CANCELLED:"PAYMENT_CANCELLED",CLOSE_WEBVIEW:"CLOSE_WEBVIEW",AUTO_CLOSE_WEBVIEW:"AUTO_CLOSE_WEBVIEW",PAYMENT_PAGE_LOADED:"PAYMENT_PAGE_LOADED"},n="DROPP_SDK_INIT",i="DROPP_SDK_CLOSE",s={PRODUCTION:"production",QA:"qa",SANDBOX:"sandbox"},a={[s.PRODUCTION]:"https://wv.pay.dropp.cc",[s.QA]:"https://wv.qa.dropp.cc",[s.SANDBOX]:"https://wv.sandbox.dropp.cc"},r={[s.PRODUCTION]:["https://pay.dropp.cc"],[s.QA]:["https://wv.qa.dropp.cc"],[s.SANDBOX]:["https://wv.sandbox.dropp.cc"]},o=3e4,l=6e5,c={STANDARD:"standard",PREAUTH:"preauth",RECURRING:"recurring"},d="INIT_TIMEOUT",p="PAYMENT_TIMEOUT",h="INVALID_CONFIG",u="ALREADY_OPEN",m="UNKNOWN_ERROR",g="1.0.0";const y=new class{constructor(e){this.environment=e,this.enabled=this._shouldEnableLogging()}_shouldEnableLogging(){const e=this.environment?.toLowerCase()||"";return"prod"!==e&&"production"!==e}setEnvironment(e){this.environment=e,this.enabled=this._shouldEnableLogging()}log(...e){this.enabled&&console.log(...e)}warn(...e){this.enabled&&console.warn(...e)}error(...e){this.enabled&&console.error(...e)}debug(...e){this.enabled&&console.debug(...e)}info(...e){this.enabled&&console.info(...e)}}("qa"),f=["USD","HBAR","USDC"],D=["NONE","HALF_HOURLY","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],S=[c.STANDARD,c.PREAUTH,c.RECURRING];function E(e){if("string"!=typeof e||!e.trim())return!1;try{const t=new URL(e.trim());return"http:"===t.protocol||"https:"===t.protocol}catch{return!1}}async function v(e,t,n,i){try{const s={};Object.keys(n).forEach(e=>{const t=n[e];null!=t&&(s[e]=t)}),y.log("[buildPaymentUrl] ๐Ÿ”‘ Payload with sessionId:",s),console.log("[buildPaymentUrl] ๐Ÿ”‘ Full payload being encoded:",s);const a=JSON.stringify(s),r=btoa(a).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"");console.log("[buildPaymentUrl] ๐Ÿ”‘ Base64 payload:",r);const o=Date.now().toString(),l=await async function(e,t,n){try{const i=`${e}.${n}`,s=`${t}.${n}`,a=new TextEncoder,r=a.encode(i),o=a.encode(s),l=await crypto.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),c=await crypto.subtle.sign("HMAC",l,o);return btoa(String.fromCharCode(...new Uint8Array(c))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}catch(e){return y.error("Error generating SDK auth:",e),""}}(n.merchantAccount,r,o),c=`${e}/#${t}?pay=${r}&sdkAuth=${l}&sdkTs=${o}&sdkVersion=${i}&platform=web`;return console.log("[buildPaymentUrl] ๐Ÿ”‘ Final URL:",c),c}catch(e){throw y.error("Error building payment URL:",e),e}}function w(e={}){const t=[],n=e.paymentType||c.STANDARD,i="string"==typeof e.currency?e.currency.trim().toUpperCase():"";if(S.includes(n)||t.push(`paymentType must be one of: ${S.join(", ")}`),void 0===e.amount||null===e.amount||""===e.amount?t.push("amount is required"):function(e){const t="number"==typeof e?e:parseFloat(e);return"number"==typeof t&&!Number.isNaN(t)&&t>0}(e.amount)||t.push("amount must be a positive number"),e.currency&&"string"==typeof e.currency&&e.currency.trim()?f.includes(i)||t.push(`currency must be one of: ${f.join(", ")}`):t.push("currency is required"),e.itemName&&"string"==typeof e.itemName&&e.itemName.trim()||t.push("itemName is required"),n===c.PREAUTH&&(i&&"USD"!==i&&t.push("currency must be USD for preauth payments"),e.callbackUrl&&String(e.callbackUrl).trim()?E(e.callbackUrl)||t.push("callbackUrl must be a valid HTTP or HTTPS URL"):t.push("callbackUrl (signing URL) is required for preauth payments"),void 0===e.authHoldTimeInSeconds||null===e.authHoldTimeInSeconds||""===e.authHoldTimeInSeconds?t.push("authHoldTimeInSeconds is required for preauth payments"):function(e){const t="number"==typeof e?e:parseInt(e,10);return Number.isInteger(t)&&t>0}(e.authHoldTimeInSeconds)||t.push("authHoldTimeInSeconds must be a positive integer (seconds)")),n===c.RECURRING){e.callbackUrl&&String(e.callbackUrl).trim()?E(e.callbackUrl)||t.push("callbackUrl must be a valid HTTP or HTTPS URL"):t.push("callbackUrl (signing URL) is required for recurring payments");const n=(e.frequency||e.recurringInterval||"").toString().trim().toUpperCase();n?D.includes(n)||t.push(`frequency must be one of: ${D.join(", ")}`):t.push("frequency is required for recurring payments"),e.recurringEndDate&&String(e.recurringEndDate).trim()?!function(e){if("string"!=typeof e||!e.trim())return!1;const t=new Date(e.trim());return!Number.isNaN(t.getTime())}(e.recurringEndDate)?t.push("recurringEndDate must be a valid ISO date-time string"):new Date(e.recurringEndDate.trim())<=new Date&&t.push("recurringEndDate must be in the future"):t.push("recurringEndDate (expiry) is required for recurring payments")}return{valid:0===t.length,errors:t}}function b(e,t,n={}){return{code:e,message:t,details:n,timestamp:(new Date).toISOString(),toString(){return this.message||"Dropp SDK error"}}}class _{constructor(e,t,n=null){this.environment=e,this.onMessage=t,this.sessionId=`dropp-sdk-${Date.now()}-${Math.random().toString(36).substring(2,15)}`,y.log("[MessageHandler] ๐Ÿ”‘ Generated sessionId:",this.sessionId),console.log("[MessageHandler] ๐Ÿ”‘ Generated sessionId:",this.sessionId),this.iframe=null,this.allowedOrigins=n?.length>0?n:r[e]||[],this.messageListener=null,this.pendingMessages=new Map}init(e){this.iframe=e,this.messageListener=this._handleMessage.bind(this),window.addEventListener("message",this.messageListener)}destroy(){this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.iframe=null,this.pendingMessages.clear()}_handleMessage(e){if(y.log("[MessageHandler DEBUG] Received message:",{origin:e.origin,source:e.source,iframeContentWindow:this.iframe?.contentWindow,sourceMatches:e.source===this.iframe?.contentWindow,data:e.data}),e.source===window)return void y.log("[MessageHandler DEBUG] Ignoring message from self");if(!this._validateOrigin(e.origin))return void y.warn("[Dropp SDK] Rejected message from untrusted origin:",e.origin);if(!this.iframe||e.source!==this.iframe.contentWindow)return void y.warn("[Dropp SDK] Rejected message from unexpected source",{hasIframe:!!this.iframe,hasContentWindow:!!this.iframe?.contentWindow,sourceMatches:e.source===this.iframe?.contentWindow,eventOrigin:e.origin,expectedOrigin:this.allowedOrigins});const t=e.data;this._validateMessageStructure(t)?t.sessionId&&t.sessionId!==this.sessionId?y.warn("[Dropp SDK] Rejected message with invalid session ID",{expected:this.sessionId,received:t.sessionId}):(y.log("[MessageHandler DEBUG] โœ… Message passed all validation, processing:",t.type),this._processMessage(t)):y.warn("[Dropp SDK] Rejected message with invalid structure:",t)}_validateOrigin(e){return!(!e.startsWith("http://localhost:")&&!e.startsWith("http://127.0.0.1:"))||this.allowedOrigins.some(t=>e===t||e.startsWith(t))}_validateMessageStructure(e){if(!e||"object"!=typeof e)return!1;if(!e.type||"string"!=typeof e.type)return!1;return!!Object.values(t).includes(e.type)&&!!e.timestamp}_processMessage(e){y.log("[Dropp SDK] Received message:",e.type,e),this.onMessage&&this.onMessage(e)}sendToPaymentApp(e,t={}){if(!this.iframe||!this.iframe.contentWindow)return y.error("[Dropp SDK] Cannot send message: iframe not ready"),!1;const n={type:e,data:t,sessionId:this.sessionId,timestamp:(new Date).toISOString(),sdkVersion:"1.0.0"},i=this.allowedOrigins[0]||"*";try{return this.iframe.contentWindow.postMessage(n,i),y.log("[Dropp SDK] Sent message:",e,n),!0}catch(e){return y.error("[Dropp SDK] Error sending message:",e),!1}}sendInit(e){return this.sendToPaymentApp(n,{mode:"sdk",config:e})}sendClose(){return this.sendToPaymentApp(i,{})}getSessionId(){return this.sessionId}}class I{constructor(e){this.onClose=e,this.overlay=null,this.container=null,this.iframe=null,this.closeButton=null,this.isOpen=!1,this.escapeListener=null}open(){return this.isOpen?(y.warn("[Dropp SDK] Modal is already open"),null):(this._createModal(),this._attachEventListeners(),this._show(),this.isOpen=!0,this.iframe)}close(){y.log("[ModalManager] ๐Ÿšฆ close() called, isOpen:",this.isOpen),this.isOpen?(y.log("[ModalManager] ๐Ÿšฆ Hiding modal..."),this._hide(),y.log("[ModalManager] ๐Ÿšฆ Removing event listeners..."),this._removeEventListeners(),y.log("[ModalManager] ๐Ÿšฆ Destroying modal..."),this._destroyModal(),this.isOpen=!1,y.log("[ModalManager] โœ… Modal close sequence initiated")):y.log("[ModalManager] โš ๏ธ Modal is not open, skipping close")}_createModal(){this.overlay=document.createElement("div"),this.overlay.id="dropp-payment-overlay",this._applyOverlayStyles(this.overlay),this.container=document.createElement("div"),this.container.id="dropp-payment-container",this._applyContainerStyles(this.container),this.iframe=document.createElement("iframe"),this.iframe.id="dropp-payment-iframe",this.iframe.setAttribute("allow","payment"),this.iframe.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"),this.iframe.setAttribute("title","Dropp Payment"),this._applyIframeStyles(this.iframe),this.container.appendChild(this.iframe),this.overlay.appendChild(this.container),document.body.appendChild(this.overlay)}_applyOverlayStyles(e){Object.assign(e.style,{position:"fixed",inset:"0",width:"100vw",height:"100vh",margin:"0",padding:"20px",boxSizing:"border-box",backgroundColor:"rgba(0, 0, 0, 0.6)",zIndex:999999..toString(),display:"flex",alignItems:"center",justifyContent:"center",opacity:"0",transition:"opacity 0.3s ease",backdropFilter:"blur(4px)",overflow:"auto"})}_applyContainerStyles(e){const t=window.innerWidth<768;this._isMobile=t,Object.assign(e.style,{position:"relative",flex:"0 0 auto",alignSelf:"center",margin:"auto",width:"100%",maxWidth:t?"100%":"400px",height:t?"100%":"auto",minHeight:t?"100%":"800px",maxHeight:t?"100%":"min(1000px, calc(100vh - 40px))",backgroundColor:"#ffffff",borderRadius:t?"0":"16px",boxShadow:"0 20px 60px rgba(0, 0, 0, 0.3)",overflow:"hidden",transform:"scale(0.95)",transition:"transform 0.3s ease, opacity 0.3s ease",display:"flex",flexDirection:"column"})}_getContainerTransform(e){return`scale(${e})`}_applyCloseButtonStyles(e){Object.assign(e.style,{position:"absolute",top:"16px",right:"16px",zIndex:"10",width:"40px",height:"40px",border:"none",borderRadius:"50%",backgroundColor:"rgba(255, 255, 255, 0.9)",color:"#333",fontSize:"28px",lineHeight:"1",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.15)",transition:"all 0.2s ease",fontFamily:"Arial, sans-serif",padding:"0"}),e.addEventListener("mouseenter",()=>{Object.assign(e.style,{backgroundColor:"#f5f5f5",transform:"scale(1.1)"})}),e.addEventListener("mouseleave",()=>{Object.assign(e.style,{backgroundColor:"rgba(255, 255, 255, 0.9)",transform:"scale(1)"})})}_applyIframeStyles(e){const t=this._isMobile;Object.assign(e.style,{width:"100%",flex:"1 1 auto",minHeight:t?"100%":"min(520px, calc(90vh - 40px))",height:t?"100%":"min(520px, calc(90vh - 40px))",border:"none",display:"block"})}_show(){document.body.style.overflow="hidden",requestAnimationFrame(()=>{this.overlay&&(this.overlay.style.opacity="1"),this.container&&(this.container.style.transform=this._getContainerTransform(1))})}_hide(){y.log("[ModalManager] ๐ŸŽญ _hide() called"),this.overlay&&(this.overlay.style.opacity="0",y.log("[ModalManager] ๐ŸŽญ Overlay opacity set to 0")),this.container&&(this.container.style.transform=this._getContainerTransform(.95),y.log("[ModalManager] ๐ŸŽญ Container transform set to scale(0.95)")),document.body.style.overflow="",y.log("[ModalManager] ๐ŸŽญ Body scroll restored")}_destroyModal(){y.log("[ModalManager] ๐Ÿ—‘๏ธ _destroyModal() called, waiting 300ms for animation"),setTimeout(()=>{y.log("[ModalManager] ๐Ÿ—‘๏ธ Animation complete, removing from DOM"),this.overlay&&this.overlay.parentNode&&(this.overlay.parentNode.removeChild(this.overlay),y.log("[ModalManager] ๐Ÿ—‘๏ธ Overlay removed from DOM")),this.overlay=null,this.container=null,this.iframe=null,this.closeButton=null,y.log("[ModalManager] โœ… Modal destroyed")},300)}_attachEventListeners(){}_removeEventListeners(){this.escapeListener&&(document.removeEventListener("keydown",this.escapeListener),this.escapeListener=null)}_handleCloseClick(e){e.stopPropagation(),this.onClose&&this.onClose("user_closed")}_handleOverlayClick(e){e.target===this.overlay&&this.onClose&&this.onClose("user_closed")}_handleEscapeKey(e){"Escape"===e.key&&this.isOpen&&this.onClose&&this.onClose("user_closed")}getIframe(){return this.iframe}getIsOpen(){return this.isOpen}}class T{constructor(e={}){if("undefined"==typeof window||"undefined"==typeof document)throw new Error("Dropp Payment SDK can only be used in a browser environment");if(!e.merchantId||!e.apiKey||!e.packageName)throw new Error("merchantId, apiKey, and packageName are required to initialize SDK");if(this.merchantId=e.merchantId,this.apiKey=e.apiKey,this.packageName=e.packageName,this.environment=e.environment||s.QA,this.baseUrl=a[this.environment],this.isInitialized=!1,this.initializationPromise=null,e.allowedOrigins?.length)this.allowedOrigins=e.allowedOrigins;else if(e.paymentAppUrl||e.baseUrl)try{this.allowedOrigins=[new URL(this.baseUrl).origin]}catch{this.allowedOrigins=r[this.environment]||[]}else this.allowedOrigins=r[this.environment]||[];this.isOpen=!1,this.currentSession=null,this.initTimeout=null,this.paymentTimeout=null,this.messageHandler=null,this.modalManager=null,y.setEnvironment(this.environment),y.log(`[Dropp SDK] Initialized v${g} - Merchant: ${this.merchantId}, Environment: ${this.environment}`)}pay(e={}){return new Promise((t,n)=>{if(this.isOpen){const e=b(u,"A payment session is already in progress",{currentSession:this.currentSession});return void n(e)}(async()=>{try{await this.initialize();const i=w(e);if(!i.valid){const e=b(h,"Invalid payment configuration",{errors:i.errors});return void n(e)}this.onSuccess=e.onSuccess||null,this.onFailure=e.onFailure||null,this.onCancel=e.onCancel||null,this.onClose=e.onClose||null,this.currentSession={resolve:t,reject:n,options:e,startTime:Date.now()},await this._initializePayment(e)}catch(e){const t=e&&e.code===h?e:b(m,"Failed to initialize payment",{originalError:e?.message||String(e)});n(t),this._cleanup()}})()})}async initialize(){return this.initializationPromise||(this.initializationPromise=(async()=>(await this._validateInitializationCredentials(),this.isInitialized=!0,{status:"success",code:"INITIALIZED",message:"Dropp SDK initialized successfully"}))().catch(e=>{throw this.isInitialized=!1,this.initializationPromise=null,e})),this.initializationPromise}_getValidationUrl(){const e={[s.QA]:"https://main.qa.dropp.cc/payer/webview/validate",[s.SANDBOX]:"https://sandbox.dropp.cc/payer/webview/validate",[s.PRODUCTION]:"https://pay.dropp.cc/payer/webview/validate"};return e[this.environment]||e[s.QA]}async _validateInitializationCredentials(){const e=this._getValidationUrl();let t,n=null;try{t=await fetch(e,{method:"POST",headers:{accept:"application/json, text/plain, */*","content-type":"application/json","x-api-key":this.apiKey,"x-app-package":this.packageName},body:JSON.stringify({id:this.merchantId})})}catch(t){throw b(h,"Unable to validate merchant credentials",{endpoint:e,originalError:t?.message||String(t)})}try{n=await t.json()}catch{n=null}if(!t.ok)throw b(h,"Merchant validation failed for merchantId/apiKey/packageName",{endpoint:e,status:t.status,response:n});const i=Number(n?.responseCode),s=n?.errors,a=!Array.isArray(s)||0===s.length;if(!(n&&0===i&&a))throw b(h,"Merchant validation returned an unsuccessful response",{endpoint:e,status:t.status,response:n});y.log("[Dropp SDK] Merchant credentials validated successfully")}closePayment(){this.isOpen&&this._handleCancel("sdk_close")}async _initializePayment(e){y.log("[Dropp SDK] Initializing payment:",e),this.messageHandler=new _(this.environment,this._handleMessage.bind(this),this.allowedOrigins),this.modalManager=new I(this._handleModalClose.bind(this));const t=this.modalManager.open();if(!t)throw new Error("Failed to create modal iframe");this.messageHandler.init(t);const n=e.paymentType||c.STANDARD;let i="/payViaUrl";n===c.PREAUTH?i="/preAuthPayment":n===c.RECURRING&&(i="/recurringPayment");const s=n===c.RECURRING?(e.frequency||e.recurringInterval||"").toString().trim().toUpperCase():"",a=n===c.RECURRING&&"NONE"===s,r=e.appUrl||("undefined"!=typeof window&&window.location?window.location.href:void 0),d={merchantAccount:this.merchantId,amount:n===c.PREAUTH?void 0:e.amount,maxAmount:n===c.PREAUTH||a?e.amount:void 0,fixAmount:n!==c.RECURRING||a?void 0:e.amount,currency:e.currency,itemName:e.itemName,description:e.description,invoiceId:e.invoiceId||`INV-${Date.now()}`,invoiceType:n===c.PREAUTH?"PREAUTH":void 0,apiKey:this.apiKey,packageName:this.packageName,sdkVersion:g,platform:"web",appUrl:r,sessionId:this.messageHandler.getSessionId()};if(y.log("[Dropp SDK] ๐Ÿ”‘ Including sessionId in payment params:",d.sessionId),e.successURL&&(d.successURL=e.successURL),e.failureURL&&(d.failureURL=e.failureURL),n===c.RECURRING){const t=e.frequency||e.recurringInterval;t&&(d.frequency=t),e.recurringEndDate&&(d.expiry=e.recurringEndDate)}n===c.PREAUTH&&e.authHoldTimeInSeconds&&(d.authHoldTimeInSeconds=e.authHoldTimeInSeconds),e.callbackUrl&&(d.url=e.callbackUrl,d.submitToCallBack="post");const p=await v(this.baseUrl,i,d,g);y.log("[Dropp SDK] Loading payment URL:",p),t.src=p,this.isOpen=!0,this.initTimeout=setTimeout(()=>{this._handleTimeout("init")},o),this.paymentTimeout=setTimeout(()=>{this._handleTimeout("payment")},l)}_handleMessage(e){const{type:n,data:i}=e;switch(n){case t.READY:this._handleReady(i);break;case t.PAYMENT_PAGE_LOADED:this._handlePageLoaded(i);break;case t.PAYMENT_SUCCESS:this._handleSuccess(i);break;case t.PAYMENT_FAILED:this._handleFailure(i);break;case t.PAYMENT_CANCELLED:this._handleCancel("user_cancelled");break;case t.AUTO_CLOSE_WEBVIEW:y.log("[Dropp SDK] ๐Ÿ”” AUTO_CLOSE_WEBVIEW received - closing modal now"),this._cleanup(),y.log("[Dropp SDK] โœ… _cleanup() called");break;case t.CLOSE_WEBVIEW:y.log("[Dropp SDK] ๐Ÿ“ฑ CLOSE_WEBVIEW received from chrome app - closing modal"),this._handleCancel("app_close");break;default:y.warn("[Dropp SDK] Unknown message type:",n)}}_handleReady(e){if(y.log("[Dropp SDK] Payment app ready"),this.initTimeout&&(clearTimeout(this.initTimeout),this.initTimeout=null),this.messageHandler&&this.currentSession){const e={};Object.keys(this.currentSession.options).forEach(t=>{const n=this.currentSession.options[t];"function"!=typeof n&&(e[t]=n)}),y.log("[Dropp SDK] Sending serializable init config:",e),this.messageHandler.sendInit(e)}}_handlePageLoaded(e){y.log("[Dropp SDK] Payment page loaded")}_handleSuccess(e){y.log("[Dropp SDK] Payment successful:",e);const t={status:"success",...e,sessionDuration:Date.now()-this.currentSession.startTime};this.currentSession&&this.currentSession.resolve(t),this.onSuccess&&this.onSuccess(t)}_handleFailure(e){y.log("[Dropp SDK] Payment failed:",e);const t={status:"failed",...e,sessionDuration:Date.now()-this.currentSession.startTime};this.currentSession&&this.currentSession.resolve(t),this.onFailure&&this.onFailure(t)}_handleCancel(e){y.log("[Dropp SDK] Payment cancelled:",e);const t={status:"cancelled",reason:e,sessionDuration:this.currentSession?Date.now()-this.currentSession.startTime:0};this.currentSession&&this.currentSession.resolve(t),this.onCancel&&this.onCancel(t),this._cleanup()}_handleModalClose(e){y.log("[Dropp SDK] Modal closed by user:",e),this._handleCancel(e)}_handleTimeout(e){y.error("[Dropp SDK] Timeout:",e);const t=b("init"===e?d:p,"init"===e?"Payment app failed to load within timeout period":"Payment session timed out",{type:e,sessionDuration:this.currentSession?Date.now()-this.currentSession.startTime:0});this.currentSession&&this.currentSession.reject(t),this.onFailure&&this.onFailure({status:"failed",error:t}),this._cleanup()}_cleanup(){y.log("[Dropp SDK] ๐Ÿงน Cleaning up session - starting cleanup"),this.initTimeout&&(clearTimeout(this.initTimeout),this.initTimeout=null),this.paymentTimeout&&(clearTimeout(this.paymentTimeout),this.paymentTimeout=null),this.messageHandler&&(y.log("[Dropp SDK] ๐Ÿงน Destroying message handler"),this.messageHandler.destroy(),this.messageHandler=null),this.modalManager&&(y.log("[Dropp SDK] ๐Ÿงน Closing modal manager"),this.modalManager.close(),y.log("[Dropp SDK] ๐Ÿงน Modal manager closed"),this.modalManager=null),this.currentSession=null,this.isOpen=!1,this.onClose&&this.onClose()}static getVersion(){return g}static getEnvironments(){return{...s}}static getPaymentTypes(){return{...c}}}let M=null;async function O(e){M=new T(e);return{...await M.initialize(),sdk:M}}const C={init:e=>O(e),pay(e){if(!M){const e=new Error("Dropp SDK is not initialized. Call Dropp.init(config) before Dropp.pay(options).");throw e.code="SDK_NOT_INITIALIZED",e}return M.pay(e)},getInstance:()=>M};var A={DroppPaymentSDK:T,createPaymentSDK:O,Dropp:C,ENVIRONMENTS:s,PAYMENT_TYPES:c};e.Dropp=C,e.DroppPaymentSDK=T,e.ENVIRONMENTS=s,e.PAYMENT_TYPES=c,e.createPaymentSDK=O,e.default=A,e.getDroppInstance=function(){return M},Object.defineProperty(e,"__esModule",{value:!0})});
2
+ //# sourceMappingURL=dropp-payment-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropp-payment-sdk.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 CLOSE_WEBVIEW: 'CLOSE_WEBVIEW',\n AUTO_CLOSE_WEBVIEW: 'AUTO_CLOSE_WEBVIEW',\n PAYMENT_PAGE_LOADED: 'PAYMENT_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.pay.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://pay.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.0';\n\n// SDK authentication credentials (default values, can be overridden in config)\nexport const DEFAULT_API_KEY = '<4b3a6dd3e007847d237cb206891cxxxx>';\nexport const DEFAULT_PACKAGE_NAME = '<app.dropp.com>';\n\n// CSS z-index for modal\nexport const MODAL_Z_INDEX = 999999;\n","/**\n * Logger utility for Dropp Payment SDK\n * Conditionally logs based on environment - enabled for qa/sandbox, disabled for prod\n */\n\nclass Logger {\n constructor(environment) {\n this.environment = environment;\n this.enabled = this._shouldEnableLogging();\n }\n\n /**\n * Determine if logging should be enabled based on environment\n * @private\n */\n _shouldEnableLogging() {\n const env = this.environment?.toLowerCase() || '';\n // Enable logging for qa, sandbox, dev, or local environments\n // Disable for prod/production\n return env !== 'prod' && env !== 'production';\n }\n\n /**\n * Update environment and recalculate logging state\n */\n setEnvironment(environment) {\n this.environment = environment;\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');\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 isValidHttpUrl(url) {\n if (typeof url !== 'string' || !url.trim()) {\n return false;\n }\n try {\n const parsed = new URL(url.trim());\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\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\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 * Generate HMAC-SHA256 signature for SDK authentication\n */\nexport async function generateSdkAuth(merchantAccount, base64Payload, timestamp) {\n try {\n const key = `${merchantAccount}.${timestamp}`;\n const message = `${base64Payload}.${timestamp}`;\n \n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const messageData = encoder.encode(message);\n \n // Import key for HMAC\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n \n // Generate HMAC\n const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);\n \n // Convert to base64 (URL-safe)\n const base64 = btoa(String.fromCharCode(...new Uint8Array(signature)))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n \n return base64;\n } catch (error) {\n logger.error('Error generating SDK auth:', error);\n return '';\n }\n}\n\n/**\n * Build payment URL with base64 payload (matching Android SDK pattern)\n */\nexport async function buildPaymentUrl(baseUrl, route, params, sdkVersion) {\n try {\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] ๐Ÿ”‘ Payload with sessionId:', payload);\n console.log('[buildPaymentUrl] ๐Ÿ”‘ Full payload being encoded:', payload);\n \n // Base64 encode payload (URL-safe, no padding)\n const jsonString = JSON.stringify(payload);\n const base64Payload = btoa(jsonString)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n \n console.log('[buildPaymentUrl] ๐Ÿ”‘ Base64 payload:', base64Payload);\n \n // Generate SDK authentication\n const timestamp = Date.now().toString();\n const sdkAuth = await generateSdkAuth(params.merchantAccount, base64Payload, timestamp);\n \n // Build URL with base64 payload\n const url = `${baseUrl}/#${route}?pay=${base64Payload}&sdkAuth=${sdkAuth}&sdkTs=${timestamp}&sdkVersion=${sdkVersion}&platform=web`;\n \n console.log('[buildPaymentUrl] ๐Ÿ”‘ Final URL:', url);\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 = {}) {\n const errors = [];\n const paymentType = config.paymentType || PAYMENT_TYPES.STANDARD;\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.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 (!isValidHttpUrl(config.callbackUrl)) {\n errors.push('callbackUrl must be a valid HTTP or HTTPS URL');\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 (!isValidHttpUrl(config.callbackUrl)) {\n errors.push('callbackUrl must be a valid HTTP or HTTPS URL');\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, ERROR_CODES } 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] ๐Ÿ”‘ Generated sessionId:', this.sessionId);\n console.log('[MessageHandler] ๐Ÿ”‘ Generated sessionId:', this.sessionId);\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 DEBUG] Received message:', {\n origin: event.origin,\n source: event.source,\n iframeContentWindow: this.iframe?.contentWindow,\n sourceMatches: event.source === this.iframe?.contentWindow,\n data: event.data\n });\n\n // Ignore messages from self (parent window)\n if (event.source === window) {\n logger.log('[MessageHandler DEBUG] 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 hasIframe: !!this.iframe,\n hasContentWindow: !!this.iframe?.contentWindow,\n sourceMatches: event.source === this.iframe?.contentWindow,\n eventOrigin: event.origin,\n expectedOrigin: this.allowedOrigins\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:', message);\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 expected: this.sessionId,\n received: message.sessionId\n });\n return;\n }\n\n // 5. Process valid message\n logger.log('[MessageHandler DEBUG] โœ… Message passed all validation, processing:', message.type);\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 return this.allowedOrigins.some(allowedOrigin => {\n return origin === allowedOrigin || origin.startsWith(allowedOrigin);\n });\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 // Must have timestamp\n if (!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, message);\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, message);\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 allow-popups-to-escape-sandbox');\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 validateConfig, \n createError, \n isBrowser \n} from './utils.js';\nimport logger from './logger.js';\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.packageName - Package name (required)\n * @param {string} config.environment - Environment: 'production', 'qa', or 'sandbox'\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 || !config.packageName) {\n throw new Error('merchantId, apiKey, and packageName are required to initialize SDK');\n }\n\n // Store credentials\n this.merchantId = config.merchantId;\n this.apiKey = config.apiKey;\n this.packageName = config.packageName;\n\n this.environment = config.environment || ENVIRONMENTS.QA;\n this.baseUrl =\n PAYMENT_APP_URLS[this.environment];\n\n // Initialization state\n this.isInitialized = false;\n this.initializationPromise = null;\n\n if (config.allowedOrigins?.length) {\n this.allowedOrigins = config.allowedOrigins;\n } else if (config.paymentAppUrl || config.baseUrl) {\n try {\n this.allowedOrigins = [new URL(this.baseUrl).origin];\n } catch {\n this.allowedOrigins = ALLOWED_ORIGINS[this.environment] || [];\n }\n } else {\n this.allowedOrigins = ALLOWED_ORIGINS[this.environment] || [];\n }\n\n // State\n this.isOpen = false;\n this.currentSession = null;\n this.initTimeout = null;\n this.paymentTimeout = null;\n\n // Managers\n this.messageHandler = null;\n this.modalManager = null;\n\n // Set logger environment\n logger.setEnvironment(this.environment);\n logger.log(`[Dropp SDK] Initialized v${SDK_VERSION} - Merchant: ${this.merchantId}, 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 {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 // Check if already open\n if (this.isOpen) {\n const error = createError(\n ERROR_CODES.ALREADY_OPEN,\n 'A payment session is already in progress',\n { currentSession: this.currentSession }\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 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 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://main.qa.dropp.cc/payer/webview/validate',\n [ENVIRONMENTS.SANDBOX]: 'https://sandbox.dropp.cc/payer/webview/validate',\n [ENVIRONMENTS.PRODUCTION]: 'https://pay.dropp.cc/payer/webview/validate'\n };\n\n return (\n validationUrls[this.environment] ||\n validationUrls[ENVIRONMENTS.QA]\n );\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\n let response;\n let responseBody = null;\n try {\n response = await fetch(validationUrl, {\n method: 'POST',\n headers: {\n accept: 'application/json, text/plain, */*',\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n 'x-app-package': this.packageName\n },\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 throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Merchant validation failed for merchantId/apiKey/packageName',\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 throw createError(\n ERROR_CODES.INVALID_CONFIG,\n 'Merchant validation returned an unsuccessful response',\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 this._handleCancel('sdk_close');\n }\n }\n\n /**\n * Initialize payment session\n * @private\n */\n async _initializePayment(options) {\n logger.log('[Dropp SDK] Initializing payment:', options);\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 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.packageName,\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 logger.log('[Dropp SDK] ๐Ÿ”‘ Including sessionId in payment params:', params.sessionId);\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 // Build payment URL with base64 payload (matching Android SDK pattern)\n const paymentUrl = await buildPaymentUrl(this.baseUrl, route, params, SDK_VERSION);\n\n logger.log('[Dropp SDK] Loading payment URL:', paymentUrl);\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 * 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.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.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 now');\n this._cleanup();\n logger.log('[Dropp SDK] โœ… _cleanup() called');\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 chrome app - closing modal');\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 serializable init config:', serializableOptions);\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 * Handle successful payment\n * @private\n */\n _handleSuccess(data) {\n logger.log('[Dropp SDK] Payment successful:', data);\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:', data);\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:', reason);\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:', reason);\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 // 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 // Clear state\n this.currentSession = 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\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 * 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","CLOSE_WEBVIEW","AUTO_CLOSE_WEBVIEW","PAYMENT_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","this","enabled","_shouldEnableLogging","env","toLowerCase","setEnvironment","log","args","console","warn","error","debug","info","SUPPORTED_CURRENCIES","RECURRING_FREQUENCY_VALUES","PAYMENT_TYPE_VALUES","isValidHttpUrl","url","trim","parsed","URL","protocol","async","buildPaymentUrl","baseUrl","route","params","sdkVersion","payload","Object","keys","forEach","key","value","jsonString","JSON","stringify","base64Payload","btoa","replace","timestamp","Date","now","toString","sdkAuth","merchantAccount","message","encoder","TextEncoder","keyData","encode","messageData","cryptoKey","crypto","subtle","importKey","name","hash","signature","sign","String","fromCharCode","Uint8Array","generateSdkAuth","validateConfig","config","errors","paymentType","normalizedCurrency","currency","toUpperCase","includes","push","join","undefined","amount","num","parseFloat","Number","isNaN","isPositiveNumber","itemName","callbackUrl","authHoldTimeInSeconds","parseInt","isInteger","isPositiveInteger","frequency","recurringInterval","recurringEndDate","date","getTime","isValidIsoDateTime","valid","length","createError","code","details","toISOString","MessageHandler","onMessage","allowedOrigins","sessionId","Math","random","substring","iframe","messageListener","pendingMessages","Map","init","_handleMessage","bind","window","addEventListener","destroy","removeEventListener","clear","event","origin","source","iframeContentWindow","contentWindow","sourceMatches","data","_validateOrigin","hasIframe","hasContentWindow","eventOrigin","expectedOrigin","_validateMessageStructure","expected","received","type","_processMessage","startsWith","some","allowedOrigin","values","sendToPaymentApp","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","DroppPaymentSDK","Error","merchantId","apiKey","packageName","isInitialized","initializationPromise","paymentAppUrl","currentSession","initTimeout","paymentTimeout","messageHandler","modalManager","pay","options","Promise","resolve","reject","initialize","validation","onSuccess","onFailure","onCancel","startTime","_initializePayment","sdkError","originalError","_cleanup","_validateInitializationCredentials","status","catch","_getValidationUrl","validationUrls","validationUrl","response","responseBody","fetch","method","headers","accept","endpoint","json","ok","responseCode","hasNoErrors","Array","isArray","closePayment","_handleCancel","_handleModalClose","recurringFrequency","isRecurringNone","detectedAppUrl","appUrl","location","href","maxAmount","fixAmount","description","invoiceId","invoiceType","platform","successURL","failureURL","expiry","submitToCallBack","paymentUrl","src","_handleTimeout","_handleReady","_handlePageLoaded","_handleSuccess","_handleFailure","clearTimeout","serializableOptions","result","sessionDuration","reason","getVersion","getEnvironments","getPaymentTypes","globalDroppInstance","createPaymentSDK","sdk","Dropp","getInstance","index"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@dropp.cc/payment-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Dropp Payment SDK for Web - Secure payment integration for web applications.",
5
+ "main": "dist/dropp-payment-sdk.js",
6
+ "module": "dist/dropp-payment-sdk.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "scripts": {
14
+ "build": "rollup -c",
15
+ "dev": "rollup -c -w",
16
+ "test": "jest",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "dropp",
21
+ "payment",
22
+ "sdk",
23
+ "webview",
24
+ "hedera",
25
+ "cryptocurrency",
26
+ "payment-gateway"
27
+ ],
28
+ "author": "Dropp",
29
+ "license": "MIT",
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "registry": "https://registry.npmjs.org/"
33
+ },
34
+ "devDependencies": {
35
+ "@rollup/plugin-commonjs": "^25.0.0",
36
+ "@rollup/plugin-node-resolve": "^15.0.0",
37
+ "@rollup/plugin-terser": "^1.0.0",
38
+ "rollup": "^3.0.0"
39
+ }
40
+ }