@inflow_pay/sdk 0.2.0 → 0.4.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/CHANGELOG.md ADDED
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.3.0] - 2026-01-21
11
+
12
+ ### Added
13
+ - **Dynamic Height Calculation**: Iframe now automatically adjusts its height based on content using postMessage communication
14
+ - Eliminates unnecessary empty space when no error/success messages are displayed
15
+ - Prevents overflow when messages appear
16
+ - Smooth height transitions with CSS animations
17
+ - Height is calculated and sent from iframe to parent SDK when content changes
18
+
19
+ ## [0.2.0] - 2026-01-21
20
+
21
+ ### Added
22
+ - **Skeleton Loader with Shimmer Effect**: Beautiful loading state that matches the SDK structure
23
+ - Shimmer animation effect for better UX
24
+ - Dark mode support with adaptive colors
25
+ - Automatically hides when iframe is ready
26
+ - **Initial Height Fix**: Fixed iframe height to prevent overflow and empty space issues
27
+ - Set minimum height to accommodate content
28
+
29
+ ### Fixed
30
+ - Fixed iframe visibility issue where loader would show on top of iframe
31
+ - Fixed empty space issue when centering SDK in flex containers
32
+ - Fixed disclaimer overflow when general error/success messages appear
33
+
34
+ ## [0.1.0] - 2026-01-20
35
+
36
+ ### Added
37
+ - **Customization Properties**: Comprehensive styling API for customizing the payment form
38
+ - Input container styling (backgroundColor, borderColor, borderRadius, borderEnabled)
39
+ - Input field styling (textColor, placeholderColor, backgroundColor, borders)
40
+ - Button styling with hover and disabled states
41
+ - General error and success message styling
42
+ - Theme support (light/dark mode overrides)
43
+ - Custom font family selection
44
+ - Custom button text
45
+ - Custom input placeholders
46
+ - **Enhanced Type Safety**: Added proper TypeScript types for styling properties
47
+ - `FontWeight` type: Supports numeric (100-900) and keyword values ('normal', 'bold', 'lighter', 'bolder')
48
+ - `Opacity` type: Supports both number (0-1) and string ('0.5', '50%') values
49
+
50
+ ### Changed
51
+ - **Button Border Logic**: Fixed inconsistent border behavior
52
+ - Borders now only apply when `borderEnabled: true` is explicitly set
53
+ - Previously, borders would appear if `borderColor` was provided without `borderEnabled`
54
+ - Matches the behavior of `inputContainer` border logic
55
+
56
+ ## [0.0.1]
57
+
58
+ ### Added
59
+ - Initial release of the SDK with iframe-based payment flow
60
+ - React and vanilla JavaScript support
61
+ - Basic payment processing
62
+ - 3D Secure (3DS) support
63
+ - TypeScript definitions
64
+ - Secure iframe-based card form
65
+ - Automatic 3DS handling
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # InflowPay SDK v2 - Iframe-based Payment SDK
1
+ # InflowPay Iframe-based Payment SDK
2
2
 
3
- Accept card payments with a pre-built, secure payment form. **Same API as the React SDK** for easy migration.
3
+ Accept card payments with a pre-built, secure payment form. Uses an iframe-based architecture for enhanced security and easy integration.
4
4
 
5
5
  ## Installation
6
6
 
@@ -28,7 +28,7 @@ Or use via CDN (UMD build):
28
28
 
29
29
  ## Quick Start
30
30
 
31
- **Same API as React SDK!** Easy migration from React SDK to iframe-based SDK:
31
+ Get started with the iframe-based SDK:
32
32
 
33
33
  ```javascript
34
34
  import { InflowPayProvider } from '@inflow_pay/sdk';
@@ -105,6 +105,25 @@ const cardElement = provider.createCardElement({
105
105
  paymentId: 'pay_xxx', // Required
106
106
  container: '#card-container', // Required (CSS selector or HTMLElement)
107
107
 
108
+ // Styling (optional)
109
+ style: {
110
+ fontFamily: 'Inter',
111
+ button: {
112
+ backgroundColor: '#0070F3',
113
+ textColor: '#FFFFFF'
114
+ }
115
+ },
116
+
117
+ // Custom button text (optional)
118
+ buttonText: 'Complete Payment',
119
+
120
+ // Custom placeholders (optional)
121
+ placeholders: {
122
+ cardNumber: '1234 5678 9012 3456',
123
+ expiry: 'MM/YY',
124
+ cvc: 'CVC'
125
+ },
126
+
108
127
  // Callbacks (same as React SDK)
109
128
  onReady: () => {
110
129
  // Card element is mounted and ready
@@ -167,7 +186,6 @@ cardElement.destroy();
167
186
 
168
187
  <script src="https://cdn.inflowpay.com/sdk/v2/sdk.umd.js"></script>
169
188
  <script>
170
- // Same API as React SDK!
171
189
  // SDK is available as window.InflowPaySDK
172
190
  const provider = new InflowPaySDK.InflowPayProvider({
173
191
  config: { apiKey: 'inflow_pub_xxx' }
@@ -255,14 +273,14 @@ See [API documentation](https://docs.inflowpay.com/v0/reference/createpayment) f
255
273
 
256
274
  ## Migration from React SDK
257
275
 
258
- The SDK v2 uses the **same API** as the React SDK, making migration easy. You have two options:
276
+ The iframe-based SDK maintains similar component APIs, but **styling has changed**. You have two options:
259
277
 
260
278
  ### Option 1: Keep Using React (Recommended for React Apps)
261
279
 
262
- If you're using React, you can use the React components which work **exactly like the original SDK**:
280
+ If you're using React, you can use the React components with a similar API:
263
281
 
264
282
  ```tsx
265
- // Just change the import path!
283
+ // Change the import path
266
284
  import { InflowPayProvider, CardElement } from '@inflow_pay/sdk/react';
267
285
 
268
286
  function App() {
@@ -270,6 +288,14 @@ function App() {
270
288
  <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>
271
289
  <CardElement
272
290
  paymentId={paymentId}
291
+ style={{
292
+ // ⚠️ Styling API has changed - see Styling section below
293
+ fontFamily: 'Inter',
294
+ button: {
295
+ backgroundColor: '#0070F3',
296
+ textColor: '#FFFFFF'
297
+ }
298
+ }}
273
299
  onComplete={(result) => {
274
300
  if (result.status === 'CHECKOUT_SUCCESS') {
275
301
  window.location.href = '/success';
@@ -281,7 +307,7 @@ function App() {
281
307
  }
282
308
  ```
283
309
 
284
- **No changes needed!** Same API, same behavior, just a different import path.
310
+ **Important:** The component API is similar, but **styling customization has changed**. See the [Styling](#styling) section for the new styling structure.
285
311
 
286
312
  ### Option 2: Vanilla JavaScript (For Non-React Apps)
287
313
 
@@ -312,6 +338,7 @@ cardElement.mount();
312
338
  - Explicit `container` prop (CSS selector or HTMLElement) instead of JSX
313
339
  - Call `mount()` explicitly instead of automatic React mounting
314
340
  - Same callbacks, same status codes, same error handling
341
+ - **Styling API has changed** - see [Styling](#styling) section for details
315
342
 
316
343
  ## TypeScript
317
344
 
@@ -339,6 +366,224 @@ const cardElement = provider.createCardElement({
339
366
  });
340
367
  ```
341
368
 
369
+ ## Styling
370
+
371
+ The iframe-based SDK provides a comprehensive styling API to match your brand. **Note: The styling structure is different from the original React SDK.** All styles are fully typed with TypeScript.
372
+
373
+ ### Basic Styling
374
+
375
+ ```javascript
376
+ const cardElement = provider.createCardElement({
377
+ paymentId: 'pay_xxx',
378
+ container: '#card-container',
379
+ style: {
380
+ fontFamily: 'Inter',
381
+ fillParent: true,
382
+ inputContainer: {
383
+ backgroundColor: '#F5F5F5',
384
+ borderRadius: '8px',
385
+ borderEnabled: true,
386
+ borderColor: '#E0E0E0'
387
+ },
388
+ input: {
389
+ textColor: '#1A1A1A',
390
+ placeholderColor: '#999999'
391
+ },
392
+ button: {
393
+ backgroundColor: '#0070F3',
394
+ textColor: '#FFFFFF',
395
+ borderRadius: '8px',
396
+ fontSize: '16px',
397
+ fontWeight: 600,
398
+ opacity: 1,
399
+ hover: {
400
+ backgroundColor: '#0051CC'
401
+ },
402
+ disabled: {
403
+ opacity: 0.5
404
+ }
405
+ }
406
+ }
407
+ });
408
+ ```
409
+
410
+ ### Theme Support (Light/Dark Mode)
411
+
412
+ The SDK automatically adapts to the user's system preference, but you can also provide theme-specific overrides:
413
+
414
+ ```javascript
415
+ style: {
416
+ // Base styles (apply to both themes)
417
+ fontFamily: 'Inter',
418
+ button: {
419
+ backgroundColor: '#0070F3',
420
+ textColor: '#FFFFFF'
421
+ },
422
+ // Light mode overrides
423
+ light: {
424
+ inputContainer: {
425
+ backgroundColor: '#FFFFFF',
426
+ borderColor: '#E0E0E0'
427
+ },
428
+ input: {
429
+ textColor: '#1A1A1A'
430
+ }
431
+ },
432
+ // Dark mode overrides
433
+ dark: {
434
+ inputContainer: {
435
+ backgroundColor: '#1A1A1A',
436
+ borderColor: '#333333'
437
+ },
438
+ input: {
439
+ textColor: '#FFFFFF',
440
+ backgroundColor: '#2A2A2A'
441
+ },
442
+ button: {
443
+ backgroundColor: '#0066CC'
444
+ }
445
+ }
446
+ }
447
+ ```
448
+
449
+ ### Available Font Families
450
+
451
+ ```typescript
452
+ type FontFamily =
453
+ | 'DM Sans'
454
+ | 'Inter'
455
+ | 'Poppins'
456
+ | 'Nunito'
457
+ | 'Work Sans'
458
+ | 'Manrope'
459
+ | 'Rubik'
460
+ | 'Karla'
461
+ | 'Figtree'
462
+ | 'Outfit'
463
+ | 'Space Grotesk'
464
+ | 'Urbanist';
465
+ ```
466
+
467
+ ### Complete Styling API
468
+
469
+ ```typescript
470
+ interface CSSProperties {
471
+ fontFamily?: FontFamily;
472
+ fillParent?: boolean;
473
+
474
+ // Input container (wrapper around all inputs)
475
+ inputContainer?: {
476
+ backgroundColor?: string;
477
+ borderColor?: string;
478
+ borderEnabled?: boolean; // Must be true to show border
479
+ borderRadius?: string;
480
+ };
481
+
482
+ // Individual input fields
483
+ input?: {
484
+ backgroundColor?: string;
485
+ borderColor?: string;
486
+ borderEnabled?: boolean;
487
+ borderRadius?: string;
488
+ textColor?: string;
489
+ placeholderColor?: string;
490
+ };
491
+
492
+ // Button styles
493
+ button?: {
494
+ backgroundColor?: string;
495
+ textColor?: string;
496
+ borderRadius?: string;
497
+ borderColor?: string;
498
+ borderEnabled?: boolean; // Must be true to show border
499
+ fontSize?: string;
500
+ fontWeight?: FontWeight;
501
+ opacity?: Opacity;
502
+ hover?: ButtonBaseStyles; // Hover state
503
+ disabled?: ButtonBaseStyles; // Disabled state
504
+ loaderColor?: string;
505
+ };
506
+
507
+ // General messages (errors/success)
508
+ generalError?: {
509
+ textColor?: string;
510
+ backgroundColor?: string;
511
+ borderEnabled?: boolean;
512
+ borderRadius?: string;
513
+ borderColor?: string;
514
+ };
515
+
516
+ generalSuccess?: {
517
+ textColor?: string;
518
+ backgroundColor?: string;
519
+ borderEnabled?: boolean;
520
+ borderRadius?: string;
521
+ borderColor?: string;
522
+ };
523
+
524
+ // Other colors
525
+ disclaimerColor?: string;
526
+ fieldErrorColor?: string;
527
+
528
+ // Theme-specific overrides
529
+ light?: ThemeStyles;
530
+ dark?: ThemeStyles;
531
+ }
532
+ ```
533
+
534
+ ### Custom Placeholders
535
+
536
+ ```javascript
537
+ placeholders: {
538
+ cardNumber: '1234 5678 9012 3456',
539
+ expiry: 'MM/YY',
540
+ cvc: 'CVC'
541
+ }
542
+ ```
543
+
544
+ ### Custom Button Text
545
+
546
+ ```javascript
547
+ buttonText: 'Pay Now'
548
+ ```
549
+
550
+ ### React Example with Styling
551
+
552
+ ```tsx
553
+ import { InflowPayProvider, CardElement } from '@inflow_pay/sdk/react';
554
+
555
+ function App() {
556
+ return (
557
+ <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>
558
+ <CardElement
559
+ paymentId="pay_xxx"
560
+ style={{
561
+ fontFamily: 'Inter',
562
+ fillParent: true,
563
+ button: {
564
+ backgroundColor: '#0070F3',
565
+ textColor: '#FFFFFF',
566
+ borderRadius: '8px',
567
+ fontWeight: 600
568
+ },
569
+ dark: {
570
+ button: {
571
+ backgroundColor: '#0066CC'
572
+ }
573
+ }
574
+ }}
575
+ buttonText="Complete Payment"
576
+ onComplete={(result) => {
577
+ if (result.status === 'CHECKOUT_SUCCESS') {
578
+ alert('Payment successful!');
579
+ }
580
+ }}
581
+ />
582
+ </InflowPayProvider>
583
+ );
584
+ }
585
+ ```
586
+
342
587
  ## Security
343
588
 
344
589
  - ✅ Card data is tokenized before reaching your server (PCI compliant)
@@ -347,11 +592,22 @@ const cardElement = provider.createCardElement({
347
592
  - ✅ All requests over HTTPS
348
593
  - ✅ Iframe isolation for security
349
594
 
595
+ ## Features
596
+
597
+ - ✅ **Dynamic Height**: Automatically adjusts iframe height based on content
598
+ - ✅ **Skeleton Loader**: Beautiful loading state with shimmer effect
599
+ - ✅ **Dark Mode Support**: Automatic theme detection with manual overrides
600
+ - ✅ **TypeScript**: Full type definitions included
601
+ - ✅ **Responsive**: Works on all screen sizes
602
+ - ✅ **Accessible**: WCAG compliant
603
+ - ✅ **Secure**: PCI compliant, iframe isolation
604
+
350
605
  ## Support
351
606
 
352
607
  - **Documentation:** https://docs.inflowpay.com/v0/reference/createpayment
353
608
  - **Email:** support@inflowpay.com
354
609
  - **GitHub:** https://github.com/inflowpay/sdk
610
+ - **Changelog:** See [CHANGELOG.md](./CHANGELOG.md) for version history
355
611
 
356
612
  ## License
357
613
 
@@ -1,4 +1,4 @@
1
- "use strict";class x{constructor(e){if(this.iframe=null,this.messageListener=null,this.containerElement=null,this.config=e,this.iframeUrl=e.iframeUrl||"http://localhost:3000/iframe/checkout",this.environment=this.getEnvironmentFromApiKey(e.apiKey||""),this.usePopup=!e.container,e.container)if(typeof e.container=="string"){if(this.containerElement=document.querySelector(e.container),!this.containerElement)throw new Error(`Container not found: ${e.container}`)}else this.containerElement=e.container}init(){this.iframe||(this.createIframe(),this.addMessageListener())}createIframe(){const e=new URL(this.iframeUrl);this.config.apiKey&&e.searchParams.set("apiKey",this.config.apiKey),this.config.config?.paymentId&&e.searchParams.set("paymentId",this.config.config.paymentId);const t=e.toString();if(this.usePopup){const i=document.createElement("div");i.id="inflowpay-sdk-overlay",i.style.cssText=`
1
+ "use strict";class w{constructor(e){if(this.iframe=null,this.messageListener=null,this.containerElement=null,this.config=e,this.iframeUrl=e.iframeUrl||"http://localhost:3000/iframe/checkout",this.environment=this.getEnvironmentFromApiKey(e.apiKey||""),this.usePopup=!e.container,e.container)if(typeof e.container=="string"){if(this.containerElement=document.querySelector(e.container),!this.containerElement)throw new Error(`Container not found: ${e.container}`)}else this.containerElement=e.container}init(){this.iframe||(this.createIframe(),this.addMessageListener())}createIframe(){const e=new URL(this.iframeUrl);this.config.apiKey&&e.searchParams.set("apiKey",this.config.apiKey),this.config.config?.paymentId&&e.searchParams.set("paymentId",this.config.config.paymentId);const t=e.toString();if(this.usePopup){const i=document.createElement("div");i.id="inflowpay-sdk-overlay",i.style.cssText=`
2
2
  position: fixed;
3
3
  top: 0;
4
4
  left: 0;
@@ -41,11 +41,12 @@
41
41
  `,this.iframe.setAttribute("allow","payment"),n.appendChild(s),n.appendChild(this.iframe),i.appendChild(n),document.body.appendChild(i),this.showLoader(n),i.addEventListener("click",o=>{o.target===i&&this.close()})}else{if(!this.containerElement)throw new Error("Container element is required for inline mode");if(this.containerElement.innerHTML="",this.containerElement instanceof HTMLElement){const s=this.containerElement.getAttribute("style")||"";s.includes("min-height")||(this.containerElement.style.minHeight="196px"),s.includes("position")||(this.containerElement.style.position="relative"),s.includes("overflow")||(this.containerElement.style.overflow="hidden")}this.iframe=document.createElement("iframe"),this.iframe.src=t;const i=this.config.config?.style?.fillParent?"100%":"344px",n=this.config.config?.style?.fillParent?"none":"100%";this.iframe.style.cssText=`
42
42
  width: ${i};
43
43
  max-width: ${n};
44
- height: 100%;
44
+ height: 196px;
45
45
  min-height: 196px;
46
46
  border: none;
47
47
  display: block;
48
- `,this.iframe.setAttribute("allow","payment"),this.containerElement.appendChild(this.iframe),this.showLoader(this.containerElement)}}addMessageListener(){this.messageListener=e=>{const t=new URL(this.iframeUrl).origin;let n=e.origin===t;if(n||((this.environment==="sandbox"||this.environment==="development")&&(n=(e.origin.includes("localhost")||e.origin.includes("127.0.0.1"))&&(t.includes("localhost")||t.includes("127.0.0.1"))),n||(n=e.origin==="https://dev.api.inflowpay.com"||e.origin==="https://pre-prod.api.inflowpay.xyz"||e.origin==="https://api.inflowpay.xyz")),!n){this.config.debug&&console.warn("[SDK] Rejected message from unauthorized origin:",e.origin);return}const s=e.data;if(!(!s||!s.type))switch(s.type){case"iframe-ready":this.hideLoader(),this.sendConfigToIframe();break;case"close":this.close();break;case"success":this.config.onSuccess&&this.config.onSuccess(s.data);break;case"error":this.config.onError&&this.config.onError(s.data);break;case"3ds-required":this.config.debug&&console.log("[SDK] Received 3DS request:",s.threeDsSessionUrl),s.threeDsSessionUrl?(this.config.debug&&console.log("[SDK] Opening 3DS modal..."),this.open3DSModal(s.threeDsSessionUrl).then(o=>{if(this.config.debug&&console.log("[SDK] 3DS modal closed, result:",o),this.iframe&&this.iframe.contentWindow){const r=this.getTargetOrigin();this.iframe.contentWindow.postMessage({type:"3ds-result",success:o,paymentId:s.paymentId||this.config.config?.paymentId},r)}})):this.config.debug&&console.error("[SDK] 3DS required but no threeDsSessionUrl provided");break;default:this.config.debug&&console.log("SDK: Received message:",s)}},window.addEventListener("message",this.messageListener)}sendConfigToIframe(){if(!this.iframe||!this.iframe.contentWindow){this.iframe&&(this.iframe.onload=()=>{this.sendConfigToIframe()});return}const e={type:"sdkData",config:{...this.config.config||{},paymentId:this.config.config?.paymentId},data:{apiKey:this.config.apiKey}},t=this.getTargetOrigin();this.iframe.contentWindow.postMessage(e,t)}showLoader(e){this.iframe&&(this.iframe.style.display="none");const t=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,i=t?"#2d2d2d":"#F5F5F5",n=t?"#3d3d3d":"#E5E5E5",o=`linear-gradient(90deg, ${n} 25%, ${t?"#4d4d4d":"#F0F0F0"} 50%, ${n} 75%)`,r=document.createElement("div");r.id="inflowpay-loader";const u=this.config.config?.style?.fillParent?"100%":"344px";r.style.cssText=`
48
+ transition: height 0.2s ease;
49
+ `,this.iframe.setAttribute("allow","payment"),this.containerElement.appendChild(this.iframe),this.showLoader(this.containerElement)}}addMessageListener(){this.messageListener=e=>{const t=new URL(this.iframeUrl).origin;let n=e.origin===t;if(n||((this.environment==="sandbox"||this.environment==="development")&&(n=(e.origin.includes("localhost")||e.origin.includes("127.0.0.1"))&&(t.includes("localhost")||t.includes("127.0.0.1"))),n||(n=e.origin==="https://dev.api.inflowpay.com"||e.origin==="https://pre-prod.api.inflowpay.xyz"||e.origin==="https://api.inflowpay.xyz")),!n){this.config.debug&&console.warn("[SDK] Rejected message from unauthorized origin:",e.origin);return}const s=e.data;if(!(!s||!s.type))switch(s.type){case"iframe-ready":this.hideLoader(),this.sendConfigToIframe();break;case"content-height":if(s.height&&this.iframe){const o=Math.max(s.height,196);this.iframe.style.height=`${o}px`,this.containerElement&&(this.containerElement.style.minHeight=`${o}px`)}break;case"close":this.close();break;case"success":this.config.onSuccess&&this.config.onSuccess(s.data);break;case"error":this.config.onError&&this.config.onError(s.data);break;case"3ds-required":this.config.debug&&console.log("[SDK] Received 3DS request:",s.threeDsSessionUrl),s.threeDsSessionUrl?(this.config.debug&&console.log("[SDK] Opening 3DS modal..."),this.open3DSModal(s.threeDsSessionUrl).then(o=>{if(this.config.debug&&console.log("[SDK] 3DS modal closed, result:",o),this.iframe&&this.iframe.contentWindow){const r=this.getTargetOrigin();this.iframe.contentWindow.postMessage({type:"3ds-result",success:o,paymentId:s.paymentId||this.config.config?.paymentId},r)}})):this.config.debug&&console.error("[SDK] 3DS required but no threeDsSessionUrl provided");break;default:this.config.debug&&console.log("SDK: Received message:",s)}},window.addEventListener("message",this.messageListener)}sendConfigToIframe(){if(!this.iframe||!this.iframe.contentWindow){this.iframe&&(this.iframe.onload=()=>{this.sendConfigToIframe()});return}const e={type:"sdkData",config:{...this.config.config||{},paymentId:this.config.config?.paymentId},data:{apiKey:this.config.apiKey}},t=this.getTargetOrigin();this.iframe.contentWindow.postMessage(e,t)}showLoader(e){this.iframe&&(this.iframe.style.display="none");const t=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,i=t?"#2d2d2d":"#F5F5F5",n=t?"#3d3d3d":"#E5E5E5",o=`linear-gradient(90deg, ${n} 25%, ${t?"#4d4d4d":"#F0F0F0"} 50%, ${n} 75%)`,r=document.createElement("div");r.id="inflowpay-loader";const u=this.config.config?.style?.fillParent?"100%":"344px";r.style.cssText=`
49
50
  position: absolute;
50
51
  top: 0;
51
52
  left: 0;
@@ -173,5 +174,5 @@
173
174
  width: 100%;
174
175
  height: 100%;
175
176
  border: none;
176
- `,r.setAttribute("allow","payment"),r.setAttribute("sandbox","allow-forms allow-scripts allow-same-origin allow-popups"),o.appendChild(r),n.appendChild(s),n.appendChild(o),i.appendChild(n),document.body.appendChild(i);const u=i.querySelector("#inflowpay-3ds-close"),c=()=>{i.remove(),window.removeEventListener("message",l),t(!1)};u?.addEventListener("click",c);const l=a=>{if(!a.data)return;const p=["https://dev.api.inflowpay.com","https://pre-prod.api.inflowpay.xyz","https://api.inflowpay.xyz"];if(this.environment==="sandbox"||this.environment==="development"){if(!(a.origin.includes("localhost")||a.origin.includes("127.0.0.1"))){if(!p.includes(a.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",a.origin);return}}}else if(!p.includes(a.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",a.origin);return}const d=a.data,m=d.type==="THREE_DS_COMPLETE"||d.type==="3ds-complete",h=d.status==="success",f=d.status==="failed"||d.status==="failure";if(m&&h){i.remove(),window.removeEventListener("message",l),t(!0);return}if(h&&!m){i.remove(),window.removeEventListener("message",l),t(!0);return}if(m&&f||d.type==="3ds-failed"||f){i.remove(),window.removeEventListener("message",l),t(!1);return}};window.addEventListener("message",l)})}getTargetOrigin(){return this.environment==="production"||this.environment==="preprod"?new URL(this.iframeUrl).origin:"*"}getEnvironmentFromApiKey(e){return!e||e.includes("_local_")||e.startsWith("inflow_local_")?"sandbox":e.includes("_prod_")&&!e.includes("_preprod_")?"production":e.includes("_preprod_")||e.startsWith("inflow_preprod_")?"preprod":e.includes("_dev_")?"development":"sandbox"}destroy(){this.close()}}class b{constructor(e,t){this.mounted=!1;let i;if(typeof t.container=="string"){if(i=document.querySelector(t.container),!i)throw new Error(`Container not found: ${t.container}`)}else i=t.container;this.container=i,this.sdk=new x({iframeUrl:e.iframeUrl,apiKey:e.apiKey,container:this.container,config:{paymentId:t.paymentId,...t.style&&{style:t.style},...t.buttonText&&{buttonText:t.buttonText},...t.placeholders&&{placeholders:t.placeholders}},onSuccess:n=>{t.onComplete&&t.onComplete({status:n?.data?.transaction?.status||"CHECKOUT_SUCCESS",data:n})},onError:n=>{t.onError?t.onError(n):t.onComplete&&t.onComplete({status:"PAYMENT_FAILED",error:n})},onClose:()=>{t.onClose&&t.onClose()}})}mount(){if(this.mounted)throw new Error("CardElement is already mounted");this.sdk.init(),this.mounted=!0}destroy(){this.mounted&&(this.sdk.destroy(),this.mounted=!1)}}class E{constructor(e){if(!e.apiKey||typeof e.apiKey!="string")throw new Error("API key is required");let t=e.iframeUrl;const i=this.getEnvironmentFromApiKey(e.apiKey);t||(i==="production"?t="https://api.inflowpay.xyz/iframe/checkout":i==="preprod"?t="https://pre-prod.api.inflowpay.xyz/iframe/checkout":i==="development"?t="https://dev.api.inflowpay.com/iframe/checkout":t="http://localhost:3000/iframe/checkout");const n=e.debug??!1;n&&(i==="production"||i==="preprod")&&console.warn("[InflowPay SDK] Debug mode is not allowed in production/pre-prod environments. Debug mode disabled.");const s=n&&(i==="sandbox"||i==="development");this.config={apiKey:e.apiKey,iframeUrl:t,timeout:e.timeout??3e4,debug:s}}createCardElement(e){return new b(this.config,e)}getIframeUrl(){return this.config.iframeUrl}getApiKey(){return this.config.apiKey}getEnvironmentFromApiKey(e){return e.includes("_local_")||e.startsWith("inflow_local_")?"sandbox":e.includes("_prod_")&&!e.includes("_preprod_")?"production":e.includes("_preprod_")||e.startsWith("inflow_preprod_")?"preprod":e.includes("_dev_")?"development":"sandbox"}}exports.CardElement=b;exports.PaymentSDK=E;exports.SDK=x;
177
- //# sourceMappingURL=payment-sdk-DRIfoXw9.js.map
177
+ `,r.setAttribute("allow","payment"),r.setAttribute("sandbox","allow-forms allow-scripts allow-same-origin allow-popups"),o.appendChild(r),n.appendChild(s),n.appendChild(o),i.appendChild(n),document.body.appendChild(i);const u=i.querySelector("#inflowpay-3ds-close"),c=()=>{i.remove(),window.removeEventListener("message",l),t(!1)};u?.addEventListener("click",c);const l=a=>{if(!a.data)return;const p=["https://dev.api.inflowpay.com","https://pre-prod.api.inflowpay.xyz","https://api.inflowpay.xyz"];if(this.environment==="sandbox"||this.environment==="development"){if(!(a.origin.includes("localhost")||a.origin.includes("127.0.0.1"))){if(!p.includes(a.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",a.origin);return}}}else if(!p.includes(a.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",a.origin);return}const d=a.data,m=d.type==="THREE_DS_COMPLETE"||d.type==="3ds-complete",h=d.status==="success",f=d.status==="failed"||d.status==="failure";if(m&&h){i.remove(),window.removeEventListener("message",l),t(!0);return}if(h&&!m){i.remove(),window.removeEventListener("message",l),t(!0);return}if(m&&f||d.type==="3ds-failed"||f){i.remove(),window.removeEventListener("message",l),t(!1);return}};window.addEventListener("message",l)})}getTargetOrigin(){return this.environment==="production"||this.environment==="preprod"?new URL(this.iframeUrl).origin:"*"}getEnvironmentFromApiKey(e){return!e||e.includes("_local_")||e.startsWith("inflow_local_")?"sandbox":e.includes("_prod_")&&!e.includes("_preprod_")?"production":e.includes("_preprod_")||e.startsWith("inflow_preprod_")?"preprod":e.includes("_dev_")?"development":"sandbox"}destroy(){this.close()}}class b{constructor(e,t){this.mounted=!1;let i;if(typeof t.container=="string"){if(i=document.querySelector(t.container),!i)throw new Error(`Container not found: ${t.container}`)}else i=t.container;this.container=i,this.sdk=new w({iframeUrl:e.iframeUrl,apiKey:e.apiKey,container:this.container,config:{paymentId:t.paymentId,...t.style&&{style:t.style},...t.buttonText&&{buttonText:t.buttonText},...t.placeholders&&{placeholders:t.placeholders}},onSuccess:n=>{t.onComplete&&t.onComplete({status:n?.data?.transaction?.status||"CHECKOUT_SUCCESS",data:n})},onError:n=>{t.onError?t.onError(n):t.onComplete&&t.onComplete({status:"PAYMENT_FAILED",error:n})},onClose:()=>{t.onClose&&t.onClose()}})}mount(){if(this.mounted)throw new Error("CardElement is already mounted");this.sdk.init(),this.mounted=!0}destroy(){this.mounted&&(this.sdk.destroy(),this.mounted=!1)}}class E{constructor(e){if(!e.apiKey||typeof e.apiKey!="string")throw new Error("API key is required");let t=e.iframeUrl;const i=this.getEnvironmentFromApiKey(e.apiKey);t||(i==="production"?t="https://api.inflowpay.xyz/iframe/checkout":i==="preprod"?t="https://pre-prod.api.inflowpay.xyz/iframe/checkout":i==="development"?t="https://dev.api.inflowpay.com/iframe/checkout":t="http://localhost:3000/iframe/checkout");const n=e.debug??!1;n&&(i==="production"||i==="preprod")&&console.warn("[InflowPay SDK] Debug mode is not allowed in production/pre-prod environments. Debug mode disabled.");const s=n&&(i==="sandbox"||i==="development");this.config={apiKey:e.apiKey,iframeUrl:t,timeout:e.timeout??3e4,debug:s}}createCardElement(e){return new b(this.config,e)}getIframeUrl(){return this.config.iframeUrl}getApiKey(){return this.config.apiKey}getEnvironmentFromApiKey(e){return e.includes("_local_")||e.startsWith("inflow_local_")?"sandbox":e.includes("_prod_")&&!e.includes("_preprod_")?"production":e.includes("_preprod_")||e.startsWith("inflow_preprod_")?"preprod":e.includes("_dev_")?"development":"sandbox"}}exports.CardElement=b;exports.PaymentSDK=E;exports.SDK=w;
178
+ //# sourceMappingURL=payment-sdk-CvXfOxY6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment-sdk-CvXfOxY6.js","sources":["../src/sdk.ts","../src/card-element.ts","../src/payment-sdk.ts"],"sourcesContent":["/**\n * InflowPay SDK v2 - Iframe-based Payment SDK\n * \n * This SDK creates an iframe and communicates with a React payment application\n * using postMessage API for secure cross-origin communication.\n */\n\nimport type { SDKConfig, IframeMessage } from './types';\n\nexport class SDK {\n private iframe: HTMLIFrameElement | null = null;\n private iframeUrl: string;\n private config: SDKConfig;\n private messageListener: ((event: MessageEvent) => void) | null = null;\n private containerElement: HTMLElement | null = null;\n private usePopup: boolean;\n private environment: 'sandbox' | 'production' | 'development' | 'preprod';\n\n constructor(config: SDKConfig) {\n this.config = config;\n this.iframeUrl = config.iframeUrl || 'http://localhost:3000/iframe/checkout';\n this.environment = this.getEnvironmentFromApiKey(config.apiKey || '');\n\n // Determine if we should use popup or inline\n this.usePopup = !config.container;\n\n // Resolve container if provided\n if (config.container) {\n if (typeof config.container === 'string') {\n this.containerElement = document.querySelector(config.container);\n if (!this.containerElement) {\n throw new Error(`Container not found: ${config.container}`);\n }\n } else {\n this.containerElement = config.container;\n }\n }\n }\n\n /**\n * Initialize and open the payment iframe\n */\n init(): void {\n if (this.iframe) {\n return;\n }\n\n this.createIframe();\n this.addMessageListener();\n }\n\n /**\n * Create and append the iframe to the document\n */\n private createIframe(): void {\n // Build iframe URL with API key and paymentId as query parameters\n const url = new URL(this.iframeUrl);\n if (this.config.apiKey) {\n url.searchParams.set('apiKey', this.config.apiKey);\n }\n if (this.config.config?.paymentId) {\n url.searchParams.set('paymentId', this.config.config.paymentId);\n }\n const iframeSrc = url.toString();\n\n if (this.usePopup) {\n // Create overlay for popup mode\n const overlay = document.createElement('div');\n overlay.id = 'inflowpay-sdk-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n `;\n\n // Create iframe container\n const container = document.createElement('div');\n container.style.cssText = `\n position: relative;\n width: 90%;\n max-width: 500px;\n height: 90%;\n max-height: 600px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n `;\n\n // Create close button\n const closeButton = document.createElement('button');\n closeButton.innerHTML = '×';\n closeButton.style.cssText = `\n position: absolute;\n top: 10px;\n right: 10px;\n width: 30px;\n height: 30px;\n border: none;\n background: transparent;\n font-size: 24px;\n cursor: pointer;\n z-index: 1000000;\n color: #333;\n display: flex;\n align-items: center;\n justify-content: center;\n `;\n closeButton.onclick = () => this.close();\n\n // Create iframe\n this.iframe = document.createElement('iframe');\n this.iframe.src = iframeSrc;\n this.iframe.style.cssText = `\n width: 100%;\n height: 100%;\n border: none;\n border-radius: 8px;\n `;\n this.iframe.setAttribute('allow', 'payment');\n\n // Assemble structure\n container.appendChild(closeButton);\n container.appendChild(this.iframe);\n overlay.appendChild(container);\n document.body.appendChild(overlay);\n\n // Show loader\n this.showLoader(container);\n\n // Close on overlay click (but not on container click)\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n this.close();\n }\n });\n } else {\n // Inline mode - mount directly in container\n if (!this.containerElement) {\n throw new Error('Container element is required for inline mode');\n }\n\n // Clear container\n this.containerElement.innerHTML = '';\n\n // Set container styles for seamless integration\n if (this.containerElement instanceof HTMLElement) {\n const currentStyle = this.containerElement.getAttribute('style') || '';\n if (!currentStyle.includes('min-height')) {\n this.containerElement.style.minHeight = '196px';\n }\n if (!currentStyle.includes('position')) {\n this.containerElement.style.position = 'relative';\n }\n if (!currentStyle.includes('overflow')) {\n this.containerElement.style.overflow = 'hidden';\n }\n }\n\n // Create iframe\n this.iframe = document.createElement('iframe');\n this.iframe.src = iframeSrc;\n\n const iframeWidth = this.config.config?.style?.fillParent ? '100%' : '344px';\n const iframeMaxWidth = this.config.config?.style?.fillParent ? 'none' : '100%';\n\n this.iframe.style.cssText = `\n width: ${iframeWidth};\n max-width: ${iframeMaxWidth};\n height: 196px;\n min-height: 196px;\n border: none;\n display: block;\n transition: height 0.2s ease;\n `;\n\n this.iframe.setAttribute('allow', 'payment');\n\n // Append to container\n this.containerElement.appendChild(this.iframe);\n\n // Show loader\n this.showLoader(this.containerElement);\n }\n }\n\n /**\n * Add message listener for communication with iframe\n */\n private addMessageListener(): void {\n this.messageListener = (event: MessageEvent) => {\n const allowedOrigin = new URL(this.iframeUrl).origin;\n const isExactMatch = event.origin === allowedOrigin;\n\n let isAllowedOrigin = isExactMatch;\n\n if (!isAllowedOrigin) {\n if (this.environment === 'sandbox' || this.environment === 'development') {\n const isLocalhostDev =\n (event.origin.includes('localhost') || event.origin.includes('127.0.0.1')) &&\n (allowedOrigin.includes('localhost') || allowedOrigin.includes('127.0.0.1'));\n isAllowedOrigin = isLocalhostDev;\n }\n\n if (!isAllowedOrigin) {\n const isAllowedApiOrigin =\n event.origin === 'https://dev.api.inflowpay.com' ||\n event.origin === 'https://pre-prod.api.inflowpay.xyz' ||\n event.origin === 'https://api.inflowpay.xyz';\n isAllowedOrigin = isAllowedApiOrigin;\n }\n }\n\n if (!isAllowedOrigin) {\n if (this.config.debug) {\n console.warn('[SDK] Rejected message from unauthorized origin:', event.origin);\n }\n return;\n }\n\n const data = event.data as IframeMessage;\n\n if (!data || !data.type) {\n return;\n }\n\n switch (data.type) {\n case 'iframe-ready':\n // Wait for iframe's javascript to be ready before sending config\n this.hideLoader();\n this.sendConfigToIframe();\n break;\n\n case 'content-height':\n // Adjust iframe height based on content\n if (data.height && this.iframe) {\n const height = Math.max(data.height, 196); // Minimum 196px\n this.iframe.style.height = `${height}px`;\n if (this.containerElement) {\n this.containerElement.style.minHeight = `${height}px`;\n }\n }\n break;\n\n case 'close':\n this.close();\n break;\n\n case 'success':\n if (this.config.onSuccess) {\n this.config.onSuccess(data.data);\n }\n break;\n\n case 'error':\n if (this.config.onError) {\n this.config.onError(data.data);\n }\n break;\n\n case '3ds-required':\n // Iframe requests SDK to open 3DS popup\n if (this.config.debug) {\n console.log('[SDK] Received 3DS request:', data.threeDsSessionUrl);\n }\n if (data.threeDsSessionUrl) {\n if (this.config.debug) {\n console.log('[SDK] Opening 3DS modal...');\n }\n this.open3DSModal(data.threeDsSessionUrl).then((success) => {\n if (this.config.debug) {\n console.log('[SDK] 3DS modal closed, result:', success);\n }\n if (this.iframe && this.iframe.contentWindow) {\n const targetOrigin = this.getTargetOrigin();\n this.iframe.contentWindow.postMessage({\n type: '3ds-result',\n success: success,\n paymentId: data.paymentId || this.config.config?.paymentId,\n }, targetOrigin);\n }\n });\n } else {\n if (this.config.debug) {\n console.error('[SDK] 3DS required but no threeDsSessionUrl provided');\n }\n }\n break;\n\n default:\n if (this.config.debug) {\n console.log('SDK: Received message:', data);\n }\n }\n };\n\n window.addEventListener('message', this.messageListener);\n }\n\n /**\n * Send configuration to the iframe\n */\n private sendConfigToIframe(): void {\n if (!this.iframe || !this.iframe.contentWindow) {\n // Wait for iframe to load\n if (this.iframe) {\n this.iframe.onload = () => {\n this.sendConfigToIframe();\n };\n }\n return;\n }\n\n const message: IframeMessage = {\n type: 'sdkData',\n config: {\n ...(this.config.config || {}),\n paymentId: this.config.config?.paymentId\n },\n data: {\n apiKey: this.config.apiKey,\n },\n };\n\n const targetOrigin = this.getTargetOrigin();\n this.iframe.contentWindow.postMessage(message, targetOrigin);\n }\n\n /**\n * Show skeleton loader while iframe is connecting\n */\n private showLoader(container: HTMLElement): void {\n // Hide iframe while loader is showing\n if (this.iframe) {\n this.iframe.style.display = 'none';\n }\n \n // Detect dark mode\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n \n // Color scheme based on dark mode\n const inputBgColor = isDarkMode ? '#2d2d2d' : '#F5F5F5';\n const shimmerBase = isDarkMode ? '#3d3d3d' : '#E5E5E5';\n const shimmerLight = isDarkMode ? '#4d4d4d' : '#F0F0F0';\n const shimmerGradient = `linear-gradient(90deg, ${shimmerBase} 25%, ${shimmerLight} 50%, ${shimmerBase} 75%)`;\n \n const loader = document.createElement('div');\n loader.id = 'inflowpay-loader';\n \n // Get container width to match SDK structure\n const containerWidth = this.config.config?.style?.fillParent ? '100%' : '344px';\n \n loader.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1000;\n padding: 20px;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n align-items: center;\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n `;\n\n // Skeleton card element container (matching .inflowpay-card-element)\n const skeletonCard = document.createElement('div');\n skeletonCard.style.cssText = `\n width: ${containerWidth};\n max-width: 100%;\n margin: 0 auto;\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n `;\n\n // Input container skeleton (matching .inflowpay-card-inp-wrap)\n const inputWrap = document.createElement('div');\n inputWrap.style.cssText = `\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n background-color: ${inputBgColor};\n padding: 8px;\n border-radius: 8px;\n margin-bottom: 20px;\n `;\n\n // Card number skeleton (flex: 1)\n const cardNumberSkeleton = document.createElement('div');\n cardNumberSkeleton.className = 'inflowpay-skeleton';\n cardNumberSkeleton.style.cssText = `\n flex: 1;\n min-width: 0;\n height: 32px;\n border-radius: 6px;\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n `;\n\n // Expiry skeleton (21.5% width)\n const expirySkeleton = document.createElement('div');\n expirySkeleton.className = 'inflowpay-skeleton';\n expirySkeleton.style.cssText = `\n width: 21.5%;\n flex-shrink: 0;\n height: 32px;\n border-radius: 6px;\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n `;\n\n // CVC skeleton (17.5% width)\n const cvcSkeleton = document.createElement('div');\n cvcSkeleton.className = 'inflowpay-skeleton';\n cvcSkeleton.style.cssText = `\n width: 17.5%;\n flex-shrink: 0;\n height: 32px;\n border-radius: 6px;\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n `;\n\n inputWrap.appendChild(cardNumberSkeleton);\n inputWrap.appendChild(expirySkeleton);\n inputWrap.appendChild(cvcSkeleton);\n\n // Button skeleton (matching .inflowpay-button)\n const buttonSkeleton = document.createElement('div');\n buttonSkeleton.className = 'inflowpay-skeleton';\n buttonSkeleton.style.cssText = `\n width: 100%;\n height: 42px;\n border-radius: 8px;\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n margin-bottom: 16px;\n `;\n\n // Disclaimer skeleton (matching .inflowpay-disclaimer)\n const disclaimerSkeleton = document.createElement('div');\n disclaimerSkeleton.style.cssText = `\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n width: 100%;\n margin-top: 16px;\n `;\n\n const disclaimerIconSkeleton = document.createElement('div');\n disclaimerIconSkeleton.className = 'inflowpay-skeleton';\n disclaimerIconSkeleton.style.cssText = `\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n `;\n\n const disclaimerTextSkeleton = document.createElement('div');\n disclaimerTextSkeleton.className = 'inflowpay-skeleton';\n disclaimerTextSkeleton.style.cssText = `\n width: 80%;\n height: 16px;\n border-radius: 4px;\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n `;\n\n disclaimerSkeleton.appendChild(disclaimerIconSkeleton);\n disclaimerSkeleton.appendChild(disclaimerTextSkeleton);\n\n skeletonCard.appendChild(inputWrap);\n skeletonCard.appendChild(buttonSkeleton);\n skeletonCard.appendChild(disclaimerSkeleton);\n loader.appendChild(skeletonCard);\n\n // Add shimmer animation keyframes\n if (!document.getElementById('inflowpay-loader-styles')) {\n const style = document.createElement('style');\n style.id = 'inflowpay-loader-styles';\n style.textContent = `\n @keyframes inflowpay-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n }\n `;\n document.head.appendChild(style);\n }\n\n container.appendChild(loader);\n }\n\n /**\n * Hide loader\n */\n private hideLoader(): void {\n const loader = document.getElementById('inflowpay-loader');\n if (loader) {\n loader.remove();\n }\n \n // Show iframe again when loader is hidden\n if (this.iframe) {\n this.iframe.style.display = '';\n }\n }\n\n /**\n * Close the iframe and cleanup\n */\n private close(): void {\n if (this.config.onClose) {\n this.config.onClose();\n }\n\n // Hide loader\n this.hideLoader();\n\n // Remove message listener\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n\n if (this.usePopup) {\n // Remove overlay\n const overlay = document.getElementById('inflowpay-sdk-overlay');\n if (overlay) {\n overlay.remove();\n }\n } else {\n // Clear container\n if (this.containerElement) {\n this.containerElement.innerHTML = '';\n }\n }\n\n this.iframe = null;\n }\n\n /**\n * Open 3DS authentication modal\n * Called when iframe requests 3DS authentication\n */\n private open3DSModal(challengeUrl: string): Promise<boolean> {\n if (this.config.debug) {\n console.log('[SDK] open3DSModal called with URL:', challengeUrl);\n }\n return new Promise((resolve) => {\n // Create overlay\n const overlay = document.createElement('div');\n overlay.id = 'inflowpay-3ds-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.7);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n `;\n\n // Create modal\n const modal = document.createElement('div');\n modal.style.cssText = `\n position: relative;\n width: 90%;\n max-width: 500px;\n height: 90%;\n max-height: 600px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n `;\n\n // Create header\n const header = document.createElement('div');\n header.style.cssText = `\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 15px 20px;\n border-bottom: 1px solid #e5e5e5;\n `;\n header.innerHTML = `\n <h3 style=\"margin: 0; font-size: 18px; font-weight: 600;\">Secure Payment Authentication</h3>\n <button id=\"inflowpay-3ds-close\" style=\"background: none; border: none; font-size: 24px; cursor: pointer; padding: 0; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; color: #333;\">×</button>\n `;\n\n // Create content with iframe\n const content = document.createElement('div');\n content.style.cssText = `\n flex: 1;\n position: relative;\n overflow: hidden;\n `;\n const iframe = document.createElement('iframe');\n iframe.src = challengeUrl;\n iframe.style.cssText = `\n width: 100%;\n height: 100%;\n border: none;\n `;\n iframe.setAttribute('allow', 'payment');\n iframe.setAttribute('sandbox', 'allow-forms allow-scripts allow-same-origin allow-popups');\n content.appendChild(iframe);\n\n modal.appendChild(header);\n modal.appendChild(content);\n overlay.appendChild(modal);\n document.body.appendChild(overlay);\n\n // Close button handler\n const closeBtn = overlay.querySelector('#inflowpay-3ds-close');\n const closeHandler = () => {\n overlay.remove();\n window.removeEventListener('message', messageHandler);\n resolve(false);\n };\n closeBtn?.addEventListener('click', closeHandler);\n\n const messageHandler = (event: MessageEvent) => {\n if (!event.data) return;\n\n const allowed3DSOrigins = [\n 'https://dev.api.inflowpay.com',\n 'https://pre-prod.api.inflowpay.xyz',\n 'https://api.inflowpay.xyz',\n ];\n\n if (this.environment === 'sandbox' || this.environment === 'development') {\n if (event.origin.includes('localhost') || event.origin.includes('127.0.0.1')) {\n // Allow localhost in dev/sandbox\n } else if (!allowed3DSOrigins.includes(event.origin)) {\n if (this.config.debug) {\n console.warn('[SDK] Rejected 3DS message from unauthorized origin:', event.origin);\n }\n return;\n }\n } else {\n if (!allowed3DSOrigins.includes(event.origin)) {\n if (this.config.debug) {\n console.warn('[SDK] Rejected 3DS message from unauthorized origin:', event.origin);\n }\n return;\n }\n }\n\n const data = event.data;\n const is3DSComplete = data.type === 'THREE_DS_COMPLETE' || data.type === '3ds-complete';\n const isSuccess = data.status === 'success';\n const isFailure = data.status === 'failed' || data.status === 'failure';\n\n // Success case\n if (is3DSComplete && isSuccess) {\n overlay.remove();\n window.removeEventListener('message', messageHandler);\n resolve(true);\n return;\n }\n\n // Also handle legacy format\n if (isSuccess && !is3DSComplete) {\n overlay.remove();\n window.removeEventListener('message', messageHandler);\n resolve(true);\n return;\n }\n\n // Failure case\n if ((is3DSComplete && isFailure) || data.type === '3ds-failed' || isFailure) {\n overlay.remove();\n window.removeEventListener('message', messageHandler);\n resolve(false);\n return;\n }\n };\n\n window.addEventListener('message', messageHandler);\n });\n }\n\n /**\n * Get target origin for postMessage based on environment\n * In production/pre-prod: use exact origin for security\n * In dev/sandbox: use wildcard for development flexibility\n */\n private getTargetOrigin(): string {\n if (this.environment === 'production' || this.environment === 'preprod') {\n return new URL(this.iframeUrl).origin;\n }\n return '*';\n }\n\n /**\n * Detect environment from API key\n */\n private getEnvironmentFromApiKey(apiKey: string): 'sandbox' | 'production' | 'development' | 'preprod' {\n if (!apiKey) return 'sandbox';\n if (apiKey.includes('_local_') || apiKey.startsWith('inflow_local_')) {\n return 'sandbox';\n } else if (apiKey.includes('_prod_') && !apiKey.includes('_preprod_')) {\n return 'production';\n } else if (apiKey.includes('_preprod_') || apiKey.startsWith('inflow_preprod_')) {\n return 'preprod';\n } else if (apiKey.includes('_dev_')) {\n return 'development';\n }\n return 'sandbox';\n }\n\n /**\n * Public method to close the iframe\n */\n public destroy(): void {\n this.close();\n }\n}\n\n","/**\n * CardElement - Iframe-based payment element\n * \n * Mounts an iframe with the payment checkout form\n */\n\nimport { SDK } from './sdk';\n\nimport type { CSSProperties } from './types';\n\nexport interface CardElementOptions {\n /** Container element or CSS selector where the iframe will be mounted */\n container: string | HTMLElement;\n /** Payment ID for this transaction */\n paymentId: string;\n /** Callback when payment completes */\n onComplete?: (result: { status: string; data?: any; error?: any }) => void;\n /** Callback when payment fails */\n onError?: (error: any) => void;\n /** Callback when user closes the payment */\n onClose?: () => void;\n /** Custom styling for the card element */\n style?: CSSProperties;\n /** Custom button text (default: \"Complete Payment\") */\n buttonText?: string;\n /** Custom placeholder text for inputs */\n placeholders?: {\n cardNumber?: string;\n expiry?: string;\n cvc?: string;\n };\n}\n\ninterface InternalSDKConfig {\n apiKey: string;\n iframeUrl: string;\n timeout: number;\n debug: boolean;\n}\n\nexport class CardElement {\n private sdk: SDK;\n private container: HTMLElement;\n private mounted: boolean = false;\n\n constructor(\n config: InternalSDKConfig,\n options: CardElementOptions\n ) {\n let containerElement: HTMLElement | null;\n if (typeof options.container === 'string') {\n containerElement = document.querySelector(options.container);\n if (!containerElement) {\n throw new Error(`Container not found: ${options.container}`);\n }\n } else {\n containerElement = options.container;\n }\n this.container = containerElement;\n\n this.sdk = new SDK({\n iframeUrl: config.iframeUrl,\n apiKey: config.apiKey,\n container: this.container,\n config: {\n paymentId: options.paymentId,\n ...(options.style && { style: options.style }),\n ...(options.buttonText && { buttonText: options.buttonText }),\n ...(options.placeholders && { placeholders: options.placeholders }),\n },\n onSuccess: (data) => {\n if (options.onComplete) {\n options.onComplete({\n status: data?.data?.transaction?.status || 'CHECKOUT_SUCCESS',\n data: data,\n });\n }\n },\n onError: (error) => {\n if (options.onError) {\n options.onError(error);\n } else if (options.onComplete) {\n options.onComplete({\n status: 'PAYMENT_FAILED',\n error: error,\n });\n }\n },\n onClose: () => {\n if (options.onClose) {\n options.onClose();\n }\n },\n });\n }\n\n /**\n * Mount the CardElement to the DOM\n * This will create and display the iframe\n */\n mount(): void {\n if (this.mounted) {\n throw new Error('CardElement is already mounted');\n }\n\n this.sdk.init();\n this.mounted = true;\n }\n\n /**\n * Destroy the CardElement and cleanup\n */\n destroy(): void {\n if (this.mounted) {\n this.sdk.destroy();\n this.mounted = false;\n }\n }\n}\n","/**\n * InflowPay Payment SDK v2\n * \n * Provider class that manages global SDK configuration\n * Similar to the original SDK but uses iframe-based payment flow\n */\n\nimport type { SDKConfig, PaymentConfig, CSSProperties } from './types';\nimport { CardElement } from './card-element';\n\nexport interface PaymentSDKConfig {\n /** Public API key */\n apiKey: string;\n /** Backend API URL (optional, auto-detected from API key) */\n iframeUrl?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Enable debug logging (default: false, only allowed in local/dev environments) */\n debug?: boolean;\n}\n\nexport class PaymentSDK {\n private config: PaymentSDKConfig & { iframeUrl: string; timeout: number; debug: boolean };\n\n /**\n * Initialize the InflowPay Payment SDK\n * \n * @param config - SDK configuration\n * \n * @example\n * ```typescript\n * const sdk = new PaymentSDK({\n * apiKey: 'inflow_pub_local_xxx'\n * });\n * ```\n */\n constructor(config: PaymentSDKConfig) {\n // Validate API key\n if (!config.apiKey || typeof config.apiKey !== 'string') {\n throw new Error('API key is required');\n }\n\n // Auto-detect iframe URL from API key if not provided\n let iframeUrl = config.iframeUrl;\n const environment = this.getEnvironmentFromApiKey(config.apiKey);\n \n if (!iframeUrl) {\n if (environment === 'production') {\n iframeUrl = 'https://api.inflowpay.xyz/iframe/checkout';\n } else if (environment === 'preprod') {\n iframeUrl = 'https://pre-prod.api.inflowpay.xyz/iframe/checkout';\n } else if (environment === 'development') {\n iframeUrl = 'https://dev.api.inflowpay.com/iframe/checkout';\n } else {\n // sandbox/local\n iframeUrl = 'http://localhost:3000/iframe/checkout';\n }\n }\n\n // Validate debug mode - only allowed in local/dev environments\n const requestedDebug = config.debug ?? false;\n if (requestedDebug && (environment === 'production' || environment === 'preprod')) {\n console.warn('[InflowPay SDK] Debug mode is not allowed in production/pre-prod environments. Debug mode disabled.');\n }\n const debug = requestedDebug && (environment === 'sandbox' || environment === 'development');\n\n this.config = {\n apiKey: config.apiKey,\n iframeUrl,\n timeout: config.timeout ?? 30000,\n debug,\n };\n }\n\n /**\n * Create a CardElement for iframe-based payment UI\n * \n * @param options - CardElement configuration\n * @returns CardElement instance\n * \n * @example\n * ```typescript\n * const cardElement = sdk.createCardElement({\n * container: '#card-container',\n * paymentId: 'pay_123',\n * onComplete: (result) => {\n * if (result.status === 'CHECKOUT_SUCCESS') {\n * window.location.href = '/success';\n * }\n * }\n * });\n * \n * cardElement.mount();\n * ```\n */\n createCardElement(options: {\n container: string | HTMLElement;\n paymentId: string;\n style?: CSSProperties;\n buttonText?: string;\n placeholders?: {\n cardNumber?: string;\n expiry?: string;\n cvc?: string;\n };\n onComplete?: (result: { status: string; data?: any; error?: any }) => void;\n onError?: (error: any) => void;\n onClose?: () => void;\n }): CardElement {\n return new CardElement(this.config, options);\n }\n\n /**\n * Get the iframe URL being used\n */\n getIframeUrl(): string {\n return this.config.iframeUrl;\n }\n\n /**\n * Get the API key\n */\n getApiKey(): string {\n return this.config.apiKey;\n }\n\n /**\n * Auto-detect environment from API key\n */\n private getEnvironmentFromApiKey(apiKey: string): 'sandbox' | 'production' | 'development' | 'preprod' {\n if (apiKey.includes('_local_') || apiKey.startsWith('inflow_local_')) {\n return 'sandbox';\n } else if (apiKey.includes('_prod_') && !apiKey.includes('_preprod_')) {\n return 'production';\n } else if (apiKey.includes('_preprod_') || apiKey.startsWith('inflow_preprod_')) {\n return 'preprod';\n } else if (apiKey.includes('_dev_')) {\n return 'development';\n }\n return 'sandbox';\n }\n}\n\n"],"names":["SDK","config","url","iframeSrc","overlay","container","closeButton","e","currentStyle","iframeWidth","iframeMaxWidth","event","allowedOrigin","isAllowedOrigin","data","height","success","targetOrigin","message","isDarkMode","inputBgColor","shimmerBase","shimmerGradient","loader","containerWidth","skeletonCard","inputWrap","cardNumberSkeleton","expirySkeleton","cvcSkeleton","buttonSkeleton","disclaimerSkeleton","disclaimerIconSkeleton","disclaimerTextSkeleton","style","challengeUrl","resolve","modal","header","content","iframe","closeBtn","closeHandler","messageHandler","allowed3DSOrigins","is3DSComplete","isSuccess","isFailure","apiKey","CardElement","options","containerElement","error","PaymentSDK","iframeUrl","environment","requestedDebug","debug"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- class x {
1
+ class w {
2
2
  constructor(e) {
3
3
  if (this.iframe = null, this.messageListener = null, this.containerElement = null, this.config = e, this.iframeUrl = e.iframeUrl || "http://localhost:3000/iframe/checkout", this.environment = this.getEnvironmentFromApiKey(e.apiKey || ""), this.usePopup = !e.container, e.container)
4
4
  if (typeof e.container == "string") {
@@ -81,10 +81,11 @@ class x {
81
81
  this.iframe.style.cssText = `
82
82
  width: ${i};
83
83
  max-width: ${n};
84
- height: 100%;
84
+ height: 196px;
85
85
  min-height: 196px;
86
86
  border: none;
87
87
  display: block;
88
+ transition: height 0.2s ease;
88
89
  `, this.iframe.setAttribute("allow", "payment"), this.containerElement.appendChild(this.iframe), this.showLoader(this.containerElement);
89
90
  }
90
91
  }
@@ -105,6 +106,12 @@ class x {
105
106
  case "iframe-ready":
106
107
  this.hideLoader(), this.sendConfigToIframe();
107
108
  break;
109
+ case "content-height":
110
+ if (s.height && this.iframe) {
111
+ const o = Math.max(s.height, 196);
112
+ this.iframe.style.height = `${o}px`, this.containerElement && (this.containerElement.style.minHeight = `${o}px`);
113
+ }
114
+ break;
108
115
  case "close":
109
116
  this.close();
110
117
  break;
@@ -416,7 +423,7 @@ class b {
416
423
  throw new Error(`Container not found: ${t.container}`);
417
424
  } else
418
425
  i = t.container;
419
- this.container = i, this.sdk = new x({
426
+ this.container = i, this.sdk = new w({
420
427
  iframeUrl: e.iframeUrl,
421
428
  apiKey: e.apiKey,
422
429
  container: this.container,
@@ -534,6 +541,6 @@ class E {
534
541
  export {
535
542
  b as C,
536
543
  E as P,
537
- x as S
544
+ w as S
538
545
  };
539
- //# sourceMappingURL=payment-sdk-DCTbabp6.mjs.map
546
+ //# sourceMappingURL=payment-sdk-DK3VOIGL.mjs.map