@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.
@@ -0,0 +1,821 @@
1
+ import { jsx as k } from "react/jsx-runtime";
2
+ import { createContext as K, useContext as _, useRef as R, useState as N, useEffect as D } from "react";
3
+ var b = /* @__PURE__ */ ((t) => (t.SUCCESS = "SUCCESS", t.FAILED = "FAILED", t))(b || {}), U = /* @__PURE__ */ ((t) => (t.THREE_DS_FAILED = "THREE_DS_FAILED", t.PAYMENT_PROCESSING_ERROR = "PAYMENT_PROCESSING_ERROR", t))(U || {});
4
+ const L = K(null);
5
+ function ye({
6
+ config: t,
7
+ children: e
8
+ }) {
9
+ const [n] = N(() => {
10
+ const o = {
11
+ publicKey: t.publicKey,
12
+ locale: t.locale
13
+ };
14
+ return new H(o);
15
+ });
16
+ return /* @__PURE__ */ k(L.Provider, { value: { sdk: n }, children: e });
17
+ }
18
+ function Ee() {
19
+ const t = _(L);
20
+ if (!t)
21
+ throw new Error("useInflowPay must be used within InflowPayProvider");
22
+ return t.sdk;
23
+ }
24
+ function we(t) {
25
+ const {
26
+ paymentId: e,
27
+ onReady: n,
28
+ onChange: o,
29
+ onComplete: s,
30
+ onError: i,
31
+ style: r,
32
+ buttonText: a,
33
+ placeholders: u,
34
+ showDefaultSuccessUI: h,
35
+ config: m
36
+ } = t, p = _(L), l = R(null), f = R(null), [g, x] = N(!1), T = p?.sdk || (m ? new H({
37
+ publicKey: m.publicKey,
38
+ locale: m.locale
39
+ }) : null);
40
+ if (!T)
41
+ throw new Error("CardElement must be used within InflowPayProvider or have a config prop");
42
+ return D(() => {
43
+ if (!l.current)
44
+ return;
45
+ l.current.id || (l.current.id = `inflowpay-card-element-${Date.now()}`);
46
+ const $ = {
47
+ container: l.current,
48
+ paymentId: e,
49
+ ...r && { style: r },
50
+ ...a && { buttonText: a },
51
+ ...u && { placeholders: u },
52
+ ...h !== void 0 && { showDefaultSuccessUI: h },
53
+ onComplete: (E) => {
54
+ s && s(E);
55
+ },
56
+ onError: (E) => {
57
+ i ? i(E) : s && s({
58
+ status: b.FAILED,
59
+ paymentId: e,
60
+ error: E
61
+ });
62
+ },
63
+ onClose: () => {
64
+ }
65
+ }, O = T.createCardElement($);
66
+ if (f.current = O, O.mount(), x(!0), n) {
67
+ const E = setTimeout(() => {
68
+ n();
69
+ }, 100);
70
+ return () => clearTimeout(E);
71
+ }
72
+ }, [e, T, s, i, n, r, a, u, h]), D(() => {
73
+ o && g && o({ complete: !1 });
74
+ }, [g, o]), D(() => () => {
75
+ f.current && (f.current.destroy(), f.current = null);
76
+ }, []), /* @__PURE__ */ k(
77
+ "div",
78
+ {
79
+ ref: l,
80
+ style: {
81
+ width: r?.fillParent ? "100%" : "344px"
82
+ }
83
+ }
84
+ );
85
+ }
86
+ const v = {
87
+ OVERLAY: 999999,
88
+ MODAL: 1e6,
89
+ LOADER: 1e3
90
+ }, c = {
91
+ MIN_HEIGHT: 196,
92
+ CONTAINER_MAX_WIDTH: "500px",
93
+ CONTAINER_WIDTH_PERCENT: "90%",
94
+ CONTAINER_HEIGHT_PERCENT: "90%",
95
+ CONTAINER_MAX_HEIGHT: "600px",
96
+ BUTTON_SIZE: 30,
97
+ DEFAULT_IFRAME_WIDTH: "344px"
98
+ }, F = [
99
+ "https://dev.api.inflowpay.xyz",
100
+ "https://pre-prod.api.inflowpay.xyz",
101
+ "https://api.inflowpay.xyz"
102
+ ], y = {
103
+ OVERLAY: "inflowpay-sdk-overlay",
104
+ LOADER: "inflowpay-loader",
105
+ LOADER_STYLES: "inflowpay-loader-styles",
106
+ THREE_DS_OVERLAY: "inflowpay-3ds-overlay"
107
+ }, I = {
108
+ PRODUCTION: "https://iframe.inflowpay.com/iframe/checkout",
109
+ PREPROD: "https://preprod.iframe.inflowpay.com/iframe/checkout",
110
+ DEVELOPMENT: "https://dev.iframe.inflowpay.com/iframe/checkout",
111
+ LOCAL: "http://localhost:3010/iframe/checkout"
112
+ };
113
+ function W(t) {
114
+ return {
115
+ inputBgColor: t ? "#2d2d2d" : "#F5F5F5",
116
+ shimmerBase: t ? "#3d3d3d" : "#E5E5E5",
117
+ shimmerLight: t ? "#4d4d4d" : "#F0F0F0"
118
+ };
119
+ }
120
+ function B(t) {
121
+ return `linear-gradient(90deg, ${t.shimmerBase} 25%, ${t.shimmerLight} 50%, ${t.shimmerBase} 75%)`;
122
+ }
123
+ function G() {
124
+ return `
125
+ position: fixed;
126
+ top: 0;
127
+ left: 0;
128
+ width: 100%;
129
+ height: 100%;
130
+ background-color: rgba(0, 0, 0, 0.5);
131
+ display: flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ z-index: ${v.OVERLAY};
135
+ `;
136
+ }
137
+ function z() {
138
+ return `
139
+ position: relative;
140
+ width: ${c.CONTAINER_WIDTH_PERCENT};
141
+ max-width: ${c.CONTAINER_MAX_WIDTH};
142
+ height: ${c.CONTAINER_HEIGHT_PERCENT};
143
+ max-height: ${c.CONTAINER_MAX_HEIGHT};
144
+ background: white;
145
+ border-radius: 8px;
146
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
147
+ `;
148
+ }
149
+ function Y() {
150
+ return `
151
+ position: absolute;
152
+ top: 10px;
153
+ right: 10px;
154
+ width: ${c.BUTTON_SIZE}px;
155
+ height: ${c.BUTTON_SIZE}px;
156
+ border: none;
157
+ background: transparent;
158
+ font-size: 24px;
159
+ cursor: pointer;
160
+ z-index: ${v.MODAL};
161
+ color: #333;
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ `;
166
+ }
167
+ function j() {
168
+ return `
169
+ width: 100%;
170
+ height: 100%;
171
+ border: none;
172
+ border-radius: 8px;
173
+ `;
174
+ }
175
+ function V(t) {
176
+ return `
177
+ width: ${t ? "100%" : c.DEFAULT_IFRAME_WIDTH};
178
+ max-width: ${t ? "none" : "100%"};
179
+ height: ${c.MIN_HEIGHT}px;
180
+ min-height: ${c.MIN_HEIGHT}px;
181
+ border: none;
182
+ display: block;
183
+ transition: height 0.2s ease;
184
+ `;
185
+ }
186
+ function q() {
187
+ return `
188
+ position: absolute;
189
+ top: 0;
190
+ left: 0;
191
+ width: 100%;
192
+ height: 100%;
193
+ z-index: ${v.LOADER};
194
+ padding: 20px;
195
+ box-sizing: border-box;
196
+ display: flex;
197
+ flex-direction: column;
198
+ align-items: center;
199
+ `;
200
+ }
201
+ function X(t) {
202
+ return `
203
+ width: ${t ? "100%" : c.DEFAULT_IFRAME_WIDTH};
204
+ max-width: 100%;
205
+ margin: 0 auto;
206
+ `;
207
+ }
208
+ function Z(t) {
209
+ return `
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ gap: 6px;
214
+ background-color: ${t};
215
+ padding: 8px;
216
+ border-radius: 8px;
217
+ margin-bottom: 20px;
218
+ `;
219
+ }
220
+ function w(t) {
221
+ return `
222
+ background: ${t};
223
+ background-size: 200% 100%;
224
+ animation: inflowpay-shimmer 1.5s infinite;
225
+ `;
226
+ }
227
+ function J(t) {
228
+ return `
229
+ flex: 1;
230
+ min-width: 0;
231
+ height: 32px;
232
+ border-radius: 6px;
233
+ ${w(t)}
234
+ `;
235
+ }
236
+ function Q(t) {
237
+ return `
238
+ width: 21.5%;
239
+ flex-shrink: 0;
240
+ height: 32px;
241
+ border-radius: 6px;
242
+ ${w(t)}
243
+ `;
244
+ }
245
+ function ee(t) {
246
+ return `
247
+ width: 17.5%;
248
+ flex-shrink: 0;
249
+ height: 32px;
250
+ border-radius: 6px;
251
+ ${w(t)}
252
+ `;
253
+ }
254
+ function te(t) {
255
+ return `
256
+ width: 100%;
257
+ height: 42px;
258
+ border-radius: 8px;
259
+ ${w(t)}
260
+ margin-bottom: 16px;
261
+ `;
262
+ }
263
+ function ne() {
264
+ return `
265
+ display: flex;
266
+ flex-direction: column;
267
+ align-items: center;
268
+ gap: 4px;
269
+ width: 100%;
270
+ margin-top: 16px;
271
+ `;
272
+ }
273
+ function ie(t) {
274
+ return `
275
+ width: 10px;
276
+ height: 10px;
277
+ border-radius: 50%;
278
+ ${w(t)}
279
+ `;
280
+ }
281
+ function se(t) {
282
+ return `
283
+ width: 80%;
284
+ height: 16px;
285
+ border-radius: 4px;
286
+ ${w(t)}
287
+ `;
288
+ }
289
+ const oe = `
290
+ @keyframes inflowpay-shimmer {
291
+ 0% {
292
+ background-position: -200% 0;
293
+ }
294
+ 100% {
295
+ background-position: 200% 0;
296
+ }
297
+ }
298
+ `;
299
+ function re() {
300
+ return `
301
+ position: fixed;
302
+ top: 0;
303
+ left: 0;
304
+ width: 100%;
305
+ height: 100%;
306
+ background-color: rgba(0, 0, 0, 0.7);
307
+ display: flex;
308
+ align-items: center;
309
+ justify-content: center;
310
+ z-index: ${v.OVERLAY};
311
+ `;
312
+ }
313
+ function ae() {
314
+ return `
315
+ position: relative;
316
+ width: ${c.CONTAINER_WIDTH_PERCENT};
317
+ max-width: ${c.CONTAINER_MAX_WIDTH};
318
+ height: ${c.CONTAINER_HEIGHT_PERCENT};
319
+ max-height: ${c.CONTAINER_MAX_HEIGHT};
320
+ background: white;
321
+ border-radius: 16px;
322
+ overflow: hidden;
323
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
324
+ display: flex;
325
+ flex-direction: column;
326
+ `;
327
+ }
328
+ function le() {
329
+ return `
330
+ display: flex;
331
+ align-items: center;
332
+ justify-content: space-between;
333
+ padding: 15px 20px;
334
+ border-bottom: 1px solid #e5e5e5;
335
+ `;
336
+ }
337
+ function ce() {
338
+ return `
339
+ flex: 1;
340
+ position: relative;
341
+ overflow-y: auto;
342
+ overflow-x: hidden;
343
+ `;
344
+ }
345
+ function de() {
346
+ return `
347
+ width: 100%;
348
+ height: 100%;
349
+ border: none;
350
+ `;
351
+ }
352
+ class M {
353
+ constructor(e, n = {}) {
354
+ this.loaderElement = null, this.container = e, this.config = n;
355
+ }
356
+ /**
357
+ * Show skeleton loader
358
+ */
359
+ show(e) {
360
+ e && (e.style.display = "none");
361
+ const n = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches, o = W(n), s = B(o), i = document.createElement("div");
362
+ i.id = y.LOADER, i.style.cssText = q();
363
+ const r = document.createElement("div");
364
+ r.style.cssText = X(this.config.fillParent || !1);
365
+ const a = document.createElement("div");
366
+ a.style.cssText = Z(o.inputBgColor);
367
+ const u = document.createElement("div");
368
+ u.className = "inflowpay-skeleton", u.style.cssText = J(s);
369
+ const h = document.createElement("div");
370
+ h.className = "inflowpay-skeleton", h.style.cssText = Q(s);
371
+ const m = document.createElement("div");
372
+ m.className = "inflowpay-skeleton", m.style.cssText = ee(s), a.appendChild(u), a.appendChild(h), a.appendChild(m);
373
+ const p = document.createElement("div");
374
+ p.className = "inflowpay-skeleton", p.style.cssText = te(s);
375
+ const l = document.createElement("div");
376
+ l.style.cssText = ne();
377
+ const f = document.createElement("div");
378
+ f.className = "inflowpay-skeleton", f.style.cssText = ie(s);
379
+ const g = document.createElement("div");
380
+ g.className = "inflowpay-skeleton", g.style.cssText = se(s), l.appendChild(f), l.appendChild(g), r.appendChild(a), r.appendChild(p), r.appendChild(l), i.appendChild(r), this.injectShimmerStyles(), this.container.appendChild(i), this.loaderElement = i;
381
+ }
382
+ /**
383
+ * Hide loader
384
+ */
385
+ hide(e) {
386
+ const n = document.getElementById(y.LOADER);
387
+ n && n.remove(), this.loaderElement = null, e && (e.style.display = "");
388
+ }
389
+ /**
390
+ * Inject shimmer animation styles into document head
391
+ */
392
+ injectShimmerStyles() {
393
+ if (!document.getElementById(y.LOADER_STYLES)) {
394
+ const e = document.createElement("style");
395
+ e.id = y.LOADER_STYLES, e.textContent = oe, document.head.appendChild(e);
396
+ }
397
+ }
398
+ }
399
+ const d = class d {
400
+ constructor(e) {
401
+ this.config = e;
402
+ }
403
+ /**
404
+ * Open 3DS authentication modal
405
+ * Returns a Promise that resolves with the authentication result
406
+ */
407
+ open(e, n, o) {
408
+ 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) => {
409
+ const i = document.createElement("div");
410
+ i.id = y.THREE_DS_OVERLAY, i.style.cssText = re();
411
+ const r = document.createElement("div");
412
+ r.style.cssText = ae();
413
+ const a = document.createElement("div");
414
+ a.style.cssText = le(), a.innerHTML = `
415
+ <h3 style="margin: 0; font-size: 18px; font-weight: 600;">Secure Payment Authentication</h3>
416
+ `;
417
+ const u = document.createElement("div");
418
+ u.style.cssText = ce();
419
+ const h = document.createElement("iframe");
420
+ 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 = {
421
+ overlay: i,
422
+ sessionId: n,
423
+ paymentId: o
424
+ };
425
+ const m = (p) => {
426
+ if (!p.data) return;
427
+ if (!this.isAllowedOrigin(p.origin)) {
428
+ this.config.debug && console.warn("[SDK] Rejected 3DS message from unauthorized origin:", p.origin);
429
+ return;
430
+ }
431
+ const l = p.data, f = l.type === "THREE_DS_COMPLETE" || l.type === "3ds-complete", g = l.status === "success", x = l.status === "failed" || l.status === "failure";
432
+ if (f && g) {
433
+ i.remove(), window.removeEventListener("message", m), s(!0);
434
+ return;
435
+ }
436
+ if (g && !f) {
437
+ i.remove(), window.removeEventListener("message", m), s(!0);
438
+ return;
439
+ }
440
+ if (f && x || l.type === "3ds-failed" || x) {
441
+ i.remove(), window.removeEventListener("message", m), s(!1);
442
+ return;
443
+ }
444
+ };
445
+ window.addEventListener("message", m);
446
+ });
447
+ }
448
+ /**
449
+ * Close 3DS modal (called from external events like WebSocket)
450
+ * @param sessionId - Optional session ID to validate before closing
451
+ */
452
+ static close(e) {
453
+ if (!d.activeModal) {
454
+ console.log("[SDK] No active modal to close");
455
+ return;
456
+ }
457
+ if (e && d.activeModal.sessionId !== e) {
458
+ console.warn(
459
+ `[SDK] Session ID mismatch: webhook for ${e}, but modal is for ${d.activeModal.sessionId}. Ignoring close request.`
460
+ );
461
+ return;
462
+ }
463
+ console.log("[SDK] Closing modal for session:", e || d.activeModal.sessionId), d.activeModal.overlay.remove(), d.activeModal = null;
464
+ }
465
+ /**
466
+ * Check if a modal is currently open
467
+ */
468
+ static isModalOpen() {
469
+ return d.activeModal !== null;
470
+ }
471
+ /**
472
+ * Get current session ID
473
+ */
474
+ static getCurrentSessionId() {
475
+ return d.activeModal?.sessionId || null;
476
+ }
477
+ /**
478
+ * Check if origin is allowed for 3DS messages
479
+ */
480
+ isAllowedOrigin(e) {
481
+ return !!(F.includes(e) || (this.config.environment === "sandbox" || this.config.environment === "development") && (e.includes("localhost") || e.includes("127.0.0.1")));
482
+ }
483
+ };
484
+ d.activeModal = null;
485
+ let S = d;
486
+ class C {
487
+ /**
488
+ * Create popup overlay with iframe
489
+ */
490
+ static createOverlay(e, n) {
491
+ const o = document.createElement("div");
492
+ o.id = y.OVERLAY, o.style.cssText = G();
493
+ const s = document.createElement("div");
494
+ s.style.cssText = z();
495
+ const i = document.createElement("button");
496
+ i.innerHTML = "×", i.style.cssText = Y(), i.onclick = n;
497
+ const r = document.createElement("iframe");
498
+ 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) => {
499
+ a.target === o && n();
500
+ }), { overlay: o, container: s, iframe: r };
501
+ }
502
+ /**
503
+ * Remove overlay from DOM
504
+ */
505
+ static removeOverlay() {
506
+ const e = document.getElementById(y.OVERLAY);
507
+ e && e.remove();
508
+ }
509
+ }
510
+ const ue = ["en", "de", "es", "fr", "it", "nl", "pl", "pt"];
511
+ function he() {
512
+ if (typeof window > "u")
513
+ return "en";
514
+ try {
515
+ const e = (navigator.language || navigator.userLanguage || "").split("-")[0].toLowerCase();
516
+ if (ue.includes(e))
517
+ return e;
518
+ } catch {
519
+ }
520
+ return "en";
521
+ }
522
+ function A(t) {
523
+ 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";
524
+ }
525
+ function P(t) {
526
+ switch (A(t)) {
527
+ case "production":
528
+ return I.PRODUCTION;
529
+ case "preprod":
530
+ return I.PREPROD;
531
+ case "development":
532
+ return I.DEVELOPMENT;
533
+ case "sandbox":
534
+ default:
535
+ return I.LOCAL;
536
+ }
537
+ }
538
+ class me {
539
+ constructor(e) {
540
+ if (this.iframe = null, this.messageListener = null, this.containerElement = null, this.loaderManager = null, this.config = e, this.iframeUrl = e.iframeUrl || P(e.publicKey || ""), this.environment = A(e.publicKey || ""), this.usePopup = !e.container, e.container)
541
+ if (typeof e.container == "string") {
542
+ if (this.containerElement = document.querySelector(e.container), !this.containerElement)
543
+ throw new Error(`Container not found: ${e.container}`);
544
+ } else
545
+ this.containerElement = e.container;
546
+ this.modalManager = new S({
547
+ environment: this.environment,
548
+ debug: this.config.debug
549
+ });
550
+ }
551
+ /**
552
+ * Initialize and open the payment iframe
553
+ */
554
+ init() {
555
+ this.iframe || (this.createIframe(), this.addMessageListener());
556
+ }
557
+ /**
558
+ * Create and append the iframe to the document
559
+ */
560
+ createIframe() {
561
+ const e = new URL(this.iframeUrl);
562
+ 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);
563
+ const n = e.toString();
564
+ if (this.usePopup) {
565
+ const { overlay: o, container: s, iframe: i } = C.createOverlay(
566
+ n,
567
+ () => this.close()
568
+ );
569
+ this.iframe = i, document.body.appendChild(o), this.loaderManager = new M(s, {
570
+ fillParent: this.config.config?.style?.fillParent
571
+ }), this.loaderManager.show(this.iframe);
572
+ } else {
573
+ if (!this.containerElement)
574
+ throw new Error("Container element is required for inline mode");
575
+ if (this.containerElement.innerHTML = "", this.containerElement instanceof HTMLElement) {
576
+ const o = this.containerElement.getAttribute("style") || "";
577
+ 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");
578
+ }
579
+ this.iframe = document.createElement("iframe"), this.iframe.src = n, this.iframe.style.cssText = V(
580
+ this.config.config?.style?.fillParent || !1
581
+ ), this.iframe.setAttribute("allow", "payment"), this.containerElement.appendChild(this.iframe), this.loaderManager = new M(this.containerElement, {
582
+ fillParent: this.config.config?.style?.fillParent
583
+ }), this.loaderManager.show(this.iframe);
584
+ }
585
+ }
586
+ /**
587
+ * Add message listener for communication with iframe
588
+ */
589
+ addMessageListener() {
590
+ this.messageListener = (e) => {
591
+ const n = new URL(this.iframeUrl).origin;
592
+ let s = e.origin === n;
593
+ 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) {
594
+ this.config.debug && console.warn("[SDK] Rejected message from unauthorized origin:", e.origin);
595
+ return;
596
+ }
597
+ const i = e.data;
598
+ if (!(!i || !i.type))
599
+ switch (i.type) {
600
+ case "iframe-ready":
601
+ this.loaderManager && this.loaderManager.hide(this.iframe || void 0), this.sendConfigToIframe();
602
+ break;
603
+ case "content-height":
604
+ if (i.height && this.iframe) {
605
+ const r = Math.max(i.height, c.MIN_HEIGHT);
606
+ this.iframe.style.height = `${r}px`, this.containerElement && (this.containerElement.style.minHeight = `${r}px`);
607
+ }
608
+ break;
609
+ case "close":
610
+ this.close();
611
+ break;
612
+ case "success":
613
+ this.config.onSuccess && this.config.onSuccess(i.data);
614
+ break;
615
+ case "error":
616
+ this.config.onError && this.config.onError(i.data);
617
+ break;
618
+ case "3ds-required":
619
+ if (this.config.debug && (console.log("[SDK] Received 3DS request:", i.threeDsSessionUrl), console.log("[SDK] Session ID:", i.sessionId)), i.threeDsSessionUrl) {
620
+ const r = i.sessionId, a = i.paymentId || this.config.config?.paymentId || "";
621
+ 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) => {
622
+ this.config.debug && console.log("[SDK] 3DS modal closed, result:", u);
623
+ });
624
+ } else
625
+ this.config.debug && console.error("[SDK] 3DS required but no threeDsSessionUrl provided");
626
+ break;
627
+ case "3ds-success":
628
+ this.config.debug && (console.log("[SDK] 3DS completed, closing modal..."), console.log("[SDK] Session ID from webhook:", i.sessionId)), S.close(i.sessionId);
629
+ break;
630
+ case "3ds-failed":
631
+ this.config.debug && (console.log("[SDK] 3DS failed, closing modal..."), console.log("[SDK] Session ID from webhook:", i.sessionId)), S.close(i.sessionId);
632
+ break;
633
+ default:
634
+ this.config.debug && console.log("SDK: Received message:", i);
635
+ }
636
+ }, window.addEventListener("message", this.messageListener);
637
+ }
638
+ /**
639
+ * Send configuration to the iframe
640
+ */
641
+ sendConfigToIframe() {
642
+ if (!this.iframe || !this.iframe.contentWindow) {
643
+ this.iframe && (this.iframe.onload = () => {
644
+ this.sendConfigToIframe();
645
+ });
646
+ return;
647
+ }
648
+ const e = {
649
+ type: "sdkData",
650
+ config: {
651
+ ...this.config.config || {},
652
+ paymentId: this.config.config?.paymentId
653
+ },
654
+ data: {
655
+ publicKey: this.config.publicKey
656
+ }
657
+ }, n = this.getTargetOrigin();
658
+ this.iframe.contentWindow.postMessage(e, n);
659
+ }
660
+ /**
661
+ * Close the iframe and cleanup
662
+ */
663
+ close() {
664
+ 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;
665
+ }
666
+ /**
667
+ * Handle success state: when showDefaultSuccessUI is true, iframe shows success UI
668
+ * and we keep it mounted; when false, we unmount so the parent can render their own.
669
+ */
670
+ switchToSuccessState(e) {
671
+ 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) {
672
+ C.removeOverlay(), this.iframe = null;
673
+ return;
674
+ }
675
+ const n = this.config.config?.showDefaultSuccessUI ?? !0;
676
+ !n && this.containerElement && (this.containerElement.innerHTML = ""), n || (this.iframe = null);
677
+ }
678
+ /**
679
+ * Get target origin for postMessage based on environment
680
+ * In production/pre-prod: use exact origin for security
681
+ * In dev/sandbox: use wildcard for development flexibility
682
+ */
683
+ getTargetOrigin() {
684
+ return this.environment === "production" || this.environment === "preprod" ? new URL(this.iframeUrl).origin : "*";
685
+ }
686
+ /**
687
+ * Public method to close the iframe
688
+ */
689
+ destroy() {
690
+ this.close();
691
+ }
692
+ }
693
+ class fe {
694
+ constructor(e, n) {
695
+ this.mounted = !1;
696
+ let o;
697
+ if (typeof n.container == "string") {
698
+ if (o = document.querySelector(n.container), !o)
699
+ throw new Error(`Container not found: ${n.container}`);
700
+ } else
701
+ o = n.container;
702
+ this.container = o, this.sdk = new me({
703
+ publicKey: e.publicKey,
704
+ container: this.container,
705
+ locale: e.locale ?? he(),
706
+ config: {
707
+ paymentId: n.paymentId,
708
+ ...n.style && { style: n.style },
709
+ ...n.buttonText && { buttonText: n.buttonText },
710
+ ...n.placeholders && { placeholders: n.placeholders },
711
+ ...n.showDefaultSuccessUI !== void 0 && {
712
+ showDefaultSuccessUI: n.showDefaultSuccessUI
713
+ }
714
+ },
715
+ onSuccess: (s) => {
716
+ n.onComplete && n.onComplete({
717
+ status: b.SUCCESS,
718
+ paymentId: n.paymentId
719
+ }), this.sdk.switchToSuccessState(s);
720
+ },
721
+ onError: (s) => {
722
+ n.onError ? n.onError(s) : n.onComplete && n.onComplete({
723
+ status: b.FAILED,
724
+ paymentId: n.paymentId,
725
+ error: s
726
+ });
727
+ },
728
+ onClose: () => {
729
+ n.onClose && n.onClose();
730
+ }
731
+ });
732
+ }
733
+ /**
734
+ * Mount the CardElement to the DOM
735
+ * This will create and display the iframe
736
+ */
737
+ mount() {
738
+ if (this.mounted)
739
+ throw new Error("CardElement is already mounted");
740
+ this.sdk.init(), this.mounted = !0;
741
+ }
742
+ /**
743
+ * Destroy the CardElement and cleanup
744
+ */
745
+ destroy() {
746
+ this.mounted && (this.sdk.destroy(), this.mounted = !1);
747
+ }
748
+ }
749
+ class H {
750
+ /**
751
+ * Initialize the InflowPay Payment SDK
752
+ *
753
+ * @param config - SDK configuration
754
+ *
755
+ * @example
756
+ * ```typescript
757
+ * const sdk = new PaymentSDK({
758
+ * apiKey: 'inflow_pub_local_xxx'
759
+ * });
760
+ * ```
761
+ */
762
+ constructor(e) {
763
+ if (!e.publicKey || typeof e.publicKey != "string")
764
+ throw new Error("API key is required");
765
+ this.config = e, this.timeout = 3e4, this.iframeUrl = P(e.publicKey);
766
+ const n = A(e.publicKey);
767
+ this.debug = n === "sandbox" || n === "development";
768
+ }
769
+ /**
770
+ * Create a CardElement for iframe-based payment UI
771
+ *
772
+ * @param options - CardElement configuration
773
+ * @returns CardElement instance
774
+ *
775
+ * @example
776
+ * ```typescript
777
+ * const cardElement = sdk.createCardElement({
778
+ * container: '#card-container',
779
+ * paymentId: 'pay_123',
780
+ * onComplete: (result) => {
781
+ * if (result.status === 'CHECKOUT_SUCCESS') {
782
+ * window.location.href = '/success';
783
+ * }
784
+ * }
785
+ * });
786
+ *
787
+ * cardElement.mount();
788
+ * ```
789
+ */
790
+ createCardElement(e) {
791
+ return new fe({
792
+ publicKey: this.config.publicKey,
793
+ iframeUrl: this.iframeUrl,
794
+ timeout: this.timeout,
795
+ debug: this.debug,
796
+ locale: this.config.locale
797
+ }, e);
798
+ }
799
+ /**
800
+ * Get the iframe URL being used
801
+ */
802
+ getIframeUrl() {
803
+ return this.iframeUrl;
804
+ }
805
+ /**
806
+ * Get the API key
807
+ */
808
+ getApiKey() {
809
+ return this.config.publicKey;
810
+ }
811
+ }
812
+ export {
813
+ fe as C,
814
+ ye as I,
815
+ H as P,
816
+ U as a,
817
+ b,
818
+ we as c,
819
+ Ee as u
820
+ };
821
+ //# sourceMappingURL=payment-sdk-oRqgQSx5.mjs.map