@inflow_pay/sdk 0.7.0 → 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/CHANGELOG.md +7 -0
- package/README.md +254 -587
- package/dist/payment-sdk-CC-mm-nt.js +169 -0
- package/dist/payment-sdk-CC-mm-nt.js.map +1 -0
- package/dist/payment-sdk-oRqgQSx5.mjs +821 -0
- package/dist/payment-sdk-oRqgQSx5.mjs.map +1 -0
- package/dist/react/index.d.ts +37 -39
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.esm.js +8 -89
- package/dist/react.esm.js.map +1 -1
- package/dist/react.umd.js +170 -179
- package/dist/react.umd.js.map +1 -1
- package/dist/sdk.cjs +1 -1
- package/dist/sdk.cjs.map +1 -1
- package/dist/sdk.d.ts +43 -160
- package/dist/sdk.esm.js +21 -24
- package/dist/sdk.esm.js.map +1 -1
- package/dist/sdk.umd.js +216 -176
- package/dist/sdk.umd.js.map +1 -1
- package/package.json +6 -6
- package/dist/payment-sdk-CvXfOxY6.js +0 -178
- package/dist/payment-sdk-CvXfOxY6.js.map +0 -1
- package/dist/payment-sdk-DK3VOIGL.mjs +0 -546
- package/dist/payment-sdk-DK3VOIGL.mjs.map +0 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";const k=require("react/jsx-runtime"),g=require("react");var I=(t=>(t.SUCCESS="SUCCESS",t.FAILED="FAILED",t))(I||{}),_=(t=>(t.THREE_DS_FAILED="THREE_DS_FAILED",t.PAYMENT_PROCESSING_ERROR="PAYMENT_PROCESSING_ERROR",t))(_||{});const L=g.createContext(null);function $({config:t,children:e}){const[n]=g.useState(()=>{const o={publicKey:t.publicKey,locale:t.locale};return new A(o)});return k.jsx(L.Provider,{value:{sdk:n},children:e})}function K(){const t=g.useContext(L);if(!t)throw new Error("useInflowPay must be used within InflowPayProvider");return t.sdk}function U(t){const{paymentId:e,onReady:n,onChange:o,onComplete:s,onError:i,style:r,buttonText:a,placeholders:u,showDefaultSuccessUI:h,config:m}=t,p=g.useContext(L),l=g.useRef(null),f=g.useRef(null),[y,v]=g.useState(!1),D=p?.sdk||(m?new A({publicKey:m.publicKey,locale:m.locale}):null);if(!D)throw new Error("CardElement must be used within InflowPayProvider or have a config prop");return g.useEffect(()=>{if(!l.current)return;l.current.id||(l.current.id=`inflowpay-card-element-${Date.now()}`);const H={container:l.current,paymentId:e,...r&&{style:r},...a&&{buttonText:a},...u&&{placeholders:u},...h!==void 0&&{showDefaultSuccessUI:h},onComplete:w=>{s&&s(w)},onError:w=>{i?i(w):s&&s({status:I.FAILED,paymentId:e,error:w})},onClose:()=>{}},O=D.createCardElement(H);if(f.current=O,O.mount(),v(!0),n){const w=setTimeout(()=>{n()},100);return()=>clearTimeout(w)}},[e,D,s,i,n,r,a,u,h]),g.useEffect(()=>{o&&y&&o({complete:!1})},[y,o]),g.useEffect(()=>()=>{f.current&&(f.current.destroy(),f.current=null)},[]),k.jsx("div",{ref:l,style:{width:r?.fillParent?"100%":"344px"}})}const T={OVERLAY:999999,MODAL:1e6,LOADER:1e3},c={MIN_HEIGHT:196,CONTAINER_MAX_WIDTH:"500px",CONTAINER_WIDTH_PERCENT:"90%",CONTAINER_HEIGHT_PERCENT:"90%",CONTAINER_MAX_HEIGHT:"600px",BUTTON_SIZE:30,DEFAULT_IFRAME_WIDTH:"344px"},F=["https://dev.api.inflowpay.xyz","https://pre-prod.api.inflowpay.xyz","https://api.inflowpay.xyz"],E={OVERLAY:"inflowpay-sdk-overlay",LOADER:"inflowpay-loader",LOADER_STYLES:"inflowpay-loader-styles",THREE_DS_OVERLAY:"inflowpay-3ds-overlay"},b={PRODUCTION:"https://iframe.inflowpay.com/iframe/checkout",PREPROD:"https://preprod.iframe.inflowpay.com/iframe/checkout",DEVELOPMENT:"https://dev.iframe.inflowpay.com/iframe/checkout",LOCAL:"http://localhost:3010/iframe/checkout"};function W(t){return{inputBgColor:t?"#2d2d2d":"#F5F5F5",shimmerBase:t?"#3d3d3d":"#E5E5E5",shimmerLight:t?"#4d4d4d":"#F0F0F0"}}function B(t){return`linear-gradient(90deg, ${t.shimmerBase} 25%, ${t.shimmerLight} 50%, ${t.shimmerBase} 75%)`}function G(){return`
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
z-index: ${T.OVERLAY};
|
|
12
|
+
`}function z(){return`
|
|
13
|
+
position: relative;
|
|
14
|
+
width: ${c.CONTAINER_WIDTH_PERCENT};
|
|
15
|
+
max-width: ${c.CONTAINER_MAX_WIDTH};
|
|
16
|
+
height: ${c.CONTAINER_HEIGHT_PERCENT};
|
|
17
|
+
max-height: ${c.CONTAINER_MAX_HEIGHT};
|
|
18
|
+
background: white;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
21
|
+
`}function Y(){return`
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: 10px;
|
|
24
|
+
right: 10px;
|
|
25
|
+
width: ${c.BUTTON_SIZE}px;
|
|
26
|
+
height: ${c.BUTTON_SIZE}px;
|
|
27
|
+
border: none;
|
|
28
|
+
background: transparent;
|
|
29
|
+
font-size: 24px;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
z-index: ${T.MODAL};
|
|
32
|
+
color: #333;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
`}function j(){return`
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 100%;
|
|
39
|
+
border: none;
|
|
40
|
+
border-radius: 8px;
|
|
41
|
+
`}function q(t){return`
|
|
42
|
+
width: ${t?"100%":c.DEFAULT_IFRAME_WIDTH};
|
|
43
|
+
max-width: ${t?"none":"100%"};
|
|
44
|
+
height: ${c.MIN_HEIGHT}px;
|
|
45
|
+
min-height: ${c.MIN_HEIGHT}px;
|
|
46
|
+
border: none;
|
|
47
|
+
display: block;
|
|
48
|
+
transition: height 0.2s ease;
|
|
49
|
+
`}function V(){return`
|
|
50
|
+
position: absolute;
|
|
51
|
+
top: 0;
|
|
52
|
+
left: 0;
|
|
53
|
+
width: 100%;
|
|
54
|
+
height: 100%;
|
|
55
|
+
z-index: ${T.LOADER};
|
|
56
|
+
padding: 20px;
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
align-items: center;
|
|
61
|
+
`}function X(t){return`
|
|
62
|
+
width: ${t?"100%":c.DEFAULT_IFRAME_WIDTH};
|
|
63
|
+
max-width: 100%;
|
|
64
|
+
margin: 0 auto;
|
|
65
|
+
`}function Z(t){return`
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
justify-content: center;
|
|
69
|
+
gap: 6px;
|
|
70
|
+
background-color: ${t};
|
|
71
|
+
padding: 8px;
|
|
72
|
+
border-radius: 8px;
|
|
73
|
+
margin-bottom: 20px;
|
|
74
|
+
`}function S(t){return`
|
|
75
|
+
background: ${t};
|
|
76
|
+
background-size: 200% 100%;
|
|
77
|
+
animation: inflowpay-shimmer 1.5s infinite;
|
|
78
|
+
`}function J(t){return`
|
|
79
|
+
flex: 1;
|
|
80
|
+
min-width: 0;
|
|
81
|
+
height: 32px;
|
|
82
|
+
border-radius: 6px;
|
|
83
|
+
${S(t)}
|
|
84
|
+
`}function Q(t){return`
|
|
85
|
+
width: 21.5%;
|
|
86
|
+
flex-shrink: 0;
|
|
87
|
+
height: 32px;
|
|
88
|
+
border-radius: 6px;
|
|
89
|
+
${S(t)}
|
|
90
|
+
`}function ee(t){return`
|
|
91
|
+
width: 17.5%;
|
|
92
|
+
flex-shrink: 0;
|
|
93
|
+
height: 32px;
|
|
94
|
+
border-radius: 6px;
|
|
95
|
+
${S(t)}
|
|
96
|
+
`}function te(t){return`
|
|
97
|
+
width: 100%;
|
|
98
|
+
height: 42px;
|
|
99
|
+
border-radius: 8px;
|
|
100
|
+
${S(t)}
|
|
101
|
+
margin-bottom: 16px;
|
|
102
|
+
`}function ne(){return`
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: column;
|
|
105
|
+
align-items: center;
|
|
106
|
+
gap: 4px;
|
|
107
|
+
width: 100%;
|
|
108
|
+
margin-top: 16px;
|
|
109
|
+
`}function ie(t){return`
|
|
110
|
+
width: 10px;
|
|
111
|
+
height: 10px;
|
|
112
|
+
border-radius: 50%;
|
|
113
|
+
${S(t)}
|
|
114
|
+
`}function se(t){return`
|
|
115
|
+
width: 80%;
|
|
116
|
+
height: 16px;
|
|
117
|
+
border-radius: 4px;
|
|
118
|
+
${S(t)}
|
|
119
|
+
`}const oe=`
|
|
120
|
+
@keyframes inflowpay-shimmer {
|
|
121
|
+
0% {
|
|
122
|
+
background-position: -200% 0;
|
|
123
|
+
}
|
|
124
|
+
100% {
|
|
125
|
+
background-position: 200% 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
`;function re(){return`
|
|
129
|
+
position: fixed;
|
|
130
|
+
top: 0;
|
|
131
|
+
left: 0;
|
|
132
|
+
width: 100%;
|
|
133
|
+
height: 100%;
|
|
134
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
z-index: ${T.OVERLAY};
|
|
139
|
+
`}function ae(){return`
|
|
140
|
+
position: relative;
|
|
141
|
+
width: ${c.CONTAINER_WIDTH_PERCENT};
|
|
142
|
+
max-width: ${c.CONTAINER_MAX_WIDTH};
|
|
143
|
+
height: ${c.CONTAINER_HEIGHT_PERCENT};
|
|
144
|
+
max-height: ${c.CONTAINER_MAX_HEIGHT};
|
|
145
|
+
background: white;
|
|
146
|
+
border-radius: 16px;
|
|
147
|
+
overflow: hidden;
|
|
148
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
149
|
+
display: flex;
|
|
150
|
+
flex-direction: column;
|
|
151
|
+
`}function le(){return`
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: space-between;
|
|
155
|
+
padding: 15px 20px;
|
|
156
|
+
border-bottom: 1px solid #e5e5e5;
|
|
157
|
+
`}function ce(){return`
|
|
158
|
+
flex: 1;
|
|
159
|
+
position: relative;
|
|
160
|
+
overflow-y: auto;
|
|
161
|
+
overflow-x: hidden;
|
|
162
|
+
`}function de(){return`
|
|
163
|
+
width: 100%;
|
|
164
|
+
height: 100%;
|
|
165
|
+
border: none;
|
|
166
|
+
`}class M{constructor(e,n={}){this.loaderElement=null,this.container=e,this.config=n}show(e){e&&(e.style.display="none");const n=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,o=W(n),s=B(o),i=document.createElement("div");i.id=E.LOADER,i.style.cssText=V();const r=document.createElement("div");r.style.cssText=X(this.config.fillParent||!1);const a=document.createElement("div");a.style.cssText=Z(o.inputBgColor);const u=document.createElement("div");u.className="inflowpay-skeleton",u.style.cssText=J(s);const h=document.createElement("div");h.className="inflowpay-skeleton",h.style.cssText=Q(s);const m=document.createElement("div");m.className="inflowpay-skeleton",m.style.cssText=ee(s),a.appendChild(u),a.appendChild(h),a.appendChild(m);const p=document.createElement("div");p.className="inflowpay-skeleton",p.style.cssText=te(s);const l=document.createElement("div");l.style.cssText=ne();const f=document.createElement("div");f.className="inflowpay-skeleton",f.style.cssText=ie(s);const y=document.createElement("div");y.className="inflowpay-skeleton",y.style.cssText=se(s),l.appendChild(f),l.appendChild(y),r.appendChild(a),r.appendChild(p),r.appendChild(l),i.appendChild(r),this.injectShimmerStyles(),this.container.appendChild(i),this.loaderElement=i}hide(e){const n=document.getElementById(E.LOADER);n&&n.remove(),this.loaderElement=null,e&&(e.style.display="")}injectShimmerStyles(){if(!document.getElementById(E.LOADER_STYLES)){const e=document.createElement("style");e.id=E.LOADER_STYLES,e.textContent=oe,document.head.appendChild(e)}}}const d=class d{constructor(e){this.config=e}open(e,n,o){return this.config.debug&&(console.log("[SDK] open3DSModal called with URL:",e),console.log("[SDK] Session ID:",n,"Payment ID:",o)),d.activeModal&&(console.warn("[SDK] Closing existing modal before opening new one"),d.activeModal.overlay.remove(),d.activeModal=null),new Promise(s=>{const i=document.createElement("div");i.id=E.THREE_DS_OVERLAY,i.style.cssText=re();const r=document.createElement("div");r.style.cssText=ae();const a=document.createElement("div");a.style.cssText=le(),a.innerHTML=`
|
|
167
|
+
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">Secure Payment Authentication</h3>
|
|
168
|
+
`;const u=document.createElement("div");u.style.cssText=ce();const h=document.createElement("iframe");h.src=e,h.style.cssText=de(),h.setAttribute("allow","payment"),h.setAttribute("sandbox","allow-forms allow-scripts allow-same-origin allow-popups"),u.appendChild(h),r.appendChild(a),r.appendChild(u),i.appendChild(r),document.body.appendChild(i),d.activeModal={overlay:i,sessionId:n,paymentId:o};const m=p=>{if(!p.data)return;if(!this.isAllowedOrigin(p.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",p.origin);return}const l=p.data,f=l.type==="THREE_DS_COMPLETE"||l.type==="3ds-complete",y=l.status==="success",v=l.status==="failed"||l.status==="failure";if(f&&y){i.remove(),window.removeEventListener("message",m),s(!0);return}if(y&&!f){i.remove(),window.removeEventListener("message",m),s(!0);return}if(f&&v||l.type==="3ds-failed"||v){i.remove(),window.removeEventListener("message",m),s(!1);return}};window.addEventListener("message",m)})}static close(e){if(!d.activeModal){console.log("[SDK] No active modal to close");return}if(e&&d.activeModal.sessionId!==e){console.warn(`[SDK] Session ID mismatch: webhook for ${e}, but modal is for ${d.activeModal.sessionId}. Ignoring close request.`);return}console.log("[SDK] Closing modal for session:",e||d.activeModal.sessionId),d.activeModal.overlay.remove(),d.activeModal=null}static isModalOpen(){return d.activeModal!==null}static getCurrentSessionId(){return d.activeModal?.sessionId||null}isAllowedOrigin(e){return!!(F.includes(e)||(this.config.environment==="sandbox"||this.config.environment==="development")&&(e.includes("localhost")||e.includes("127.0.0.1")))}};d.activeModal=null;let x=d;class C{static createOverlay(e,n){const o=document.createElement("div");o.id=E.OVERLAY,o.style.cssText=G();const s=document.createElement("div");s.style.cssText=z();const i=document.createElement("button");i.innerHTML="×",i.style.cssText=Y(),i.onclick=n;const r=document.createElement("iframe");return r.src=e,r.style.cssText=j(),r.setAttribute("allow","payment"),s.appendChild(i),s.appendChild(r),o.appendChild(s),o.addEventListener("click",a=>{a.target===o&&n()}),{overlay:o,container:s,iframe:r}}static removeOverlay(){const e=document.getElementById(E.OVERLAY);e&&e.remove()}}const ue=["en","de","es","fr","it","nl","pl","pt"];function he(){if(typeof window>"u")return"en";try{const e=(navigator.language||navigator.userLanguage||"").split("-")[0].toLowerCase();if(ue.includes(e))return e}catch{}return"en"}function R(t){return t.includes("_local_")||t.startsWith("inflow_local_")?"sandbox":t.includes("_prod_")&&!t.includes("_preprod_")?"production":t.includes("_preprod_")||t.startsWith("inflow_preprod_")?"preprod":t.includes("_dev_")?"development":"sandbox"}function N(t){switch(R(t)){case"production":return b.PRODUCTION;case"preprod":return b.PREPROD;case"development":return b.DEVELOPMENT;case"sandbox":default:return b.LOCAL}}class me{constructor(e){if(this.iframe=null,this.messageListener=null,this.containerElement=null,this.loaderManager=null,this.config=e,this.iframeUrl=e.iframeUrl||N(e.publicKey||""),this.environment=R(e.publicKey||""),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;this.modalManager=new x({environment:this.environment,debug:this.config.debug})}init(){this.iframe||(this.createIframe(),this.addMessageListener())}createIframe(){const e=new URL(this.iframeUrl);this.config.publicKey&&e.searchParams.set("publicKey",this.config.publicKey),this.config.config?.paymentId&&e.searchParams.set("paymentId",this.config.config.paymentId),this.config.locale&&e.searchParams.set("locale",this.config.locale);const n=e.toString();if(this.usePopup){const{overlay:o,container:s,iframe:i}=C.createOverlay(n,()=>this.close());this.iframe=i,document.body.appendChild(o),this.loaderManager=new M(s,{fillParent:this.config.config?.style?.fillParent}),this.loaderManager.show(this.iframe)}else{if(!this.containerElement)throw new Error("Container element is required for inline mode");if(this.containerElement.innerHTML="",this.containerElement instanceof HTMLElement){const o=this.containerElement.getAttribute("style")||"";o.includes("min-height")||(this.containerElement.style.minHeight=`${c.MIN_HEIGHT}px`),o.includes("position")||(this.containerElement.style.position="relative"),o.includes("overflow")||(this.containerElement.style.overflow="hidden")}this.iframe=document.createElement("iframe"),this.iframe.src=n,this.iframe.style.cssText=q(this.config.config?.style?.fillParent||!1),this.iframe.setAttribute("allow","payment"),this.containerElement.appendChild(this.iframe),this.loaderManager=new M(this.containerElement,{fillParent:this.config.config?.style?.fillParent}),this.loaderManager.show(this.iframe)}}addMessageListener(){this.messageListener=e=>{const n=new URL(this.iframeUrl).origin;let s=e.origin===n;if(s||((this.environment==="sandbox"||this.environment==="development")&&(s=(e.origin.includes("localhost")||e.origin.includes("127.0.0.1"))&&(n.includes("localhost")||n.includes("127.0.0.1"))),s||(s=e.origin==="https://dev.iframe.inflowpay.com"||e.origin==="https://pre-prod.iframe.inflowpay.xyz"||e.origin==="https://iframe.inflowpay.xyz")),!s){this.config.debug&&console.warn("[SDK] Rejected message from unauthorized origin:",e.origin);return}const i=e.data;if(!(!i||!i.type))switch(i.type){case"iframe-ready":this.loaderManager&&this.loaderManager.hide(this.iframe||void 0),this.sendConfigToIframe();break;case"content-height":if(i.height&&this.iframe){const r=Math.max(i.height,c.MIN_HEIGHT);this.iframe.style.height=`${r}px`,this.containerElement&&(this.containerElement.style.minHeight=`${r}px`)}break;case"close":this.close();break;case"success":this.config.onSuccess&&this.config.onSuccess(i.data);break;case"error":this.config.onError&&this.config.onError(i.data);break;case"3ds-required":if(this.config.debug&&(console.log("[SDK] Received 3DS request:",i.threeDsSessionUrl),console.log("[SDK] Session ID:",i.sessionId)),i.threeDsSessionUrl){const r=i.sessionId,a=i.paymentId||this.config.config?.paymentId||"";i.sessionId||console.warn("[SDK] No session ID provided by iframe"),this.config.debug&&console.log("[SDK] Opening 3DS modal with session ID:",r),this.modalManager.open(i.threeDsSessionUrl,r,a).then(u=>{this.config.debug&&console.log("[SDK] 3DS modal closed, result:",u)})}else this.config.debug&&console.error("[SDK] 3DS required but no threeDsSessionUrl provided");break;case"3ds-success":this.config.debug&&(console.log("[SDK] 3DS completed, closing modal..."),console.log("[SDK] Session ID from webhook:",i.sessionId)),x.close(i.sessionId);break;case"3ds-failed":this.config.debug&&(console.log("[SDK] 3DS failed, closing modal..."),console.log("[SDK] Session ID from webhook:",i.sessionId)),x.close(i.sessionId);break;default:this.config.debug&&console.log("SDK: Received message:",i)}},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:{publicKey:this.config.publicKey}},n=this.getTargetOrigin();this.iframe.contentWindow.postMessage(e,n)}close(){this.config.onClose&&this.config.onClose(),this.loaderManager&&(this.loaderManager.hide(this.iframe||void 0),this.loaderManager=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.usePopup?C.removeOverlay():this.containerElement&&(this.containerElement.innerHTML=""),this.iframe=null}switchToSuccessState(e){if(this.loaderManager&&(this.loaderManager.hide(this.iframe||void 0),this.loaderManager=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.usePopup){C.removeOverlay(),this.iframe=null;return}const n=this.config.config?.showDefaultSuccessUI??!0;!n&&this.containerElement&&(this.containerElement.innerHTML=""),n||(this.iframe=null)}getTargetOrigin(){return this.environment==="production"||this.environment==="preprod"?new URL(this.iframeUrl).origin:"*"}destroy(){this.close()}}class P{constructor(e,n){this.mounted=!1;let o;if(typeof n.container=="string"){if(o=document.querySelector(n.container),!o)throw new Error(`Container not found: ${n.container}`)}else o=n.container;this.container=o,this.sdk=new me({publicKey:e.publicKey,container:this.container,locale:e.locale??he(),config:{paymentId:n.paymentId,...n.style&&{style:n.style},...n.buttonText&&{buttonText:n.buttonText},...n.placeholders&&{placeholders:n.placeholders},...n.showDefaultSuccessUI!==void 0&&{showDefaultSuccessUI:n.showDefaultSuccessUI}},onSuccess:s=>{n.onComplete&&n.onComplete({status:I.SUCCESS,paymentId:n.paymentId}),this.sdk.switchToSuccessState(s)},onError:s=>{n.onError?n.onError(s):n.onComplete&&n.onComplete({status:I.FAILED,paymentId:n.paymentId,error:s})},onClose:()=>{n.onClose&&n.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 A{constructor(e){if(!e.publicKey||typeof e.publicKey!="string")throw new Error("API key is required");this.config=e,this.timeout=3e4,this.iframeUrl=N(e.publicKey);const n=R(e.publicKey);this.debug=n==="sandbox"||n==="development"}createCardElement(e){return new P({publicKey:this.config.publicKey,iframeUrl:this.iframeUrl,timeout:this.timeout,debug:this.debug,locale:this.config.locale},e)}getIframeUrl(){return this.iframeUrl}getApiKey(){return this.config.publicKey}}exports.CardElement=P;exports.CardElement$1=U;exports.InflowPayProvider=$;exports.PaymentResultErrorCode=_;exports.PaymentResultStatus=I;exports.PaymentSDK=A;exports.useInflowPay=K;
|
|
169
|
+
//# sourceMappingURL=payment-sdk-CC-mm-nt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-sdk-CC-mm-nt.js","sources":["../src/types.ts","../src/react/index.tsx","../src/constants/sdk-constants.ts","../src/ui/styles.ts","../src/ui/loader-manager.ts","../src/ui/modal-manager.ts","../src/ui/overlay-manager.ts","../src/utils.ts","../src/sdk.ts","../src/card-element.ts","../src/payment-sdk.ts"],"sourcesContent":["/**\n * Type definitions for SDK v2\n */\n\n// ============================================================================\n// Locale Types\n// ============================================================================\n\nexport type Locale = 'en' | 'de' | 'es' | 'fr' | 'it' | 'nl' | 'pl' | 'pt';\n\n// ============================================================================\n// Style Types\n// ============================================================================\n\nexport type FontFamily =\n | 'DM Sans'\n | 'Inter'\n | 'Poppins'\n | 'Nunito'\n | 'Work Sans'\n | 'Manrope'\n | 'Rubik'\n | 'Karla'\n | 'Figtree'\n | 'Outfit'\n | 'Space Grotesk'\n | 'Urbanist';\n\nexport type FontWeight =\n | 100\n | 200\n | 300\n | 400\n | 500\n | 600\n | 700\n | 800\n | 900\n | 'normal'\n | 'bold'\n | 'lighter'\n | 'bolder';\n\nexport type Opacity = number | string; \n\nexport interface InputContainerStyles {\n backgroundColor?: string;\n borderColor?: string;\n borderEnabled?: boolean;\n borderRadius?: string;\n}\n\nexport interface InputStyles {\n backgroundColor?: string;\n borderColor?: string;\n borderEnabled?: boolean;\n borderRadius?: string;\n textColor?: string;\n placeholderColor?: string;\n}\n\nexport interface ButtonBaseStyles {\n backgroundColor?: string;\n textColor?: string;\n borderRadius?: string;\n borderColor?: string;\n borderEnabled?: boolean;\n fontSize?: string;\n fontWeight?: FontWeight;\n opacity?: Opacity;\n}\n\nexport interface ButtonStyles extends ButtonBaseStyles {\n hover?: ButtonBaseStyles;\n disabled?: ButtonBaseStyles;\n loaderColor?: string;\n}\n\nexport interface GeneralMessageStyles {\n textColor?: string;\n backgroundColor?: string;\n borderEnabled?: boolean;\n borderRadius?: string;\n borderColor?: string;\n}\n\nexport interface ThemeStyles {\n inputContainer?: InputContainerStyles;\n input?: InputStyles;\n button?: ButtonStyles;\n disclaimerColor?: string;\n fieldErrorColor?: string;\n generalError?: GeneralMessageStyles;\n generalSuccess?: GeneralMessageStyles;\n}\n\nexport interface CSSProperties {\n fontFamily?: FontFamily;\n fillParent?: boolean;\n inputContainer?: InputContainerStyles;\n input?: InputStyles;\n button?: ButtonStyles;\n disclaimerColor?: string;\n fieldErrorColor?: string;\n generalError?: GeneralMessageStyles;\n generalSuccess?: GeneralMessageStyles;\n // Theme-specific overrides\n dark?: ThemeStyles;\n}\n\n// ============================================================================\n// SDK Config Types\n// ============================================================================\n\nexport interface SDKConfig {\n /** Public API key */\n publicKey?: string;\n /** Payment configuration */\n config?: PaymentConfig;\n /** Container element or selector where to mount the iframe (if not provided, creates a popup) */\n container?: string | HTMLElement;\n /** Locale for the UI. Defaults to 'en' */\n locale?: Locale;\n /** Callback when payment succeeds */\n onSuccess?: (data: TransactionData) => void;\n /** Callback when payment fails */\n onError?: (error: any) => void;\n /** Callback when user closes the payment modal */\n onClose?: () => void;\n /** Show default success UI after payment (default true). If false, only unmount iframe. */\n showDefaultSuccessUI?: boolean;\n}\n\nexport interface PaymentConfig {\n name?: string;\n amount?: number;\n currency?: string;\n paymentId?: string;\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 /** Show default success UI after payment (default true). If false, only unmount iframe. */\n showDefaultSuccessUI?: boolean;\n [key: string]: any;\n}\n\nexport interface IframeMessage {\n type: 'sdkData' | 'success' | 'error' | 'close' | '3ds-required' | 'iframe-ready' | 'content-height' | '3ds-failed' | '3ds-success';\n data?: any;\n config?: PaymentConfig;\n threeDsSessionUrl?: string; // URL for 3DS challenge when type is '3ds-required'\n paymentId?: string; // Payment ID for 3DS flow\n sessionId?: string; // 3DS session ID when type is '3ds-completed'\n success?: boolean; // 3DS result when type is '3ds-result'\n height?: number; // Content height when type is 'content-height'\n}\n\nexport interface TransactionData {\n transaction?: {\n id: string;\n amount: number;\n currency: string;\n status: string;\n created_at: string;\n [key: string]: any;\n };\n [key: string]: any;\n}\n\n// ============================================================================\n// Payment Result Types\n// ============================================================================\n\nexport enum PaymentResultStatus {\n SUCCESS = 'SUCCESS',\n FAILED = 'FAILED',\n}\n\nexport enum PaymentResultErrorCode {\n THREE_DS_FAILED = 'THREE_DS_FAILED',\n PAYMENT_PROCESSING_ERROR = 'PAYMENT_PROCESSING_ERROR',\n}\n\nexport interface PaymentError {\n code: PaymentResultErrorCode;\n message: string;\n retryable: boolean;\n}\n\nexport interface PaymentResult {\n status: PaymentResultStatus;\n paymentId: string;\n error?: PaymentError;\n}\n\nexport interface CardElementState {\n complete: boolean;\n}\n\n","/**\n * InflowPay React SDK v2 - React Components\n * \n * React components that use the iframe-based SDK v2\n * Same API as the original React SDK for easy migration\n */\n\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useEffect, useRef, useState } from 'react';\nimport type { CardElement as CardElementClass, CardElementOptions } from '../card-element';\nimport type { PaymentSDKConfig } from '../payment-sdk';\nimport { PaymentSDK } from '../payment-sdk';\nimport type {\n CardElementState,\n CSSProperties,\n Locale,\n PaymentError,\n PaymentResult,\n} from '../types';\nimport { PaymentResultStatus } from '../types';\n\nexport interface SDKConfig {\n publicKey: string;\n /** Locale for the payment UI. Defaults to 'en' */\n locale?: Locale;\n}\n\nexport type {\n CardElementState, PaymentError,\n PaymentResult\n} from '../types';\n\nexport { PaymentResultErrorCode, PaymentResultStatus } from '../types';\n\nexport interface CardElementProps {\n paymentId: string;\n onReady?: () => void;\n onChange?: (state: CardElementState) => void;\n onComplete?: (result: PaymentResult) => void;\n onError?: (error: PaymentError) => void;\n style?: CSSProperties;\n buttonText?: string;\n placeholders?: {\n cardNumber?: string;\n expiry?: string;\n cvc?: string;\n };\n /** Show default success UI after payment (default true). If false, only unmount iframe. */\n showDefaultSuccessUI?: boolean;\n}\n\ninterface InflowPayContextValue {\n sdk: PaymentSDK;\n}\n\nconst InflowPayContext = createContext<InflowPayContextValue | null>(null);\n\n/**\n * InflowPayProvider - React component\n * \n * Same API as the original React SDK\n * \n * @example\n * ```tsx\n * <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>\n * <CardElement\n * paymentId=\"pay_xxx\"\n * onComplete={(result) => {\n * if (result.status === 'CHECKOUT_SUCCESS') {\n * window.location.href = '/success';\n * }\n * }}\n * />\n * </InflowPayProvider>\n * ```\n */\nexport function InflowPayProvider({\n config,\n children,\n}: {\n config: SDKConfig;\n children: ReactNode;\n}) {\n const [sdk] = useState(() => {\n const sdkConfig: PaymentSDKConfig = {\n publicKey: config.publicKey,\n locale: config.locale,\n };\n return new PaymentSDK(sdkConfig);\n });\n\n return (\n <InflowPayContext.Provider value={{ sdk }}>\n {children}\n </InflowPayContext.Provider>\n );\n}\n\n/**\n * useInflowPay - Hook to access InflowPay SDK instance\n * \n * @example\n * ```tsx\n * function CustomComponent() {\n * const inflow = useInflowPay();\n * \n * const checkStatus = async () => {\n * const status = await inflow.getPaymentStatus('pay_xxx');\n * console.log(status);\n * };\n * \n * return <button onClick={checkStatus}>Check Status</button>;\n * }\n * ```\n */\nexport function useInflowPay(): PaymentSDK {\n const context = useContext(InflowPayContext);\n if (!context) {\n throw new Error('useInflowPay must be used within InflowPayProvider');\n }\n return context.sdk;\n}\n\n/**\n * CardElement - React component\n * \n * Same API as the original React SDK\n * \n * @example\n * ```tsx\n * <CardElement\n * paymentId=\"pay_xxx\"\n * onComplete={(result) => {\n * if (result.status === 'CHECKOUT_SUCCESS') {\n * window.location.href = '/success';\n * }\n * }}\n * />\n * ```\n */\nexport function CardElement(props: CardElementProps & { config?: SDKConfig }) {\n const {\n paymentId,\n onReady,\n onChange,\n onComplete,\n onError,\n style,\n buttonText,\n placeholders,\n showDefaultSuccessUI,\n config: propConfig,\n } = props;\n const context = useContext(InflowPayContext);\n const containerRef = useRef<HTMLDivElement>(null);\n const cardElementRef = useRef<CardElementClass | null>(null);\n const [mounted, setMounted] = useState(false);\n\n const sdk = context?.sdk || (propConfig ? new PaymentSDK({\n publicKey: propConfig.publicKey,\n locale: propConfig.locale,\n }) : null);\n\n if (!sdk) {\n throw new Error('CardElement must be used within InflowPayProvider or have a config prop');\n }\n\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n if (!containerRef.current.id) {\n containerRef.current.id = `inflowpay-card-element-${Date.now()}`;\n }\n\n const cardElementOptions: CardElementOptions = {\n container: containerRef.current,\n paymentId: paymentId,\n ...(style && { style }),\n ...(buttonText && { buttonText }),\n ...(placeholders && { placeholders }),\n ...(showDefaultSuccessUI !== undefined && { showDefaultSuccessUI }),\n onComplete: (result: PaymentResult) => {\n if (onComplete) {\n onComplete(result);\n }\n },\n onError: (error) => {\n if (onError) {\n onError(error);\n } else if (onComplete) {\n onComplete({\n status: PaymentResultStatus.FAILED,\n paymentId: paymentId,\n error: error,\n });\n }\n },\n onClose: () => {\n },\n };\n\n const cardElement = sdk.createCardElement(cardElementOptions);\n cardElementRef.current = cardElement;\n cardElement.mount();\n setMounted(true);\n\n if (onReady) {\n const timer = setTimeout(() => {\n onReady();\n }, 100);\n return () => clearTimeout(timer);\n }\n }, [paymentId, sdk, onComplete, onError, onReady, style, buttonText, placeholders, showDefaultSuccessUI]);\n\n useEffect(() => {\n if (onChange && mounted) {\n onChange({ complete: false });\n }\n }, [mounted, onChange]);\n\n useEffect(() => {\n return () => {\n if (cardElementRef.current) {\n cardElementRef.current.destroy();\n cardElementRef.current = null;\n }\n };\n }, []);\n\n return (\n <div\n ref={containerRef}\n style={{\n width: style?.fillParent ? \"100%\" : \"344px\"\n }}\n />\n );\n}\n","/**\n * SDK Constants\n * Centralized constants for z-indices, dimensions, and configuration values\n */\n\nexport const Z_INDEX = {\n OVERLAY: 999999,\n MODAL: 1000000,\n LOADER: 1000,\n} as const;\n\nexport const DIMENSIONS = {\n MIN_HEIGHT: 196,\n CONTAINER_MAX_WIDTH: '500px',\n CONTAINER_WIDTH_PERCENT: '90%',\n CONTAINER_HEIGHT_PERCENT: '90%',\n CONTAINER_MAX_HEIGHT: '600px',\n BUTTON_SIZE: 30,\n DEFAULT_IFRAME_WIDTH: '344px',\n} as const;\n\nexport const ALLOWED_3DS_ORIGINS = [\n 'https://dev.api.inflowpay.xyz',\n 'https://pre-prod.api.inflowpay.xyz',\n 'https://api.inflowpay.xyz',\n] as const;\n\nexport const ELEMENT_IDS = {\n OVERLAY: 'inflowpay-sdk-overlay',\n LOADER: 'inflowpay-loader',\n LOADER_STYLES: 'inflowpay-loader-styles',\n THREE_DS_OVERLAY: 'inflowpay-3ds-overlay',\n THREE_DS_CLOSE: 'inflowpay-3ds-close',\n} as const;\n\nexport const IFRAME_URLS = {\n PRODUCTION: 'https://iframe.inflowpay.com/iframe/checkout',\n PREPROD: 'https://preprod.iframe.inflowpay.com/iframe/checkout',\n DEVELOPMENT: 'https://dev.iframe.inflowpay.com/iframe/checkout',\n LOCAL: 'http://localhost:3010/iframe/checkout',\n} as const;\n","/**\n * UI Styles\n * Centralized CSS styles for SDK components\n */\n\nimport { Z_INDEX, DIMENSIONS } from '../constants/sdk-constants';\n\n/**\n * Color scheme for dark mode support\n */\nexport interface ColorScheme {\n inputBgColor: string;\n shimmerBase: string;\n shimmerLight: string;\n}\n\n/**\n * Get color scheme based on dark mode preference\n */\nexport function getColorScheme(isDarkMode: boolean): ColorScheme {\n return {\n inputBgColor: isDarkMode ? '#2d2d2d' : '#F5F5F5',\n shimmerBase: isDarkMode ? '#3d3d3d' : '#E5E5E5',\n shimmerLight: isDarkMode ? '#4d4d4d' : '#F0F0F0',\n };\n}\n\n/**\n * Get shimmer gradient for skeleton loader\n */\nexport function getShimmerGradient(colors: ColorScheme): string {\n return `linear-gradient(90deg, ${colors.shimmerBase} 25%, ${colors.shimmerLight} 50%, ${colors.shimmerBase} 75%)`;\n}\n\n/**\n * Overlay styles for popup mode\n */\nexport function getOverlayStyles(): string {\n return `\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: ${Z_INDEX.OVERLAY};\n `;\n}\n\n/**\n * Container styles for popup mode\n */\nexport function getContainerStyles(): string {\n return `\n position: relative;\n width: ${DIMENSIONS.CONTAINER_WIDTH_PERCENT};\n max-width: ${DIMENSIONS.CONTAINER_MAX_WIDTH};\n height: ${DIMENSIONS.CONTAINER_HEIGHT_PERCENT};\n max-height: ${DIMENSIONS.CONTAINER_MAX_HEIGHT};\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n `;\n}\n\n/**\n * Close button styles\n */\nexport function getCloseButtonStyles(): string {\n return `\n position: absolute;\n top: 10px;\n right: 10px;\n width: ${DIMENSIONS.BUTTON_SIZE}px;\n height: ${DIMENSIONS.BUTTON_SIZE}px;\n border: none;\n background: transparent;\n font-size: 24px;\n cursor: pointer;\n z-index: ${Z_INDEX.MODAL};\n color: #333;\n display: flex;\n align-items: center;\n justify-content: center;\n `;\n}\n\n/**\n * Iframe styles for popup mode\n */\nexport function getPopupIframeStyles(): string {\n return `\n width: 100%;\n height: 100%;\n border: none;\n border-radius: 8px;\n `;\n}\n\n/**\n * Iframe styles for inline mode\n */\nexport function getInlineIframeStyles(fillParent: boolean): string {\n const width = fillParent ? '100%' : DIMENSIONS.DEFAULT_IFRAME_WIDTH;\n const maxWidth = fillParent ? 'none' : '100%';\n \n return `\n width: ${width};\n max-width: ${maxWidth};\n height: ${DIMENSIONS.MIN_HEIGHT}px;\n min-height: ${DIMENSIONS.MIN_HEIGHT}px;\n border: none;\n display: block;\n transition: height 0.2s ease;\n `;\n}\n\n/**\n * Loader container styles\n */\nexport function getLoaderContainerStyles(): string {\n return `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: ${Z_INDEX.LOADER};\n padding: 20px;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n align-items: center;\n `;\n}\n\n/**\n * Skeleton card element styles\n */\nexport function getSkeletonCardStyles(fillParent: boolean): string {\n const width = fillParent ? '100%' : DIMENSIONS.DEFAULT_IFRAME_WIDTH;\n \n return `\n width: ${width};\n max-width: 100%;\n margin: 0 auto;\n `;\n}\n\n/**\n * Input wrapper styles for skeleton loader\n */\nexport function getInputWrapStyles(bgColor: string): string {\n return `\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n background-color: ${bgColor};\n padding: 8px;\n border-radius: 8px;\n margin-bottom: 20px;\n `;\n}\n\n/**\n * Skeleton element base styles\n */\nexport function getSkeletonBaseStyles(shimmerGradient: string): string {\n return `\n background: ${shimmerGradient};\n background-size: 200% 100%;\n animation: inflowpay-shimmer 1.5s infinite;\n `;\n}\n\n/**\n * Card number skeleton styles\n */\nexport function getCardNumberSkeletonStyles(shimmerGradient: string): string {\n return `\n flex: 1;\n min-width: 0;\n height: 32px;\n border-radius: 6px;\n ${getSkeletonBaseStyles(shimmerGradient)}\n `;\n}\n\n/**\n * Expiry skeleton styles\n */\nexport function getExpirySkeletonStyles(shimmerGradient: string): string {\n return `\n width: 21.5%;\n flex-shrink: 0;\n height: 32px;\n border-radius: 6px;\n ${getSkeletonBaseStyles(shimmerGradient)}\n `;\n}\n\n/**\n * CVC skeleton styles\n */\nexport function getCvcSkeletonStyles(shimmerGradient: string): string {\n return `\n width: 17.5%;\n flex-shrink: 0;\n height: 32px;\n border-radius: 6px;\n ${getSkeletonBaseStyles(shimmerGradient)}\n `;\n}\n\n/**\n * Button skeleton styles\n */\nexport function getButtonSkeletonStyles(shimmerGradient: string): string {\n return `\n width: 100%;\n height: 42px;\n border-radius: 8px;\n ${getSkeletonBaseStyles(shimmerGradient)}\n margin-bottom: 16px;\n `;\n}\n\n/**\n * Disclaimer skeleton container styles\n */\nexport function getDisclaimerSkeletonStyles(): string {\n return `\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n width: 100%;\n margin-top: 16px;\n `;\n}\n\n/**\n * Disclaimer icon skeleton styles\n */\nexport function getDisclaimerIconSkeletonStyles(shimmerGradient: string): string {\n return `\n width: 10px;\n height: 10px;\n border-radius: 50%;\n ${getSkeletonBaseStyles(shimmerGradient)}\n `;\n}\n\n/**\n * Disclaimer text skeleton styles\n */\nexport function getDisclaimerTextSkeletonStyles(shimmerGradient: string): string {\n return `\n width: 80%;\n height: 16px;\n border-radius: 4px;\n ${getSkeletonBaseStyles(shimmerGradient)}\n `;\n}\n\n/**\n * Shimmer animation keyframes\n */\nexport const SHIMMER_ANIMATION = `\n @keyframes inflowpay-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n }\n`;\n\n/**\n * 3DS overlay styles\n */\nexport function get3DSOverlayStyles(): string {\n return `\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: ${Z_INDEX.OVERLAY};\n `;\n}\n\n/**\n * 3DS modal styles\n */\nexport function get3DSModalStyles(): string {\n return `\n position: relative;\n width: ${DIMENSIONS.CONTAINER_WIDTH_PERCENT};\n max-width: ${DIMENSIONS.CONTAINER_MAX_WIDTH};\n height: ${DIMENSIONS.CONTAINER_HEIGHT_PERCENT};\n max-height: ${DIMENSIONS.CONTAINER_MAX_HEIGHT};\n background: white;\n border-radius: 16px;\n overflow: hidden;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n `;\n}\n\n/**\n * 3DS header styles\n */\nexport function get3DSHeaderStyles(): string {\n return `\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 15px 20px;\n border-bottom: 1px solid #e5e5e5;\n `;\n}\n\n/**\n * 3DS content styles\n */\nexport function get3DSContentStyles(): string {\n return `\n flex: 1;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n `;\n}\n\n/**\n * 3DS iframe styles\n */\nexport function get3DSIframeStyles(): string {\n return `\n width: 100%;\n height: 100%;\n border: none;\n `;\n}\n","/**\n * Loader Manager\n * Handles skeleton loading UI while iframe is initializing\n */\n\nimport { ELEMENT_IDS } from '../constants/sdk-constants';\nimport {\n getColorScheme,\n getShimmerGradient,\n getLoaderContainerStyles,\n getSkeletonCardStyles,\n getInputWrapStyles,\n getCardNumberSkeletonStyles,\n getExpirySkeletonStyles,\n getCvcSkeletonStyles,\n getButtonSkeletonStyles,\n getDisclaimerSkeletonStyles,\n getDisclaimerIconSkeletonStyles,\n getDisclaimerTextSkeletonStyles,\n SHIMMER_ANIMATION,\n} from './styles';\n\nexport interface LoaderConfig {\n fillParent?: boolean;\n}\n\nexport class LoaderManager {\n private container: HTMLElement;\n private config: LoaderConfig;\n private loaderElement: HTMLElement | null = null;\n\n constructor(container: HTMLElement, config: LoaderConfig = {}) {\n this.container = container;\n this.config = config;\n }\n\n /**\n * Show skeleton loader\n */\n show(iframe?: HTMLIFrameElement): void {\n // Hide iframe while loader is showing\n if (iframe) {\n iframe.style.display = 'none';\n }\n\n // Detect dark mode\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n\n // Get color scheme\n const colors = getColorScheme(isDarkMode);\n const shimmerGradient = getShimmerGradient(colors);\n\n // Create loader container\n const loader = document.createElement('div');\n loader.id = ELEMENT_IDS.LOADER;\n loader.style.cssText = getLoaderContainerStyles();\n\n // Create skeleton card element\n const skeletonCard = document.createElement('div');\n skeletonCard.style.cssText = getSkeletonCardStyles(this.config.fillParent || false);\n\n // Create input wrapper\n const inputWrap = document.createElement('div');\n inputWrap.style.cssText = getInputWrapStyles(colors.inputBgColor);\n\n // Create card number skeleton\n const cardNumberSkeleton = document.createElement('div');\n cardNumberSkeleton.className = 'inflowpay-skeleton';\n cardNumberSkeleton.style.cssText = getCardNumberSkeletonStyles(shimmerGradient);\n\n // Create expiry skeleton\n const expirySkeleton = document.createElement('div');\n expirySkeleton.className = 'inflowpay-skeleton';\n expirySkeleton.style.cssText = getExpirySkeletonStyles(shimmerGradient);\n\n // Create CVC skeleton\n const cvcSkeleton = document.createElement('div');\n cvcSkeleton.className = 'inflowpay-skeleton';\n cvcSkeleton.style.cssText = getCvcSkeletonStyles(shimmerGradient);\n\n // Assemble input wrapper\n inputWrap.appendChild(cardNumberSkeleton);\n inputWrap.appendChild(expirySkeleton);\n inputWrap.appendChild(cvcSkeleton);\n\n // Create button skeleton\n const buttonSkeleton = document.createElement('div');\n buttonSkeleton.className = 'inflowpay-skeleton';\n buttonSkeleton.style.cssText = getButtonSkeletonStyles(shimmerGradient);\n\n // Create disclaimer skeleton\n const disclaimerSkeleton = document.createElement('div');\n disclaimerSkeleton.style.cssText = getDisclaimerSkeletonStyles();\n\n const disclaimerIconSkeleton = document.createElement('div');\n disclaimerIconSkeleton.className = 'inflowpay-skeleton';\n disclaimerIconSkeleton.style.cssText = getDisclaimerIconSkeletonStyles(shimmerGradient);\n\n const disclaimerTextSkeleton = document.createElement('div');\n disclaimerTextSkeleton.className = 'inflowpay-skeleton';\n disclaimerTextSkeleton.style.cssText = getDisclaimerTextSkeletonStyles(shimmerGradient);\n\n disclaimerSkeleton.appendChild(disclaimerIconSkeleton);\n disclaimerSkeleton.appendChild(disclaimerTextSkeleton);\n\n // Assemble skeleton card\n skeletonCard.appendChild(inputWrap);\n skeletonCard.appendChild(buttonSkeleton);\n skeletonCard.appendChild(disclaimerSkeleton);\n\n // Add to loader\n loader.appendChild(skeletonCard);\n\n // Inject shimmer animation styles if not already present\n this.injectShimmerStyles();\n\n // Add loader to container\n this.container.appendChild(loader);\n this.loaderElement = loader;\n }\n\n /**\n * Hide loader\n */\n hide(iframe?: HTMLIFrameElement): void {\n const loader = document.getElementById(ELEMENT_IDS.LOADER);\n if (loader) {\n loader.remove();\n }\n this.loaderElement = null;\n\n // Show iframe again when loader is hidden\n if (iframe) {\n iframe.style.display = '';\n }\n }\n\n /**\n * Inject shimmer animation styles into document head\n */\n private injectShimmerStyles(): void {\n if (!document.getElementById(ELEMENT_IDS.LOADER_STYLES)) {\n const style = document.createElement('style');\n style.id = ELEMENT_IDS.LOADER_STYLES;\n style.textContent = SHIMMER_ANIMATION;\n document.head.appendChild(style);\n }\n }\n}\n","/**\n * Modal Manager\n * Handles 3DS authentication modal\n */\n\nimport { ALLOWED_3DS_ORIGINS, DIMENSIONS, ELEMENT_IDS } from '../constants/sdk-constants';\nimport {\n get3DSContentStyles,\n get3DSHeaderStyles,\n get3DSIframeStyles,\n get3DSModalStyles,\n get3DSOverlayStyles,\n getCloseButtonStyles,\n} from './styles';\n\nexport interface ModalConfig {\n environment: 'sandbox' | 'production' | 'development' | 'preprod';\n debug?: boolean;\n}\n\nexport class ModalManager {\n private config: ModalConfig;\n private static activeModal: {\n overlay: HTMLElement;\n sessionId: string;\n paymentId: string;\n } | null = null;\n\n constructor(config: ModalConfig) {\n this.config = config;\n }\n\n /**\n * Open 3DS authentication modal\n * Returns a Promise that resolves with the authentication result\n */\n open(challengeUrl: string, sessionId: string, paymentId: string): Promise<boolean> {\n if (this.config.debug) {\n console.log('[SDK] open3DSModal called with URL:', challengeUrl);\n console.log('[SDK] Session ID:', sessionId, 'Payment ID:', paymentId);\n }\n\n // If there's already a modal open, close it first\n if (ModalManager.activeModal) {\n console.warn('[SDK] Closing existing modal before opening new one');\n ModalManager.activeModal.overlay.remove();\n ModalManager.activeModal = null;\n }\n\n return new Promise((resolve) => {\n // Create overlay\n const overlay = document.createElement('div');\n overlay.id = ELEMENT_IDS.THREE_DS_OVERLAY;\n overlay.style.cssText = get3DSOverlayStyles();\n\n // Create modal\n const modal = document.createElement('div');\n modal.style.cssText = get3DSModalStyles();\n\n // Create header\n const header = document.createElement('div');\n header.style.cssText = get3DSHeaderStyles();\n header.innerHTML = `\n <h3 style=\"margin: 0; font-size: 18px; font-weight: 600;\">Secure Payment Authentication</h3>\n `;\n\n // Create content with iframe\n const content = document.createElement('div');\n content.style.cssText = get3DSContentStyles();\n \n const iframe = document.createElement('iframe');\n iframe.src = challengeUrl;\n iframe.style.cssText = get3DSIframeStyles();\n iframe.setAttribute('allow', 'payment');\n iframe.setAttribute('sandbox', 'allow-forms allow-scripts allow-same-origin allow-popups');\n content.appendChild(iframe);\n\n // Assemble modal\n modal.appendChild(header);\n modal.appendChild(content);\n overlay.appendChild(modal);\n document.body.appendChild(overlay);\n\n // Store as THE active modal\n ModalManager.activeModal = {\n overlay,\n sessionId,\n paymentId\n };\n\n // Message handler for 3DS completion\n const messageHandler = (event: MessageEvent) => {\n if (!event.data) return;\n\n // Validate origin\n if (!this.isAllowedOrigin(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 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 * Close 3DS modal (called from external events like WebSocket)\n * @param sessionId - Optional session ID to validate before closing\n */\n static close(sessionId?: string): void {\n if (!ModalManager.activeModal) {\n // No modal is open - nothing to do\n console.log('[SDK] No active modal to close');\n return;\n }\n\n // If sessionId is provided, validate it matches the current modal\n if (sessionId && ModalManager.activeModal.sessionId !== sessionId) {\n console.warn(\n `[SDK] Session ID mismatch: webhook for ${sessionId}, but modal is for ${ModalManager.activeModal.sessionId}. Ignoring close request.`\n );\n return;\n }\n\n // Close the modal\n console.log('[SDK] Closing modal for session:', sessionId || ModalManager.activeModal.sessionId);\n ModalManager.activeModal.overlay.remove();\n ModalManager.activeModal = null;\n }\n\n /**\n * Check if a modal is currently open\n */\n static isModalOpen(): boolean {\n return ModalManager.activeModal !== null;\n }\n\n /**\n * Get current session ID\n */\n static getCurrentSessionId(): string | null {\n return ModalManager.activeModal?.sessionId || null;\n }\n\n /**\n * Check if origin is allowed for 3DS messages\n */\n private isAllowedOrigin(origin: string): boolean {\n // Check exact match with allowed origins\n if ((ALLOWED_3DS_ORIGINS as readonly string[]).includes(origin)) {\n return true;\n }\n\n // Allow localhost in dev/sandbox environments\n if (this.config.environment === 'sandbox' || this.config.environment === 'development') {\n if (origin.includes('localhost') || origin.includes('127.0.0.1')) {\n return true;\n }\n }\n\n return false;\n }\n}\n","/**\n * Overlay Manager\n * Handles popup overlay UI for payment iframe\n */\n\nimport { ELEMENT_IDS } from '../constants/sdk-constants';\nimport {\n getOverlayStyles,\n getContainerStyles,\n getCloseButtonStyles,\n getPopupIframeStyles,\n} from './styles';\n\nexport interface OverlayElements {\n overlay: HTMLElement;\n container: HTMLElement;\n iframe: HTMLIFrameElement;\n}\n\nexport class OverlayManager {\n /**\n * Create popup overlay with iframe\n */\n static createOverlay(\n iframeSrc: string,\n onClose: () => void\n ): OverlayElements {\n // Create overlay\n const overlay = document.createElement('div');\n overlay.id = ELEMENT_IDS.OVERLAY;\n overlay.style.cssText = getOverlayStyles();\n\n // Create iframe container\n const container = document.createElement('div');\n container.style.cssText = getContainerStyles();\n\n // Create close button\n const closeButton = document.createElement('button');\n closeButton.innerHTML = '×';\n closeButton.style.cssText = getCloseButtonStyles();\n closeButton.onclick = onClose;\n\n // Create iframe\n const iframe = document.createElement('iframe');\n iframe.src = iframeSrc;\n iframe.style.cssText = getPopupIframeStyles();\n iframe.setAttribute('allow', 'payment');\n\n // Assemble structure\n container.appendChild(closeButton);\n container.appendChild(iframe);\n overlay.appendChild(container);\n\n // Close on overlay click (but not on container click)\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n onClose();\n }\n });\n\n return { overlay, container, iframe };\n }\n\n /**\n * Remove overlay from DOM\n */\n static removeOverlay(): void {\n const overlay = document.getElementById(ELEMENT_IDS.OVERLAY);\n if (overlay) {\n overlay.remove();\n }\n }\n}\n","/**\n * Utility functions\n */\n\nimport { IFRAME_URLS } from './constants/sdk-constants';\nimport type { Locale } from './types';\n\nexport const SUPPORTED_LOCALES: Locale[] = ['en', 'de', 'es', 'fr', 'it', 'nl', 'pl', 'pt'];\n\n/**\n * Detects the browser's language and returns a supported locale if available.\n * Falls back to 'en' if the browser language is not supported.\n */\nexport function detectBrowserLocale(): Locale {\n if (typeof window === 'undefined') {\n return 'en';\n }\n\n try {\n const browserLang =\n navigator.language ||\n (navigator as { userLanguage?: string }).userLanguage ||\n '';\n\n const primaryLang = browserLang.split('-')[0].toLowerCase();\n\n if (SUPPORTED_LOCALES.includes(primaryLang as Locale)) {\n return primaryLang as Locale;\n }\n } catch {\n // If detection fails, fall back to default\n }\n\n return 'en';\n}\n\n/**\n * Determines the environment from the API key format\n */\nexport function getEnvironmentFromApiKey(publicKey: string): 'sandbox' | 'production' | 'development' | 'preprod' {\n if (publicKey.includes('_local_') || publicKey.startsWith('inflow_local_')) {\n return 'sandbox';\n } else if (publicKey.includes('_prod_') && !publicKey.includes('_preprod_')) {\n return 'production';\n } else if (publicKey.includes('_preprod_') || publicKey.startsWith('inflow_preprod_')) {\n return 'preprod';\n } else if (publicKey.includes('_dev_')) {\n return 'development';\n }\n return 'sandbox';\n}\n\n/**\n * Gets the iframe URL based on the API key environment\n * This function auto-detects the correct iframe URL from the API key format\n * \n * @param publicKey - The public API key\n * @returns The iframe URL for the detected environment\n * \n * @example\n * ```typescript\n * const url = getIframeUrlFromApiKey('inflow_pub_prod_xxx');\n * // Returns: 'https://api.inflowpay.xyz/iframe/checkout'\n * \n * const url = getIframeUrlFromApiKey('inflow_pub_local_xxx');\n * // Returns: 'http://localhost:3000/iframe/checkout'\n * ```\n */\nexport function getIframeUrlFromApiKey(publicKey: string): string {\n const environment = getEnvironmentFromApiKey(publicKey);\n \n switch (environment) {\n case 'production':\n return IFRAME_URLS.PRODUCTION;\n case 'preprod':\n return IFRAME_URLS.PREPROD;\n case 'development':\n return IFRAME_URLS.DEVELOPMENT;\n case 'sandbox':\n default:\n return IFRAME_URLS.LOCAL;\n }\n}\n","/**\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 { DIMENSIONS } from './constants/sdk-constants';\nimport type { IframeMessage, SDKConfig, TransactionData } from './types';\nimport { LoaderManager } from './ui/loader-manager';\nimport { ModalManager } from './ui/modal-manager';\nimport { OverlayManager } from './ui/overlay-manager';\nimport { getInlineIframeStyles } from './ui/styles';\nimport { getEnvironmentFromApiKey, getIframeUrlFromApiKey } from './utils';\nexport class SDK {\n private iframe: HTMLIFrameElement | null = null;\n private iframeUrl: string;\n private config: SDKConfig & { iframeUrl?: string; debug?: boolean };\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 private loaderManager: LoaderManager | null = null;\n private modalManager: ModalManager;\n\n constructor(config: SDKConfig & { iframeUrl?: string; debug?: boolean }) {\n this.config = config;\n\n // Auto-detect iframe URL from API key, or use provided iframeUrl (internal use only)\n this.iframeUrl = config.iframeUrl || getIframeUrlFromApiKey(config.publicKey || '');\n this.environment = getEnvironmentFromApiKey(config.publicKey || '');\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 // Initialize modal manager\n this.modalManager = new ModalManager({\n environment: this.environment,\n debug: this.config.debug,\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 and locale as query parameters\n const url = new URL(this.iframeUrl);\n if (this.config.publicKey) {\n url.searchParams.set('publicKey', this.config.publicKey);\n }\n if (this.config.config?.paymentId) {\n url.searchParams.set('paymentId', this.config.config.paymentId);\n }\n if (this.config.locale) {\n url.searchParams.set('locale', this.config.locale);\n }\n const iframeSrc = url.toString();\n\n if (this.usePopup) {\n // Use OverlayManager to create popup UI\n const { overlay, container, iframe } = OverlayManager.createOverlay(\n iframeSrc,\n () => this.close()\n );\n\n this.iframe = iframe;\n document.body.appendChild(overlay);\n\n // Show loader\n this.loaderManager = new LoaderManager(container, {\n fillParent: this.config.config?.style?.fillParent,\n });\n this.loaderManager.show(this.iframe);\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 = `${DIMENSIONS.MIN_HEIGHT}px`;\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 this.iframe.style.cssText = getInlineIframeStyles(\n this.config.config?.style?.fillParent || false\n );\n this.iframe.setAttribute('allow', 'payment');\n\n // Append to container\n this.containerElement.appendChild(this.iframe);\n\n // Show loader\n this.loaderManager = new LoaderManager(this.containerElement, {\n fillParent: this.config.config?.style?.fillParent,\n });\n this.loaderManager.show(this.iframe);\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.iframe.inflowpay.com' ||\n event.origin === 'https://pre-prod.iframe.inflowpay.xyz' ||\n event.origin === 'https://iframe.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 if (this.loaderManager) {\n this.loaderManager.hide(this.iframe || undefined);\n }\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, DIMENSIONS.MIN_HEIGHT);\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 console.log('[SDK] Session ID:', data.sessionId);\n }\n if (data.threeDsSessionUrl) {\n const sessionId = data.sessionId;\n const paymentId = data.paymentId || this.config.config?.paymentId || '';\n\n if (!data.sessionId) {\n console.warn('[SDK] No session ID provided by iframe');\n }\n\n if (this.config.debug) {\n console.log('[SDK] Opening 3DS modal with session ID:', sessionId);\n }\n\n this.modalManager.open(data.threeDsSessionUrl, sessionId as string, paymentId).then((success) => {\n if (this.config.debug) {\n console.log('[SDK] 3DS modal closed, result:', success);\n }\n // No longer send message back to iframe - unidirectional flow\n });\n } else {\n if (this.config.debug) {\n console.error('[SDK] 3DS required but no threeDsSessionUrl provided');\n }\n }\n break;\n\n case '3ds-success':\n // 3DS challenge completed via WebSocket, close modal automatically\n if (this.config.debug) {\n console.log('[SDK] 3DS completed, closing modal...');\n console.log('[SDK] Session ID from webhook:', data.sessionId);\n }\n // Pass session ID to validate before closing\n ModalManager.close(data.sessionId);\n break;\n\n case '3ds-failed':\n // 3DS challenge completed via WebSocket, close modal automatically\n if (this.config.debug) {\n console.log('[SDK] 3DS failed, closing modal...');\n console.log('[SDK] Session ID from webhook:', data.sessionId);\n }\n // Pass session ID to validate before closing\n ModalManager.close(data.sessionId);\n break;\n\n default:\n if (this.config.debug) {\n console.log('SDK: Received message:', data);\n }\n\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 publicKey: this.config.publicKey,\n },\n };\n\n const targetOrigin = this.getTargetOrigin();\n this.iframe.contentWindow.postMessage(message, targetOrigin);\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 if (this.loaderManager) {\n this.loaderManager.hide(this.iframe || undefined);\n this.loaderManager = null;\n }\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 OverlayManager.removeOverlay();\n } else {\n // Clear container\n if (this.containerElement) {\n this.containerElement.innerHTML = '';\n }\n }\n\n this.iframe = null;\n }\n\n /**\n * Handle success state: when showDefaultSuccessUI is true, iframe shows success UI\n * and we keep it mounted; when false, we unmount so the parent can render their own.\n */\n public switchToSuccessState(_result: TransactionData): void {\n // Hide loader and remove message listener (same as close)\n if (this.loaderManager) {\n this.loaderManager.hide(this.iframe || undefined);\n this.loaderManager = null;\n }\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n\n if (this.usePopup) {\n OverlayManager.removeOverlay();\n this.iframe = null;\n return;\n }\n\n const showDefault = this.config.config?.showDefaultSuccessUI ?? true;\n\n if (!showDefault && this.containerElement) {\n // Parent will render their own success UI: unmount iframe\n this.containerElement.innerHTML = '';\n }\n if (!showDefault) {\n this.iframe = null;\n }\n // When showDefault is true, keep iframe mounted (success UI is shown inside iframe)\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 * 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 { PaymentResult, PaymentResultStatus } from './react';\nimport { SDK } from './sdk';\n\nimport type { CSSProperties, Locale } from './types';\nimport { detectBrowserLocale } from './utils';\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: PaymentResult) => 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 /** Show default success UI after payment (default true). If false, only unmount iframe. */\n showDefaultSuccessUI?: boolean;\n}\n\ninterface InternalSDKConfig {\n publicKey: string;\n iframeUrl: string;\n timeout: number;\n debug: boolean;\n locale?: Locale;\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 publicKey: config.publicKey,\n container: this.container,\n locale: config.locale ?? detectBrowserLocale(),\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 ...(options.showDefaultSuccessUI !== undefined && {\n showDefaultSuccessUI: options.showDefaultSuccessUI,\n }),\n },\n onSuccess: (data) => {\n if (options.onComplete) {\n options.onComplete({\n status: PaymentResultStatus.SUCCESS,\n paymentId: options.paymentId,\n });\n }\n // Replace iframe with success UI (default, custom, or none)\n this.sdk.switchToSuccessState(data);\n },\n onError: (error) => {\n if (options.onError) {\n options.onError(error);\n } else if (options.onComplete) {\n options.onComplete({\n status: PaymentResultStatus.FAILED,\n paymentId: options.paymentId,\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 { CardElement } from './card-element';\nimport type { PaymentResult } from './react';\nimport type { CSSProperties, Locale } from './types';\nimport { getEnvironmentFromApiKey, getIframeUrlFromApiKey } from './utils';\n\nexport interface PaymentSDKConfig {\n /** Public API key */\n publicKey: string;\n /** Locale for the UI. Defaults to 'en' */\n locale?: Locale;\n}\n\nexport class PaymentSDK {\n private config: PaymentSDKConfig;\n private iframeUrl: string;\n private timeout: number;\n private 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.publicKey || typeof config.publicKey !== 'string') {\n throw new Error('API key is required');\n }\n\n this.config = config;\n this.timeout = 30000;\n\n // Auto-detect iframe URL from API key using utility function\n this.iframeUrl = getIframeUrlFromApiKey(config.publicKey);\n\n // Auto-enable debug in development and sandbox environments\n const environment = getEnvironmentFromApiKey(config.publicKey);\n this.debug = environment === 'sandbox' || environment === 'development';\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: PaymentResult) => void;\n onError?: (error: any) => void;\n onClose?: () => void;\n }): CardElement {\n return new CardElement({\n publicKey: this.config.publicKey,\n iframeUrl: this.iframeUrl,\n timeout: this.timeout,\n debug: this.debug,\n locale: this.config.locale,\n }, options);\n }\n\n /**\n * Get the iframe URL being used\n */\n getIframeUrl(): string {\n return this.iframeUrl;\n }\n\n /**\n * Get the API key\n */\n getApiKey(): string {\n return this.config.publicKey;\n }\n}\n\n"],"names":["PaymentResultStatus","PaymentResultErrorCode","InflowPayContext","createContext","InflowPayProvider","config","children","sdk","useState","sdkConfig","PaymentSDK","jsx","useInflowPay","context","useContext","CardElement","props","paymentId","onReady","onChange","onComplete","onError","style","buttonText","placeholders","showDefaultSuccessUI","propConfig","containerRef","useRef","cardElementRef","mounted","setMounted","useEffect","cardElementOptions","result","error","cardElement","timer","Z_INDEX","DIMENSIONS","ALLOWED_3DS_ORIGINS","ELEMENT_IDS","IFRAME_URLS","getColorScheme","isDarkMode","getShimmerGradient","colors","getOverlayStyles","getContainerStyles","getCloseButtonStyles","getPopupIframeStyles","getInlineIframeStyles","fillParent","getLoaderContainerStyles","getSkeletonCardStyles","getInputWrapStyles","bgColor","getSkeletonBaseStyles","shimmerGradient","getCardNumberSkeletonStyles","getExpirySkeletonStyles","getCvcSkeletonStyles","getButtonSkeletonStyles","getDisclaimerSkeletonStyles","getDisclaimerIconSkeletonStyles","getDisclaimerTextSkeletonStyles","SHIMMER_ANIMATION","get3DSOverlayStyles","get3DSModalStyles","get3DSHeaderStyles","get3DSContentStyles","get3DSIframeStyles","LoaderManager","container","iframe","loader","skeletonCard","inputWrap","cardNumberSkeleton","expirySkeleton","cvcSkeleton","buttonSkeleton","disclaimerSkeleton","disclaimerIconSkeleton","disclaimerTextSkeleton","_ModalManager","challengeUrl","sessionId","resolve","overlay","modal","header","content","messageHandler","event","data","is3DSComplete","isSuccess","isFailure","origin","ModalManager","OverlayManager","iframeSrc","onClose","closeButton","e","SUPPORTED_LOCALES","detectBrowserLocale","primaryLang","getEnvironmentFromApiKey","publicKey","getIframeUrlFromApiKey","SDK","url","currentStyle","allowedOrigin","isAllowedOrigin","height","success","message","targetOrigin","_result","showDefault","options","containerElement","environment"],"mappings":"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"}
|