@inflow_pay/sdk 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -83
- package/dist/payment-sdk-BWb7DDT1.js +88 -0
- package/dist/payment-sdk-BWb7DDT1.js.map +1 -0
- package/dist/payment-sdk-CH8ugKck.mjs +411 -0
- package/dist/payment-sdk-CH8ugKck.mjs.map +1 -0
- package/dist/react/index.d.ts +310 -0
- package/dist/react.cjs +2 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.esm.js +64 -719
- package/dist/react.esm.js.map +1 -1
- package/dist/react.umd.js +30 -13
- package/dist/react.umd.js.map +1 -1
- package/dist/sdk.cjs +2 -0
- package/dist/sdk.cjs.map +1 -0
- package/dist/sdk.d.ts +326 -5
- package/dist/sdk.esm.js +29 -420
- package/dist/sdk.esm.js.map +1 -1
- package/dist/sdk.umd.js +13 -12
- package/dist/sdk.umd.js.map +1 -1
- package/package.json +21 -28
- package/dist/react.d.ts +0 -104
- package/dist/react.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -8,27 +8,45 @@ Accept card payments with a pre-built, secure payment form. **Same API as the Re
|
|
|
8
8
|
npm install @inflow_pay/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Or use via CDN (UMD build):
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<!-- Main SDK -->
|
|
15
|
+
<script src="https://cdn.inflowpay.com/sdk/v2/sdk.umd.js"></script>
|
|
16
|
+
<script>
|
|
17
|
+
// SDK is available as window.InflowPaySDK
|
|
18
|
+
const provider = new InflowPaySDK.InflowPayProvider({
|
|
19
|
+
config: { apiKey: 'inflow_pub_xxx' }
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<!-- React SDK (if using React) -->
|
|
24
|
+
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
25
|
+
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
26
|
+
<script src="https://cdn.inflowpay.com/sdk/v2/react.umd.js"></script>
|
|
27
|
+
```
|
|
28
|
+
|
|
11
29
|
## Quick Start
|
|
12
30
|
|
|
13
31
|
**Same API as React SDK!** Easy migration from React SDK to iframe-based SDK:
|
|
14
32
|
|
|
15
33
|
```javascript
|
|
16
|
-
import { InflowPayProvider } from
|
|
34
|
+
import { InflowPayProvider } from '@inflow_pay/sdk';
|
|
17
35
|
|
|
18
36
|
// Step 1: Create InflowPayProvider (same as React's <InflowPayProvider>)
|
|
19
37
|
const provider = new InflowPayProvider({
|
|
20
|
-
config: { apiKey:
|
|
38
|
+
config: { apiKey: 'inflow_pub_xxx' }
|
|
21
39
|
});
|
|
22
40
|
|
|
23
41
|
// Step 2: Create CardElement (same as React's <CardElement>)
|
|
24
42
|
const cardElement = provider.createCardElement({
|
|
25
|
-
paymentId:
|
|
26
|
-
container:
|
|
43
|
+
paymentId: 'pay_xxx', // From your backend
|
|
44
|
+
container: '#card-container',
|
|
27
45
|
onComplete: (result) => {
|
|
28
|
-
if (result.status ===
|
|
29
|
-
window.location.href =
|
|
46
|
+
if (result.status === 'CHECKOUT_SUCCESS') {
|
|
47
|
+
window.location.href = '/success';
|
|
30
48
|
}
|
|
31
|
-
}
|
|
49
|
+
}
|
|
32
50
|
});
|
|
33
51
|
|
|
34
52
|
// Step 3: Mount the CardElement
|
|
@@ -48,15 +66,19 @@ cardElement.mount();
|
|
|
48
66
|
|
|
49
67
|
Payments progress through these statuses:
|
|
50
68
|
|
|
51
|
-
| Status
|
|
52
|
-
|
|
53
|
-
| `CHECKOUT_SUCCESS` | Payment confirmed | ✅ Yes
|
|
54
|
-
| `
|
|
69
|
+
| Status | Description | Success? |
|
|
70
|
+
|--------|-------------|----------|
|
|
71
|
+
| `CHECKOUT_SUCCESS` | Payment confirmed | ✅ Yes |
|
|
72
|
+
| `PAYMENT_RECEIVED` | Funds received | ✅ Yes |
|
|
73
|
+
| `PAYMENT_SUCCESS` | Complete | ✅ Yes |
|
|
74
|
+
| `PAYMENT_FAILED` | Failed | ❌ No |
|
|
55
75
|
|
|
56
76
|
**Check for success:**
|
|
57
77
|
|
|
58
78
|
```javascript
|
|
59
|
-
if (result.status ===
|
|
79
|
+
if (result.status === 'CHECKOUT_SUCCESS' ||
|
|
80
|
+
result.status === 'PAYMENT_RECEIVED' ||
|
|
81
|
+
result.status === 'PAYMENT_SUCCESS') {
|
|
60
82
|
// Payment successful
|
|
61
83
|
}
|
|
62
84
|
```
|
|
@@ -68,11 +90,11 @@ if (result.status === "CHECKOUT_SUCCESS") {
|
|
|
68
90
|
```javascript
|
|
69
91
|
const provider = new InflowPayProvider({
|
|
70
92
|
config: {
|
|
71
|
-
apiKey:
|
|
72
|
-
iframeUrl:
|
|
73
|
-
timeout: 30000,
|
|
74
|
-
debug: false
|
|
75
|
-
}
|
|
93
|
+
apiKey: 'inflow_pub_xxx', // Required
|
|
94
|
+
iframeUrl: 'https://...', // Optional, auto-detected from API key
|
|
95
|
+
timeout: 30000, // Optional, default: 30000
|
|
96
|
+
debug: false // Optional, default: false
|
|
97
|
+
}
|
|
76
98
|
});
|
|
77
99
|
```
|
|
78
100
|
|
|
@@ -80,34 +102,34 @@ const provider = new InflowPayProvider({
|
|
|
80
102
|
|
|
81
103
|
```javascript
|
|
82
104
|
const cardElement = provider.createCardElement({
|
|
83
|
-
paymentId:
|
|
84
|
-
container:
|
|
85
|
-
|
|
105
|
+
paymentId: 'pay_xxx', // Required
|
|
106
|
+
container: '#card-container', // Required (CSS selector or HTMLElement)
|
|
107
|
+
|
|
86
108
|
// Callbacks (same as React SDK)
|
|
87
109
|
onReady: () => {
|
|
88
110
|
// Card element is mounted and ready
|
|
89
111
|
},
|
|
90
|
-
|
|
112
|
+
|
|
91
113
|
onChange: (state) => {
|
|
92
114
|
// Track validation state
|
|
93
115
|
// state.complete - whether form is valid
|
|
94
116
|
},
|
|
95
|
-
|
|
117
|
+
|
|
96
118
|
onComplete: (result) => {
|
|
97
119
|
// Payment complete (success or failure)
|
|
98
120
|
if (result.error) {
|
|
99
121
|
console.error(result.error.message);
|
|
100
122
|
}
|
|
101
123
|
},
|
|
102
|
-
|
|
124
|
+
|
|
103
125
|
onError: (error) => {
|
|
104
126
|
// SDK-level errors (network, validation)
|
|
105
127
|
console.error(error);
|
|
106
128
|
},
|
|
107
|
-
|
|
129
|
+
|
|
108
130
|
onClose: () => {
|
|
109
131
|
// User closed the payment
|
|
110
|
-
}
|
|
132
|
+
}
|
|
111
133
|
});
|
|
112
134
|
|
|
113
135
|
// Mount the CardElement
|
|
@@ -137,32 +159,33 @@ cardElement.destroy();
|
|
|
137
159
|
```html
|
|
138
160
|
<!DOCTYPE html>
|
|
139
161
|
<html>
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
</
|
|
162
|
+
<head>
|
|
163
|
+
<title>My Payment Page</title>
|
|
164
|
+
</head>
|
|
165
|
+
<body>
|
|
166
|
+
<div id="card-container"></div>
|
|
167
|
+
|
|
168
|
+
<script src="https://cdn.inflowpay.com/sdk/v2/sdk.umd.js"></script>
|
|
169
|
+
<script>
|
|
170
|
+
// Same API as React SDK!
|
|
171
|
+
// SDK is available as window.InflowPaySDK
|
|
172
|
+
const provider = new InflowPaySDK.InflowPayProvider({
|
|
173
|
+
config: { apiKey: 'inflow_pub_xxx' }
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const cardElement = provider.createCardElement({
|
|
177
|
+
paymentId: 'pay_xxx',
|
|
178
|
+
container: '#card-container',
|
|
179
|
+
onComplete: (result) => {
|
|
180
|
+
if (result.status === InflowPaySDK.PaymentStatus.CHECKOUT_SUCCESS) {
|
|
181
|
+
alert('Payment successful!');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
cardElement.mount();
|
|
187
|
+
</script>
|
|
188
|
+
</body>
|
|
166
189
|
</html>
|
|
167
190
|
```
|
|
168
191
|
|
|
@@ -203,25 +226,25 @@ Create payments on your backend with your **private key**:
|
|
|
203
226
|
|
|
204
227
|
```javascript
|
|
205
228
|
// Your backend (Node.js example)
|
|
206
|
-
const response = await fetch(
|
|
207
|
-
method:
|
|
229
|
+
const response = await fetch('https://api.inflowpay.xyz/api/server/payment', {
|
|
230
|
+
method: 'POST',
|
|
208
231
|
headers: {
|
|
209
|
-
Accept:
|
|
210
|
-
|
|
211
|
-
|
|
232
|
+
'Accept': 'application/json',
|
|
233
|
+
'Content-Type': 'application/json',
|
|
234
|
+
'X-Inflow-Api-Key': 'inflow_priv_xxx' // Private key
|
|
212
235
|
},
|
|
213
236
|
body: JSON.stringify({
|
|
214
|
-
products: [{ name:
|
|
215
|
-
currency:
|
|
216
|
-
customerEmail:
|
|
217
|
-
billingCountry:
|
|
218
|
-
postalCode:
|
|
219
|
-
firstName:
|
|
220
|
-
lastName:
|
|
237
|
+
products: [{ name: 'Product', price: 4999, quantity: 1 }],
|
|
238
|
+
currency: 'EUR',
|
|
239
|
+
customerEmail: 'customer@example.com',
|
|
240
|
+
billingCountry: 'FR',
|
|
241
|
+
postalCode: '75001',
|
|
242
|
+
firstName: 'John',
|
|
243
|
+
lastName: 'Doe',
|
|
221
244
|
purchasingAsBusiness: false,
|
|
222
|
-
successUrl:
|
|
223
|
-
cancelUrl:
|
|
224
|
-
})
|
|
245
|
+
successUrl: 'https://yourdomain.com/success',
|
|
246
|
+
cancelUrl: 'https://yourdomain.com/cancel'
|
|
247
|
+
})
|
|
225
248
|
});
|
|
226
249
|
|
|
227
250
|
const { payment } = await response.json();
|
|
@@ -240,16 +263,16 @@ If you're using React, you can use the React components which work **exactly lik
|
|
|
240
263
|
|
|
241
264
|
```tsx
|
|
242
265
|
// Just change the import path!
|
|
243
|
-
import { InflowPayProvider, CardElement } from
|
|
266
|
+
import { InflowPayProvider, CardElement } from '@inflow_pay/sdk/react';
|
|
244
267
|
|
|
245
268
|
function App() {
|
|
246
269
|
return (
|
|
247
|
-
<InflowPayProvider config={{ apiKey:
|
|
270
|
+
<InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>
|
|
248
271
|
<CardElement
|
|
249
272
|
paymentId={paymentId}
|
|
250
273
|
onComplete={(result) => {
|
|
251
|
-
if (result.status ===
|
|
252
|
-
window.location.href =
|
|
274
|
+
if (result.status === 'CHECKOUT_SUCCESS') {
|
|
275
|
+
window.location.href = '/success';
|
|
253
276
|
}
|
|
254
277
|
}}
|
|
255
278
|
/>
|
|
@@ -265,27 +288,26 @@ function App() {
|
|
|
265
288
|
If you're not using React, you can use the vanilla JavaScript API:
|
|
266
289
|
|
|
267
290
|
```javascript
|
|
268
|
-
import { InflowPayProvider } from
|
|
291
|
+
import { InflowPayProvider } from '@inflow_pay/sdk';
|
|
269
292
|
|
|
270
293
|
const provider = new InflowPayProvider({
|
|
271
|
-
config: { apiKey:
|
|
294
|
+
config: { apiKey: 'inflow_pub_xxx' }
|
|
272
295
|
});
|
|
273
296
|
|
|
274
297
|
const cardElement = provider.createCardElement({
|
|
275
298
|
paymentId: paymentId,
|
|
276
|
-
container:
|
|
299
|
+
container: '#card-container',
|
|
277
300
|
onComplete: (result) => {
|
|
278
|
-
if (result.status ===
|
|
279
|
-
window.location.href =
|
|
301
|
+
if (result.status === 'CHECKOUT_SUCCESS') {
|
|
302
|
+
window.location.href = '/success';
|
|
280
303
|
}
|
|
281
|
-
}
|
|
304
|
+
}
|
|
282
305
|
});
|
|
283
306
|
|
|
284
307
|
cardElement.mount();
|
|
285
308
|
```
|
|
286
309
|
|
|
287
310
|
**Key differences from React version:**
|
|
288
|
-
|
|
289
311
|
- No React required - works with vanilla JavaScript
|
|
290
312
|
- Explicit `container` prop (CSS selector or HTMLElement) instead of JSX
|
|
291
313
|
- Call `mount()` explicitly instead of automatic React mounting
|
|
@@ -296,16 +318,16 @@ cardElement.mount();
|
|
|
296
318
|
Full type definitions included:
|
|
297
319
|
|
|
298
320
|
```typescript
|
|
299
|
-
import { InflowPayProvider, PaymentStatus } from
|
|
300
|
-
import type { PaymentResult, PaymentError } from
|
|
321
|
+
import { InflowPayProvider, PaymentStatus } from '@inflow_pay/sdk';
|
|
322
|
+
import type { PaymentResult, PaymentError } from '@inflow_pay/sdk';
|
|
301
323
|
|
|
302
324
|
const provider = new InflowPayProvider({
|
|
303
|
-
config: { apiKey:
|
|
325
|
+
config: { apiKey: 'inflow_pub_xxx' }
|
|
304
326
|
});
|
|
305
327
|
|
|
306
328
|
const cardElement = provider.createCardElement({
|
|
307
|
-
paymentId:
|
|
308
|
-
container:
|
|
329
|
+
paymentId: 'pay_xxx',
|
|
330
|
+
container: '#card-container',
|
|
309
331
|
onComplete: (result: PaymentResult) => {
|
|
310
332
|
if (result.status === PaymentStatus.CHECKOUT_SUCCESS) {
|
|
311
333
|
// Success
|
|
@@ -313,7 +335,7 @@ const cardElement = provider.createCardElement({
|
|
|
313
335
|
},
|
|
314
336
|
onError: (error: PaymentError) => {
|
|
315
337
|
console.error(error);
|
|
316
|
-
}
|
|
338
|
+
}
|
|
317
339
|
});
|
|
318
340
|
```
|
|
319
341
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";class u{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
|
+
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: 999999;
|
|
12
|
+
`;const n=document.createElement("div");n.style.cssText=`
|
|
13
|
+
position: relative;
|
|
14
|
+
width: 90%;
|
|
15
|
+
max-width: 500px;
|
|
16
|
+
height: 90%;
|
|
17
|
+
max-height: 600px;
|
|
18
|
+
background: white;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
21
|
+
`;const s=document.createElement("button");s.innerHTML="×",s.style.cssText=`
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: 10px;
|
|
24
|
+
right: 10px;
|
|
25
|
+
width: 30px;
|
|
26
|
+
height: 30px;
|
|
27
|
+
border: none;
|
|
28
|
+
background: transparent;
|
|
29
|
+
font-size: 24px;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
z-index: 1000000;
|
|
32
|
+
color: #333;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
`,s.onclick=()=>this.close(),this.iframe=document.createElement("iframe"),this.iframe.src=t,this.iframe.style.cssText=`
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 100%;
|
|
39
|
+
border: none;
|
|
40
|
+
border-radius: 8px;
|
|
41
|
+
`,this.iframe.setAttribute("allow","payment"),n.appendChild(s),n.appendChild(this.iframe),i.appendChild(n),document.body.appendChild(i),i.addEventListener("click",r=>{r.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="175px"),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
|
+
width: ${i};
|
|
43
|
+
max-width: ${n};
|
|
44
|
+
height: 100%;
|
|
45
|
+
min-height: 175px;
|
|
46
|
+
border: none;
|
|
47
|
+
display: block;
|
|
48
|
+
`,this.iframe.setAttribute("allow","payment"),this.containerElement.appendChild(this.iframe)}}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.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(r=>{if(this.config.debug&&console.log("[SDK] 3DS modal closed, result:",r),this.iframe&&this.iframe.contentWindow){const a=this.getTargetOrigin();this.iframe.contentWindow.postMessage({type:"3ds-result",success:r,paymentId:s.paymentId||this.config.config?.paymentId},a)}})):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)}close(){if(this.config.onClose&&this.config.onClose(),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.usePopup){const e=document.getElementById("inflowpay-sdk-overlay");e&&e.remove()}else this.containerElement&&this.iframe&&this.containerElement.removeChild(this.iframe);this.iframe=null}open3DSModal(e){return this.config.debug&&console.log("[SDK] open3DSModal called with URL:",e),new Promise(t=>{const i=document.createElement("div");i.id="inflowpay-3ds-overlay",i.style.cssText=`
|
|
49
|
+
position: fixed;
|
|
50
|
+
top: 0;
|
|
51
|
+
left: 0;
|
|
52
|
+
width: 100%;
|
|
53
|
+
height: 100%;
|
|
54
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
z-index: 999999;
|
|
59
|
+
`;const n=document.createElement("div");n.style.cssText=`
|
|
60
|
+
position: relative;
|
|
61
|
+
width: 90%;
|
|
62
|
+
max-width: 500px;
|
|
63
|
+
height: 90%;
|
|
64
|
+
max-height: 600px;
|
|
65
|
+
background: white;
|
|
66
|
+
border-radius: 8px;
|
|
67
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
`;const s=document.createElement("div");s.style.cssText=`
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
justify-content: space-between;
|
|
74
|
+
padding: 15px 20px;
|
|
75
|
+
border-bottom: 1px solid #e5e5e5;
|
|
76
|
+
`,s.innerHTML=`
|
|
77
|
+
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">Secure Payment Authentication</h3>
|
|
78
|
+
<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>
|
|
79
|
+
`;const r=document.createElement("div");r.style.cssText=`
|
|
80
|
+
flex: 1;
|
|
81
|
+
position: relative;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
`;const a=document.createElement("iframe");a.src=e,a.style.cssText=`
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
border: none;
|
|
87
|
+
`,a.setAttribute("allow","payment"),a.setAttribute("sandbox","allow-forms allow-scripts allow-same-origin allow-popups"),r.appendChild(a),n.appendChild(s),n.appendChild(r),i.appendChild(n),document.body.appendChild(i);const y=i.querySelector("#inflowpay-3ds-close"),w=()=>{i.remove(),window.removeEventListener("message",d),t(!1)};y?.addEventListener("click",w);const d=o=>{if(!o.data)return;const m=["https://dev.api.inflowpay.com","https://pre-prod.api.inflowpay.xyz","https://api.inflowpay.xyz"];if(this.environment==="sandbox"||this.environment==="development"){if(!(o.origin.includes("localhost")||o.origin.includes("127.0.0.1"))){if(!m.includes(o.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",o.origin);return}}}else if(!m.includes(o.origin)){this.config.debug&&console.warn("[SDK] Rejected 3DS message from unauthorized origin:",o.origin);return}const l=o.data,c=l.type==="THREE_DS_COMPLETE"||l.type==="3ds-complete",f=l.status==="success",p=l.status==="failed"||l.status==="failure";if(c&&f){i.remove(),window.removeEventListener("message",d),t(!0);return}if(f&&!c){i.remove(),window.removeEventListener("message",d),t(!0);return}if(c&&p||l.type==="3ds-failed"||p){i.remove(),window.removeEventListener("message",d),t(!1);return}};window.addEventListener("message",d)})}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 g{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 u({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 x{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 g(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=g;exports.PaymentSDK=x;exports.SDK=u;
|
|
88
|
+
//# sourceMappingURL=payment-sdk-BWb7DDT1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-sdk-BWb7DDT1.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 // 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 = '175px';\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: 100%;\n min-height: 175px;\n border: none;\n display: block;\n `;\n\n this.iframe.setAttribute('allow', 'payment');\n\n // Append to container\n this.containerElement.appendChild(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.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.sendConfigToIframe();\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 * Close the iframe and cleanup\n */\n private close(): void {\n if (this.config.onClose) {\n this.config.onClose();\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 const overlay = document.getElementById('inflowpay-sdk-overlay');\n if (overlay) {\n overlay.remove();\n }\n } else {\n // Clear container\n if (this.containerElement && this.iframe) {\n this.containerElement.removeChild(this.iframe);\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","success","targetOrigin","message","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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"}
|