@paynext/sdk 0.0.173 → 0.0.174

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/dist/index.d.ts CHANGED
@@ -352,37 +352,13 @@ declare enum PaymentStatus {
352
352
 
353
353
  export declare class PayNextCheckout {
354
354
  private cdnInstance;
355
- private iframeInstance;
356
355
  private initPromise;
357
- private mode;
358
356
  constructor();
359
357
  private initialize;
360
358
  private waitForReady;
361
- mount(containerId: string, config: PayNextConfigExtended): Promise<void>;
362
- unmount(): Promise<void>;
363
- updateConfig(config: Partial<PayNextConfigExtended>): Promise<void>;
364
- static preload(envType: 'develop' | 'staging' | 'sandbox' | 'production', options?: {
365
- iframeMode?: boolean;
366
- }): Promise<void>;
367
- }
368
-
369
- export declare class PayNextCheckoutIframe {
370
- private iframe;
371
- private container;
372
- private config;
373
- private messageHandlers;
374
- private pendingRequests;
375
- private isReady;
376
- private allowedOrigin;
377
- constructor();
378
- private generateRequestId;
379
- private sendMessage;
380
- private handleMessage;
381
- private createIframe;
382
- private waitForReady;
383
359
  mount(containerId: string, config: PayNextConfig): Promise<void>;
384
360
  unmount(): Promise<void>;
385
- updateConfig(config: Partial<PayNextConfig>): Promise<void>;
361
+ updateConfig(config: any): Promise<void>;
386
362
  static preload(envType: 'develop' | 'staging' | 'sandbox' | 'production'): Promise<void>;
387
363
  }
388
364
 
@@ -403,23 +379,10 @@ export declare interface PayNextConfig {
403
379
  _themeExplicit?: boolean;
404
380
  }
405
381
 
406
- export declare interface PayNextConfigExtended extends PayNextConfig {
407
- /**
408
- * Enable PCI-compliant iframe mode
409
- * @default false
410
- * @description When true, checkout will be rendered in isolated iframe for better PCI compliance
411
- */
412
- iframeMode?: boolean;
413
- }
414
-
415
382
  export declare const PayNextSDK: {
416
383
  preload: typeof PayNextCheckout.preload;
417
384
  };
418
385
 
419
- export declare const PayNextSDKIframe: {
420
- preload: typeof PayNextCheckoutIframe.preload;
421
- };
422
-
423
386
  export declare interface StylesConfig {
424
387
  Input?: InputStyles;
425
388
  SubmitButton?: ISubmitButtonStyles;
package/dist/index.es.js CHANGED
@@ -1,379 +1,45 @@
1
- var w = Object.defineProperty;
2
- var x = (a, t, e) => t in a ? w(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
3
- var r = (a, t, e) => x(a, typeof t != "symbol" ? t + "" : t, e);
4
- const h = "https://cdn-sdk-dev.paynext.com/checkout.html", p = "https://cdn-sdk.paynext.com/checkout.html", C = {
5
- develop: "https://cdn-sdk-dev.paynext.com",
6
- production: "https://cdn-sdk.paynext.com"
7
- };
8
- function P(a) {
9
- return `<!DOCTYPE html>
10
- <html lang="en">
11
- <head>
12
- <meta charset="UTF-8">
13
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
14
- <title>PayNext Checkout</title>
15
- <style>
16
- * { margin: 0; padding: 0; box-sizing: border-box; }
17
- html, body { width: 100%; height: 100%; overflow: hidden; }
18
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
19
- #checkout-container { width: 100%; min-height: 100%; }
20
- .loading { display: flex; align-items: center; justify-content: center; min-height: 400px; color: #666; font-size: 14px; }
21
- .loading::after { content: '...'; animation: dots 1.5s steps(4, end) infinite; }
22
- @keyframes dots { 0%, 20% { content: '.'; } 40% { content: '..'; } 60%, 100% { content: '...'; } }
23
- .error { color: #e53e3e; padding: 20px; text-align: center; }
24
- </style>
25
- </head>
26
- <body>
27
- <div id="checkout-container"><div class="loading">Loading checkout</div></div>
28
- <script type="module">
29
- const MessageType = {
30
- MOUNT: 'paynext:mount', UNMOUNT: 'paynext:unmount', UPDATE_CONFIG: 'paynext:updateConfig',
31
- READY: 'paynext:ready', LOADED: 'paynext:loaded', ATTEMPT: 'paynext:attempt',
32
- COMPLETE: 'paynext:complete', FAIL: 'paynext:fail', ERROR: 'paynext:error', RESIZE: 'paynext:resize'
33
- }
34
- let checkout = null, parentOrigin = null, config = null
35
-
36
- function sendToParent(type, payload, requestId) {
37
- if (!parentOrigin) return
38
- window.parent.postMessage({ type, payload, requestId }, parentOrigin)
39
- }
40
-
41
- function showError(message) {
42
- document.getElementById('checkout-container').innerHTML =
43
- '<div class="error"><strong>Error:</strong> ' + message + '</div>'
44
- }
45
-
46
- window.addEventListener('message', async (event) => {
47
- const data = event.data
48
- if (!parentOrigin) parentOrigin = event.origin
49
- if (event.origin !== parentOrigin || !data.type?.startsWith('paynext:')) return
50
-
51
- try {
52
- switch (data.type) {
53
- case MessageType.MOUNT:
54
- if (data.payload?.config) {
55
- config = data.payload.config
56
-
57
- try {
58
- // Load SDK from CDN
59
- // CDN version exports to window.PayNextSDK
60
- if (!window.PayNextSDK) {
61
- // Load SDK script if not already loaded
62
- await new Promise((resolve, reject) => {
63
- const script = document.createElement('script')
64
- script.src = '${a}'
65
- script.onload = resolve
66
- script.onerror = reject
67
- document.head.appendChild(script)
68
- })
69
- }
70
-
71
- const { PayNextCheckout } = window.PayNextSDK || {}
72
-
73
- if (!PayNextCheckout) {
74
- throw new Error('PayNextCheckout not found in window.PayNextSDK')
75
- }
76
-
77
- checkout = new PayNextCheckout()
78
- await checkout.mount('checkout-container', {
79
- ...config,
80
- onCheckoutLoaded: (result) => {
81
- sendToParent(MessageType.LOADED, result, data.requestId)
82
- notifyResize()
83
- },
84
- onCheckoutAttempt: (result) => sendToParent(MessageType.ATTEMPT, result),
85
- onCheckoutComplete: (result) => sendToParent(MessageType.COMPLETE, result),
86
- onCheckoutFail: (error) => sendToParent(MessageType.FAIL, error)
87
- })
88
- sendToParent(MessageType.READY, { success: true }, data.requestId)
89
- setupResizeObserver()
90
- } catch (importError) {
91
- console.error('[Iframe] Failed to load SDK:', importError)
92
- showError('Failed to load PayNext SDK: ' + importError.message)
93
- sendToParent(MessageType.ERROR, {
94
- message: 'SDK import failed: ' + importError.message,
95
- stack: importError.stack
96
- }, data.requestId)
97
- }
98
- }
99
- break
100
-
101
- case MessageType.UNMOUNT:
102
- if (checkout) {
103
- await checkout.unmount()
104
- checkout = null
105
- }
106
- sendToParent(MessageType.READY, { success: true }, data.requestId)
107
- break
108
-
109
- case MessageType.UPDATE_CONFIG:
110
- if (checkout && data.payload?.config) {
111
- await checkout.updateConfig(data.payload.config)
112
- sendToParent(MessageType.READY, { success: true }, data.requestId)
113
- }
114
- break
115
- }
116
- } catch (error) {
117
- console.error('[Iframe] Error:', error)
118
- sendToParent(MessageType.ERROR, {
119
- message: error.message,
120
- stack: error.stack
121
- }, data.requestId)
122
- }
123
- })
124
-
125
- function setupResizeObserver() {
126
- new ResizeObserver(entries => {
127
- for (const entry of entries) {
128
- sendToParent(MessageType.RESIZE, { height: entry.contentRect.height })
129
- }
130
- }).observe(document.body)
131
- }
132
-
133
- function notifyResize() {
134
- sendToParent(MessageType.RESIZE, { height: document.body.scrollHeight })
135
- }
136
-
137
- window.addEventListener('load', () => {
138
- console.log('[Iframe] Iframe loaded, sending ready message')
139
- setTimeout(() => {
140
- window.parent.postMessage(
141
- { type: MessageType.READY, payload: { success: true } },
142
- '*'
143
- )
144
- }, 100)
145
- })
146
-
147
- window.addEventListener('error', (event) => {
148
- console.error('[Iframe] Global error:', event.error)
149
- sendToParent(MessageType.ERROR, {
150
- message: event.error?.message || 'Unknown error',
151
- stack: event.error?.stack
152
- })
153
- })
154
-
155
- console.log('[Iframe] PayNext Checkout iframe initialized, SDK URL: ${a}')
156
- <\/script>
157
- </body>
158
- </html>`;
159
- }
160
- class f {
161
- constructor() {
162
- r(this, "iframe", null);
163
- r(this, "container", null);
164
- r(this, "config", null);
165
- r(this, "messageHandlers", /* @__PURE__ */ new Map());
166
- r(this, "pendingRequests", /* @__PURE__ */ new Map());
167
- r(this, "isReady", !1);
168
- r(this, "allowedOrigin", "");
169
- this.handleMessage = this.handleMessage.bind(this);
170
- }
171
- // generate unique request ID
172
- generateRequestId() {
173
- return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
174
- }
175
- // send message to iframe
176
- sendMessage(t, e) {
177
- return new Promise((o, n) => {
178
- if (!this.iframe || !this.iframe.contentWindow) {
179
- n(new Error("Iframe not initialized"));
180
- return;
181
- }
182
- const i = this.generateRequestId(), s = { type: t, payload: e, requestId: i };
183
- this.pendingRequests.set(i, { resolve: o, reject: n }), setTimeout(() => {
184
- this.pendingRequests.has(i) && (this.pendingRequests.delete(i), n(new Error(`Request timeout: ${t}`)));
185
- }, 3e4), this.iframe.contentWindow.postMessage(s, this.allowedOrigin);
186
- });
187
- }
188
- // handle messages from iframe
189
- handleMessage(t) {
190
- if (t.origin !== this.allowedOrigin) {
191
- console.warn("[PayNext Iframe] Message from unauthorized origin:", t.origin);
192
- return;
193
- }
194
- const e = t.data;
195
- if (!(!e.type || !e.type.startsWith("paynext:"))) {
196
- if (e.requestId && this.pendingRequests.has(e.requestId)) {
197
- const { resolve: o } = this.pendingRequests.get(e.requestId);
198
- this.pendingRequests.delete(e.requestId), o(e.payload);
199
- return;
200
- }
201
- switch (e.type) {
202
- case "paynext:ready":
203
- this.isReady = !0, console.log("[PayNext Iframe] SDK ready");
204
- break;
205
- case "paynext:loaded":
206
- this.config?.onCheckoutLoaded && this.config.onCheckoutLoaded(e.payload);
207
- break;
208
- case "paynext:attempt":
209
- this.config?.onCheckoutAttempt && this.config.onCheckoutAttempt(e.payload);
210
- break;
211
- case "paynext:complete":
212
- this.config?.onCheckoutComplete && this.config.onCheckoutComplete(e.payload);
213
- break;
214
- case "paynext:fail":
215
- this.config?.onCheckoutFail && this.config.onCheckoutFail(e.payload);
216
- break;
217
- case "paynext:error":
218
- console.error("[PayNext Iframe] Error:", e.payload);
219
- break;
220
- case "paynext:resize":
221
- this.iframe && e.payload?.height && (this.iframe.style.height = `${e.payload.height}px`);
222
- break;
223
- default:
224
- console.warn("[PayNext Iframe] Unknown message type:", e.type);
225
- }
226
- }
227
- }
228
- // create and configure iframe
229
- createIframe(t, e = !1) {
230
- const o = t.environment?.toLowerCase()?.includes("develop") || t.environment?.toLowerCase()?.includes("staging") ? "develop" : "production";
231
- this.allowedOrigin = e ? window.location.origin : C[o];
232
- const n = document.createElement("iframe"), i = o === "develop" ? h : p, s = o === "develop" ? "https://cdn-sdk-dev.paynext.com/index.cdn.js" : "https://cdn-sdk.paynext.com/index.cdn.js";
233
- return e ? (console.log("[PayNext Iframe] Using inline iframe mode (embedded HTML)"), console.log("[PayNext Iframe] SDK will load from:", s), n.srcdoc = P(s)) : (console.log("[PayNext Iframe] Using CDN iframe mode"), console.log("[PayNext Iframe] Loading iframe from:", i), n.src = i), n.style.border = "none", n.style.width = "100%", n.style.minHeight = "400px", n.style.display = "block", n.allow = "payment *", n.sandbox.add(
234
- "allow-scripts",
235
- // required for SDK execution
236
- "allow-same-origin",
237
- // required for postMessage
238
- "allow-forms",
239
- // required for form submission
240
- "allow-popups",
241
- // required for 3DS redirects
242
- "allow-popups-to-escape-sandbox",
243
- // required for payment popups
244
- "allow-top-navigation-by-user-activation"
245
- // required for redirects
246
- ), n.setAttribute("referrerpolicy", "strict-origin-when-cross-origin"), n.setAttribute("importance", "high"), n;
247
- }
248
- // wait for iframe to be ready
249
- async waitForReady(t = 1e4) {
250
- const e = Date.now();
251
- for (; !this.isReady; ) {
252
- if (Date.now() - e > t)
253
- throw new Error("Iframe initialization timeout");
254
- await new Promise((o) => setTimeout(o, 100));
255
- }
256
- }
257
- // mount checkout in iframe
258
- async mount(t, e) {
259
- try {
260
- const o = document.getElementById(t);
261
- if (!o)
262
- throw new Error(`Container element "${t}" not found`);
263
- this.container = o, this.config = e, this.iframe && await this.unmount();
264
- const n = e.environment?.toLowerCase()?.includes("develop") || e.environment?.toLowerCase()?.includes("staging") ? "develop" : "production", i = n === "develop" ? h : p, s = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname.startsWith("192.168.") || window.location.hostname.endsWith(".local");
265
- let l = s;
266
- if (!s && n === "develop")
267
- try {
268
- const m = new AbortController(), u = setTimeout(() => m.abort(), 2e3);
269
- await fetch(i, {
270
- method: "HEAD",
271
- signal: m.signal,
272
- cache: "no-cache"
273
- }), clearTimeout(u), l = !1, console.log("[PayNext Iframe] CDN is available, using remote iframe");
274
- } catch {
275
- l = !0, console.warn("[PayNext Iframe] CDN not available, using inline fallback mode");
276
- }
277
- l && (console.log("[PayNext Iframe] Using inline fallback mode"), console.log("[PayNext Iframe] Reason:", s ? "localhost detected" : "CDN not available")), this.iframe = this.createIframe(e, l), window.addEventListener("message", this.handleMessage), o.innerHTML = "", o.appendChild(this.iframe), await new Promise((m, u) => {
278
- const y = setTimeout(() => {
279
- u(new Error("Iframe load timeout"));
280
- }, 1e4);
281
- this.iframe.onload = () => {
282
- clearTimeout(y), m();
283
- }, this.iframe.onerror = () => {
284
- clearTimeout(y), u(new Error("Iframe failed to load"));
285
- };
286
- }), await this.waitForReady(), await this.sendMessage("paynext:mount", {
287
- config: {
288
- ...e,
289
- // remove callbacks from config sent to iframe
290
- onCheckoutLoaded: void 0,
291
- onCheckoutAttempt: void 0,
292
- onCheckoutComplete: void 0,
293
- onCheckoutFail: void 0
294
- }
295
- }), console.log("[PayNext Iframe] Checkout mounted successfully");
296
- } catch (o) {
297
- throw console.error("[PayNext Iframe] Mount failed:", o), await this.unmount(), o;
298
- }
299
- }
300
- // unmount checkout
301
- async unmount() {
302
- try {
303
- this.iframe && (this.isReady && await this.sendMessage(
304
- "paynext:unmount"
305
- /* UNMOUNT */
306
- ).catch(() => {
307
- }), this.iframe.parentNode && this.iframe.parentNode.removeChild(this.iframe), this.iframe = null), window.removeEventListener("message", this.handleMessage), this.container && (this.container.innerHTML = "", this.container = null), this.isReady = !1, this.config = null, this.pendingRequests.clear(), this.messageHandlers.clear(), console.log("[PayNext Iframe] Checkout unmounted");
308
- } catch (t) {
309
- console.error("[PayNext Iframe] Unmount failed:", t);
310
- }
311
- }
312
- // update configuration
313
- async updateConfig(t) {
314
- if (!this.isReady)
315
- throw new Error("Iframe not ready");
316
- this.config = { ...this.config, ...t }, await this.sendMessage("paynext:updateConfig", {
317
- config: {
318
- ...t,
319
- onCheckoutLoaded: void 0,
320
- onCheckoutAttempt: void 0,
321
- onCheckoutComplete: void 0,
322
- onCheckoutFail: void 0
323
- }
324
- });
325
- }
326
- // preload iframe (optional optimization)
327
- static async preload(t) {
328
- const o = (t?.toLowerCase()?.includes("develop") || t?.toLowerCase()?.includes("staging") ? "develop" : "production") === "develop" ? h : p, n = document.createElement("link");
329
- n.rel = "preconnect", n.href = new URL(o).origin, document.head.appendChild(n);
330
- const i = document.createElement("link");
331
- i.rel = "dns-prefetch", i.href = new URL(o).origin, document.head.appendChild(i);
332
- }
333
- }
334
- const R = {
335
- preload: f.preload
336
- }, k = "https://cdn-sdk-dev.paynext.com/index.cdn.js", I = "https://cdn-sdk.paynext.com/index.cdn.js";
337
- let d = null, c = null;
338
- async function g(a) {
339
- if (c)
340
- return c;
341
- if (d)
342
- return d;
343
- const t = a?.toLowerCase()?.includes("develop") || a?.toLowerCase()?.includes("staging") ? "develop" : "production";
344
- return d = new Promise((e, o) => {
1
+ var l = Object.defineProperty;
2
+ var u = (t, n, e) => n in t ? l(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e;
3
+ var d = (t, n, e) => u(t, typeof n != "symbol" ? n + "" : n, e);
4
+ const w = "https://cdn-sdk-dev.paynext.com/index.cdn.js", P = "https://cdn-sdk.paynext.com/index.cdn.js";
5
+ let i = null, a = null;
6
+ async function c(t) {
7
+ if (a)
8
+ return a;
9
+ if (i)
10
+ return i;
11
+ const n = t?.toLowerCase()?.includes("develop") || t?.toLowerCase()?.includes("staging") ? "develop" : "production";
12
+ return i = new Promise((e, s) => {
345
13
  if (typeof window > "u") {
346
- o(new Error("PayNext SDK can only be loaded in browser environment"));
14
+ s(new Error("PayNext SDK can only be loaded in browser environment"));
347
15
  return;
348
16
  }
349
17
  if (window.PayNextSDK) {
350
- console.log("[PayNext CDN] SDK already loaded from cache"), c = window.PayNextSDK, e(c);
18
+ console.log("[PayNext CDN] SDK already loaded from cache"), a = window.PayNextSDK, e(a);
351
19
  return;
352
20
  }
353
- const n = document.createElement("script");
354
- n.src = t === "develop" ? k : I, n.crossOrigin = "*", n.async = !0, n.onload = () => {
355
- const i = window.PayNextSDK;
356
- if (!i) {
357
- console.error("[PayNext CDN] PayNextSDK not found in window after load"), d = null, document.head.removeChild(n), o(new Error("PayNextSDK not found in global scope after loading"));
21
+ const o = document.createElement("script");
22
+ o.src = n === "develop" ? w : P, o.crossOrigin = "*", o.async = !0, o.onload = () => {
23
+ const r = window.PayNextSDK;
24
+ if (!r) {
25
+ console.error("[PayNext CDN] PayNextSDK not found in window after load"), i = null, document.head.removeChild(o), s(new Error("PayNextSDK not found in global scope after loading"));
358
26
  return;
359
27
  }
360
- c = i, e(i);
361
- }, n.onerror = (i) => {
362
- console.error("[PayNext CDN] Failed to load script:", i), d = null, document.head.removeChild(n), o(new Error("Failed to load PayNext SDK script from CDN"));
363
- }, document.head.appendChild(n);
364
- }), d;
28
+ a = r, e(r);
29
+ }, o.onerror = (r) => {
30
+ console.error("[PayNext CDN] Failed to load script:", r), i = null, document.head.removeChild(o), s(new Error("Failed to load PayNext SDK script from CDN"));
31
+ }, document.head.appendChild(o);
32
+ }), i;
365
33
  }
366
- class E {
34
+ class h {
367
35
  constructor() {
368
- r(this, "cdnInstance", null);
369
- r(this, "iframeInstance", null);
370
- r(this, "initPromise", null);
371
- r(this, "mode", "direct");
36
+ d(this, "cdnInstance", null);
37
+ d(this, "initPromise", null);
372
38
  }
373
39
  // initialize
374
- async initialize(t) {
40
+ async initialize(n) {
375
41
  try {
376
- if (this.initPromise = await g(t), !this.initPromise.PayNextCheckout)
42
+ if (this.initPromise = await c(n), !this.initPromise.PayNextCheckout)
377
43
  throw new Error("PayNextCheckout not found in CDN module");
378
44
  this.cdnInstance = new this.initPromise.PayNextCheckout();
379
45
  } catch (e) {
@@ -387,37 +53,31 @@ class E {
387
53
  if (!this.cdnInstance)
388
54
  throw new Error("SDK instance not created");
389
55
  }
390
- // mount with iframe mode support
391
- async mount(t, e) {
392
- return e.iframeMode === !0 ? (this.mode = "iframe", this.iframeInstance || (this.iframeInstance = new f()), this.iframeInstance.mount(t, e)) : (this.mode = "direct", await this.initialize(e.environment), this.waitForReady(), this.cdnInstance?.mount(t, e));
56
+ // mount
57
+ async mount(n, e) {
58
+ return await this.initialize(e.environment), this.waitForReady(), this.cdnInstance?.mount(n, e);
393
59
  }
394
- // unmount with mode detection
60
+ // unmount
395
61
  async unmount() {
396
- if (this.mode === "iframe" && this.iframeInstance)
397
- return this.iframeInstance.unmount();
398
62
  if (this.waitForReady(), this.cdnInstance?.unmount)
399
63
  return this.cdnInstance.unmount();
400
64
  }
401
- // update config with mode detection
402
- async updateConfig(t) {
403
- if (this.mode === "iframe" && this.iframeInstance)
404
- return this.iframeInstance.updateConfig(t);
65
+ // update config
66
+ async updateConfig(n) {
405
67
  if (this.waitForReady(), this.cdnInstance?.updateConfig)
406
- return this.cdnInstance.updateConfig(t);
68
+ return this.cdnInstance.updateConfig(n);
407
69
  }
408
70
  // preload (optional optimization)
409
- static async preload(t, e) {
410
- e?.iframeMode ? await f.preload(t) : await g(t);
71
+ static async preload(n) {
72
+ await c(n);
411
73
  }
412
74
  }
413
- const D = {
414
- preload: E.preload
75
+ const m = {
76
+ preload: h.preload
415
77
  };
416
- var N = /* @__PURE__ */ ((a) => (a.PAYPAL = "PAYPAL", a.APPLE_PAY = "APPLEPAY", a.GOOGLE_PAY = "GPAY", a.CARD = "CARD", a.VENMO = "VENMO", a))(N || {});
78
+ var y = /* @__PURE__ */ ((t) => (t.PAYPAL = "PAYPAL", t.APPLE_PAY = "APPLEPAY", t.GOOGLE_PAY = "GPAY", t.CARD = "CARD", t.VENMO = "VENMO", t))(y || {});
417
79
  export {
418
- E as PayNextCheckout,
419
- f as PayNextCheckoutIframe,
420
- D as PayNextSDK,
421
- R as PayNextSDKIframe,
422
- N as PaymentMethod
80
+ h as PayNextCheckout,
81
+ m as PayNextSDK,
82
+ y as PaymentMethod
423
83
  };
package/dist/index.umd.js CHANGED
@@ -1,150 +1 @@
1
- (function(i,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(i=typeof globalThis<"u"?globalThis:i||self,r(i["PayNext SDK"]={}))})(this,(function(i){"use strict";var D=Object.defineProperty;var R=(i,r,c)=>r in i?D(i,r,{enumerable:!0,configurable:!0,writable:!0,value:c}):i[r]=c;var d=(i,r,c)=>R(i,typeof r!="symbol"?r+"":r,c);const r="https://cdn-sdk-dev.paynext.com/checkout.html",c="https://cdn-sdk.paynext.com/checkout.html",C={develop:"https://cdn-sdk-dev.paynext.com",production:"https://cdn-sdk.paynext.com"};function k(s){return`<!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>PayNext Checkout</title>
7
- <style>
8
- * { margin: 0; padding: 0; box-sizing: border-box; }
9
- html, body { width: 100%; height: 100%; overflow: hidden; }
10
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
11
- #checkout-container { width: 100%; min-height: 100%; }
12
- .loading { display: flex; align-items: center; justify-content: center; min-height: 400px; color: #666; font-size: 14px; }
13
- .loading::after { content: '...'; animation: dots 1.5s steps(4, end) infinite; }
14
- @keyframes dots { 0%, 20% { content: '.'; } 40% { content: '..'; } 60%, 100% { content: '...'; } }
15
- .error { color: #e53e3e; padding: 20px; text-align: center; }
16
- </style>
17
- </head>
18
- <body>
19
- <div id="checkout-container"><div class="loading">Loading checkout</div></div>
20
- <script type="module">
21
- const MessageType = {
22
- MOUNT: 'paynext:mount', UNMOUNT: 'paynext:unmount', UPDATE_CONFIG: 'paynext:updateConfig',
23
- READY: 'paynext:ready', LOADED: 'paynext:loaded', ATTEMPT: 'paynext:attempt',
24
- COMPLETE: 'paynext:complete', FAIL: 'paynext:fail', ERROR: 'paynext:error', RESIZE: 'paynext:resize'
25
- }
26
- let checkout = null, parentOrigin = null, config = null
27
-
28
- function sendToParent(type, payload, requestId) {
29
- if (!parentOrigin) return
30
- window.parent.postMessage({ type, payload, requestId }, parentOrigin)
31
- }
32
-
33
- function showError(message) {
34
- document.getElementById('checkout-container').innerHTML =
35
- '<div class="error"><strong>Error:</strong> ' + message + '</div>'
36
- }
37
-
38
- window.addEventListener('message', async (event) => {
39
- const data = event.data
40
- if (!parentOrigin) parentOrigin = event.origin
41
- if (event.origin !== parentOrigin || !data.type?.startsWith('paynext:')) return
42
-
43
- try {
44
- switch (data.type) {
45
- case MessageType.MOUNT:
46
- if (data.payload?.config) {
47
- config = data.payload.config
48
-
49
- try {
50
- // Load SDK from CDN
51
- // CDN version exports to window.PayNextSDK
52
- if (!window.PayNextSDK) {
53
- // Load SDK script if not already loaded
54
- await new Promise((resolve, reject) => {
55
- const script = document.createElement('script')
56
- script.src = '${s}'
57
- script.onload = resolve
58
- script.onerror = reject
59
- document.head.appendChild(script)
60
- })
61
- }
62
-
63
- const { PayNextCheckout } = window.PayNextSDK || {}
64
-
65
- if (!PayNextCheckout) {
66
- throw new Error('PayNextCheckout not found in window.PayNextSDK')
67
- }
68
-
69
- checkout = new PayNextCheckout()
70
- await checkout.mount('checkout-container', {
71
- ...config,
72
- onCheckoutLoaded: (result) => {
73
- sendToParent(MessageType.LOADED, result, data.requestId)
74
- notifyResize()
75
- },
76
- onCheckoutAttempt: (result) => sendToParent(MessageType.ATTEMPT, result),
77
- onCheckoutComplete: (result) => sendToParent(MessageType.COMPLETE, result),
78
- onCheckoutFail: (error) => sendToParent(MessageType.FAIL, error)
79
- })
80
- sendToParent(MessageType.READY, { success: true }, data.requestId)
81
- setupResizeObserver()
82
- } catch (importError) {
83
- console.error('[Iframe] Failed to load SDK:', importError)
84
- showError('Failed to load PayNext SDK: ' + importError.message)
85
- sendToParent(MessageType.ERROR, {
86
- message: 'SDK import failed: ' + importError.message,
87
- stack: importError.stack
88
- }, data.requestId)
89
- }
90
- }
91
- break
92
-
93
- case MessageType.UNMOUNT:
94
- if (checkout) {
95
- await checkout.unmount()
96
- checkout = null
97
- }
98
- sendToParent(MessageType.READY, { success: true }, data.requestId)
99
- break
100
-
101
- case MessageType.UPDATE_CONFIG:
102
- if (checkout && data.payload?.config) {
103
- await checkout.updateConfig(data.payload.config)
104
- sendToParent(MessageType.READY, { success: true }, data.requestId)
105
- }
106
- break
107
- }
108
- } catch (error) {
109
- console.error('[Iframe] Error:', error)
110
- sendToParent(MessageType.ERROR, {
111
- message: error.message,
112
- stack: error.stack
113
- }, data.requestId)
114
- }
115
- })
116
-
117
- function setupResizeObserver() {
118
- new ResizeObserver(entries => {
119
- for (const entry of entries) {
120
- sendToParent(MessageType.RESIZE, { height: entry.contentRect.height })
121
- }
122
- }).observe(document.body)
123
- }
124
-
125
- function notifyResize() {
126
- sendToParent(MessageType.RESIZE, { height: document.body.scrollHeight })
127
- }
128
-
129
- window.addEventListener('load', () => {
130
- console.log('[Iframe] Iframe loaded, sending ready message')
131
- setTimeout(() => {
132
- window.parent.postMessage(
133
- { type: MessageType.READY, payload: { success: true } },
134
- '*'
135
- )
136
- }, 100)
137
- })
138
-
139
- window.addEventListener('error', (event) => {
140
- console.error('[Iframe] Global error:', event.error)
141
- sendToParent(MessageType.ERROR, {
142
- message: event.error?.message || 'Unknown error',
143
- stack: event.error?.stack
144
- })
145
- })
146
-
147
- console.log('[Iframe] PayNext Checkout iframe initialized, SDK URL: ${s}')
148
- <\/script>
149
- </body>
150
- </html>`}class h{constructor(){d(this,"iframe",null);d(this,"container",null);d(this,"config",null);d(this,"messageHandlers",new Map);d(this,"pendingRequests",new Map);d(this,"isReady",!1);d(this,"allowedOrigin","");this.handleMessage=this.handleMessage.bind(this)}generateRequestId(){return`${Date.now()}-${Math.random().toString(36).substr(2,9)}`}sendMessage(t,e){return new Promise((o,n)=>{if(!this.iframe||!this.iframe.contentWindow){n(new Error("Iframe not initialized"));return}const a=this.generateRequestId(),l={type:t,payload:e,requestId:a};this.pendingRequests.set(a,{resolve:o,reject:n}),setTimeout(()=>{this.pendingRequests.has(a)&&(this.pendingRequests.delete(a),n(new Error(`Request timeout: ${t}`)))},3e4),this.iframe.contentWindow.postMessage(l,this.allowedOrigin)})}handleMessage(t){if(t.origin!==this.allowedOrigin){console.warn("[PayNext Iframe] Message from unauthorized origin:",t.origin);return}const e=t.data;if(!(!e.type||!e.type.startsWith("paynext:"))){if(e.requestId&&this.pendingRequests.has(e.requestId)){const{resolve:o}=this.pendingRequests.get(e.requestId);this.pendingRequests.delete(e.requestId),o(e.payload);return}switch(e.type){case"paynext:ready":this.isReady=!0,console.log("[PayNext Iframe] SDK ready");break;case"paynext:loaded":this.config?.onCheckoutLoaded&&this.config.onCheckoutLoaded(e.payload);break;case"paynext:attempt":this.config?.onCheckoutAttempt&&this.config.onCheckoutAttempt(e.payload);break;case"paynext:complete":this.config?.onCheckoutComplete&&this.config.onCheckoutComplete(e.payload);break;case"paynext:fail":this.config?.onCheckoutFail&&this.config.onCheckoutFail(e.payload);break;case"paynext:error":console.error("[PayNext Iframe] Error:",e.payload);break;case"paynext:resize":this.iframe&&e.payload?.height&&(this.iframe.style.height=`${e.payload.height}px`);break;default:console.warn("[PayNext Iframe] Unknown message type:",e.type)}}}createIframe(t,e=!1){const o=t.environment?.toLowerCase()?.includes("develop")||t.environment?.toLowerCase()?.includes("staging")?"develop":"production";this.allowedOrigin=e?window.location.origin:C[o];const n=document.createElement("iframe"),a=o==="develop"?r:c,l=o==="develop"?"https://cdn-sdk-dev.paynext.com/index.cdn.js":"https://cdn-sdk.paynext.com/index.cdn.js";return e?(console.log("[PayNext Iframe] Using inline iframe mode (embedded HTML)"),console.log("[PayNext Iframe] SDK will load from:",l),n.srcdoc=k(l)):(console.log("[PayNext Iframe] Using CDN iframe mode"),console.log("[PayNext Iframe] Loading iframe from:",a),n.src=a),n.style.border="none",n.style.width="100%",n.style.minHeight="400px",n.style.display="block",n.allow="payment *",n.sandbox.add("allow-scripts","allow-same-origin","allow-forms","allow-popups","allow-popups-to-escape-sandbox","allow-top-navigation-by-user-activation"),n.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),n.setAttribute("importance","high"),n}async waitForReady(t=1e4){const e=Date.now();for(;!this.isReady;){if(Date.now()-e>t)throw new Error("Iframe initialization timeout");await new Promise(o=>setTimeout(o,100))}}async mount(t,e){try{const o=document.getElementById(t);if(!o)throw new Error(`Container element "${t}" not found`);this.container=o,this.config=e,this.iframe&&await this.unmount();const n=e.environment?.toLowerCase()?.includes("develop")||e.environment?.toLowerCase()?.includes("staging")?"develop":"production",a=n==="develop"?r:c,l=window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"||window.location.hostname.startsWith("192.168.")||window.location.hostname.endsWith(".local");let p=l;if(!l&&n==="develop")try{const f=new AbortController,y=setTimeout(()=>f.abort(),2e3);await fetch(a,{method:"HEAD",signal:f.signal,cache:"no-cache"}),clearTimeout(y),p=!1,console.log("[PayNext Iframe] CDN is available, using remote iframe")}catch{p=!0,console.warn("[PayNext Iframe] CDN not available, using inline fallback mode")}p&&(console.log("[PayNext Iframe] Using inline fallback mode"),console.log("[PayNext Iframe] Reason:",l?"localhost detected":"CDN not available")),this.iframe=this.createIframe(e,p),window.addEventListener("message",this.handleMessage),o.innerHTML="",o.appendChild(this.iframe),await new Promise((f,y)=>{const P=setTimeout(()=>{y(new Error("Iframe load timeout"))},1e4);this.iframe.onload=()=>{clearTimeout(P),f()},this.iframe.onerror=()=>{clearTimeout(P),y(new Error("Iframe failed to load"))}}),await this.waitForReady(),await this.sendMessage("paynext:mount",{config:{...e,onCheckoutLoaded:void 0,onCheckoutAttempt:void 0,onCheckoutComplete:void 0,onCheckoutFail:void 0}}),console.log("[PayNext Iframe] Checkout mounted successfully")}catch(o){throw console.error("[PayNext Iframe] Mount failed:",o),await this.unmount(),o}}async unmount(){try{this.iframe&&(this.isReady&&await this.sendMessage("paynext:unmount").catch(()=>{}),this.iframe.parentNode&&this.iframe.parentNode.removeChild(this.iframe),this.iframe=null),window.removeEventListener("message",this.handleMessage),this.container&&(this.container.innerHTML="",this.container=null),this.isReady=!1,this.config=null,this.pendingRequests.clear(),this.messageHandlers.clear(),console.log("[PayNext Iframe] Checkout unmounted")}catch(t){console.error("[PayNext Iframe] Unmount failed:",t)}}async updateConfig(t){if(!this.isReady)throw new Error("Iframe not ready");this.config={...this.config,...t},await this.sendMessage("paynext:updateConfig",{config:{...t,onCheckoutLoaded:void 0,onCheckoutAttempt:void 0,onCheckoutComplete:void 0,onCheckoutFail:void 0}})}static async preload(t){const o=(t?.toLowerCase()?.includes("develop")||t?.toLowerCase()?.includes("staging")?"develop":"production")==="develop"?r:c,n=document.createElement("link");n.rel="preconnect",n.href=new URL(o).origin,document.head.appendChild(n);const a=document.createElement("link");a.rel="dns-prefetch",a.href=new URL(o).origin,document.head.appendChild(a)}}const I={preload:h.preload},N="https://cdn-sdk-dev.paynext.com/index.cdn.js",v="https://cdn-sdk.paynext.com/index.cdn.js";let u=null,m=null;async function g(s){if(m)return m;if(u)return u;const t=s?.toLowerCase()?.includes("develop")||s?.toLowerCase()?.includes("staging")?"develop":"production";return u=new Promise((e,o)=>{if(typeof window>"u"){o(new Error("PayNext SDK can only be loaded in browser environment"));return}if(window.PayNextSDK){console.log("[PayNext CDN] SDK already loaded from cache"),m=window.PayNextSDK,e(m);return}const n=document.createElement("script");n.src=t==="develop"?N:v,n.crossOrigin="*",n.async=!0,n.onload=()=>{const a=window.PayNextSDK;if(!a){console.error("[PayNext CDN] PayNextSDK not found in window after load"),u=null,document.head.removeChild(n),o(new Error("PayNextSDK not found in global scope after loading"));return}m=a,e(a)},n.onerror=a=>{console.error("[PayNext CDN] Failed to load script:",a),u=null,document.head.removeChild(n),o(new Error("Failed to load PayNext SDK script from CDN"))},document.head.appendChild(n)}),u}class w{constructor(){d(this,"cdnInstance",null);d(this,"iframeInstance",null);d(this,"initPromise",null);d(this,"mode","direct")}async initialize(t){try{if(this.initPromise=await g(t),!this.initPromise.PayNextCheckout)throw new Error("PayNextCheckout not found in CDN module");this.cdnInstance=new this.initPromise.PayNextCheckout}catch(e){throw console.error("[PayNext CDN] Failed to initialize:",e),e}}waitForReady(){if(!this.initPromise)throw new Error("SDK initialization not started");if(!this.cdnInstance)throw new Error("SDK instance not created")}async mount(t,e){return e.iframeMode===!0?(this.mode="iframe",this.iframeInstance||(this.iframeInstance=new h),this.iframeInstance.mount(t,e)):(this.mode="direct",await this.initialize(e.environment),this.waitForReady(),this.cdnInstance?.mount(t,e))}async unmount(){if(this.mode==="iframe"&&this.iframeInstance)return this.iframeInstance.unmount();if(this.waitForReady(),this.cdnInstance?.unmount)return this.cdnInstance.unmount()}async updateConfig(t){if(this.mode==="iframe"&&this.iframeInstance)return this.iframeInstance.updateConfig(t);if(this.waitForReady(),this.cdnInstance?.updateConfig)return this.cdnInstance.updateConfig(t)}static async preload(t,e){e?.iframeMode?await h.preload(t):await g(t)}}const E={preload:w.preload};var x=(s=>(s.PAYPAL="PAYPAL",s.APPLE_PAY="APPLEPAY",s.GOOGLE_PAY="GPAY",s.CARD="CARD",s.VENMO="VENMO",s))(x||{});i.PayNextCheckout=w,i.PayNextCheckoutIframe=h,i.PayNextSDK=E,i.PayNextSDKIframe=I,i.PaymentMethod=x,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(e,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(e=typeof globalThis<"u"?globalThis:e||self,n(e["PayNext SDK"]={}))})(this,(function(e){"use strict";var w=Object.defineProperty;var N=(e,n,a)=>n in e?w(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a;var u=(e,n,a)=>N(e,typeof n!="symbol"?n+"":n,a);const n="https://cdn-sdk-dev.paynext.com/index.cdn.js",a="https://cdn-sdk.paynext.com/index.cdn.js";let d=null,s=null;async function P(t){if(s)return s;if(d)return d;const o=t?.toLowerCase()?.includes("develop")||t?.toLowerCase()?.includes("staging")?"develop":"production";return d=new Promise((i,l)=>{if(typeof window>"u"){l(new Error("PayNext SDK can only be loaded in browser environment"));return}if(window.PayNextSDK){console.log("[PayNext CDN] SDK already loaded from cache"),s=window.PayNextSDK,i(s);return}const r=document.createElement("script");r.src=o==="develop"?n:a,r.crossOrigin="*",r.async=!0,r.onload=()=>{const c=window.PayNextSDK;if(!c){console.error("[PayNext CDN] PayNextSDK not found in window after load"),d=null,document.head.removeChild(r),l(new Error("PayNextSDK not found in global scope after loading"));return}s=c,i(c)},r.onerror=c=>{console.error("[PayNext CDN] Failed to load script:",c),d=null,document.head.removeChild(r),l(new Error("Failed to load PayNext SDK script from CDN"))},document.head.appendChild(r)}),d}class y{constructor(){u(this,"cdnInstance",null);u(this,"initPromise",null)}async initialize(o){try{if(this.initPromise=await P(o),!this.initPromise.PayNextCheckout)throw new Error("PayNextCheckout not found in CDN module");this.cdnInstance=new this.initPromise.PayNextCheckout}catch(i){throw console.error("[PayNext CDN] Failed to initialize:",i),i}}waitForReady(){if(!this.initPromise)throw new Error("SDK initialization not started");if(!this.cdnInstance)throw new Error("SDK instance not created")}async mount(o,i){return await this.initialize(i.environment),this.waitForReady(),this.cdnInstance?.mount(o,i)}async unmount(){if(this.waitForReady(),this.cdnInstance?.unmount)return this.cdnInstance.unmount()}async updateConfig(o){if(this.waitForReady(),this.cdnInstance?.updateConfig)return this.cdnInstance.updateConfig(o)}static async preload(o){await P(o)}}const h={preload:y.preload};var f=(t=>(t.PAYPAL="PAYPAL",t.APPLE_PAY="APPLEPAY",t.GOOGLE_PAY="GPAY",t.CARD="CARD",t.VENMO="VENMO",t))(f||{});e.PayNextCheckout=y,e.PayNextSDK=h,e.PaymentMethod=f,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paynext/sdk",
3
- "version": "0.0.173",
3
+ "version": "0.0.174",
4
4
  "description": "PayNext SDK - Payment processing with automatic CDN loading",
5
5
  "type": "module",
6
6
  "main": "dist/index.es.js",
@@ -1,259 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>PayNext Checkout - Iframe Mode</title>
7
-
8
- <!-- Security headers -->
9
- <meta http-equiv="X-Content-Type-Options" content="nosniff">
10
- <meta http-equiv="X-Frame-Options" content="ALLOW-FROM *">
11
- <meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin">
12
-
13
- <!-- CSP for iframe -->
14
- <meta http-equiv="Content-Security-Policy"
15
- content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src *; frame-ancestors *;">
16
-
17
- <style>
18
- * {
19
- margin: 0;
20
- padding: 0;
21
- box-sizing: border-box;
22
- }
23
-
24
- html, body {
25
- width: 100%;
26
- height: 100%;
27
- overflow: hidden;
28
- }
29
-
30
- body {
31
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
32
- }
33
-
34
- #checkout-container {
35
- width: 100%;
36
- min-height: 100%;
37
- }
38
-
39
- /* Loading state */
40
- .loading {
41
- display: flex;
42
- align-items: center;
43
- justify-content: center;
44
- min-height: 400px;
45
- color: #666;
46
- font-size: 14px;
47
- }
48
-
49
- .loading::after {
50
- content: '...';
51
- animation: dots 1.5s steps(4, end) infinite;
52
- }
53
-
54
- @keyframes dots {
55
- 0%, 20% { content: '.'; }
56
- 40% { content: '..'; }
57
- 60%, 100% { content: '...'; }
58
- }
59
- </style>
60
- </head>
61
- <body>
62
- <div id="checkout-container">
63
- <div class="loading">Loading checkout</div>
64
- </div>
65
-
66
- <script type="module">
67
- // Message types for parent communication
68
- const MessageType = {
69
- INIT: 'paynext:init',
70
- MOUNT: 'paynext:mount',
71
- UNMOUNT: 'paynext:unmount',
72
- UPDATE_CONFIG: 'paynext:updateConfig',
73
- READY: 'paynext:ready',
74
- LOADED: 'paynext:loaded',
75
- ATTEMPT: 'paynext:attempt',
76
- COMPLETE: 'paynext:complete',
77
- FAIL: 'paynext:fail',
78
- ERROR: 'paynext:error',
79
- RESIZE: 'paynext:resize'
80
- }
81
-
82
- let checkout = null
83
- let parentOrigin = null
84
- let config = null
85
-
86
- // Send message to parent
87
- function sendToParent(type, payload, requestId) {
88
- if (!parentOrigin) {
89
- console.error('[Iframe] Parent origin not set')
90
- return
91
- }
92
-
93
- window.parent.postMessage(
94
- { type, payload, requestId },
95
- parentOrigin
96
- )
97
- }
98
-
99
- // Handle messages from parent
100
- window.addEventListener('message', async (event) => {
101
- const data = event.data
102
-
103
- // Store parent origin on first message
104
- if (!parentOrigin) {
105
- parentOrigin = event.origin
106
- console.log('[Iframe] Parent origin set to:', parentOrigin)
107
- }
108
-
109
- // Validate origin
110
- if (event.origin !== parentOrigin) {
111
- console.warn('[Iframe] Message from unauthorized origin:', event.origin)
112
- return
113
- }
114
-
115
- if (!data.type || !data.type.startsWith('paynext:')) {
116
- return
117
- }
118
-
119
- try {
120
- switch (data.type) {
121
- case MessageType.MOUNT:
122
- console.log('[Iframe] Mount request received')
123
-
124
- if (data.payload?.config) {
125
- config = data.payload.config
126
-
127
- // Load SDK from CDN
128
- // CDN version exports to window.PayNextSDK
129
- if (!window.PayNextSDK) {
130
- await new Promise((resolve, reject) => {
131
- const script = document.createElement('script')
132
- script.src = './index.cdn.js'
133
- script.onload = resolve
134
- script.onerror = reject
135
- document.head.appendChild(script)
136
- })
137
- }
138
-
139
- const { PayNextCheckout } = window.PayNextSDK || {}
140
-
141
- if (!PayNextCheckout) {
142
- throw new Error('PayNextCheckout not found in window.PayNextSDK')
143
- }
144
-
145
- checkout = new PayNextCheckout()
146
-
147
- // Mount checkout
148
- await checkout.mount('checkout-container', {
149
- ...config,
150
- // Override callbacks to send messages to parent
151
- onCheckoutLoaded: (result) => {
152
- sendToParent(MessageType.LOADED, result, data.requestId)
153
- notifyResize()
154
- },
155
- onCheckoutAttempt: (result) => {
156
- sendToParent(MessageType.ATTEMPT, result)
157
- },
158
- onCheckoutComplete: (result) => {
159
- sendToParent(MessageType.COMPLETE, result)
160
- },
161
- onCheckoutFail: (error) => {
162
- sendToParent(MessageType.FAIL, error)
163
- }
164
- })
165
-
166
- // Send success response
167
- sendToParent(MessageType.READY, { success: true }, data.requestId)
168
-
169
- // Setup resize observer
170
- setupResizeObserver()
171
- }
172
- break
173
-
174
- case MessageType.UNMOUNT:
175
- console.log('[Iframe] Unmount request received')
176
-
177
- if (checkout) {
178
- await checkout.unmount()
179
- checkout = null
180
- }
181
-
182
- sendToParent(MessageType.READY, { success: true }, data.requestId)
183
- break
184
-
185
- case MessageType.UPDATE_CONFIG:
186
- console.log('[Iframe] Update config request received')
187
-
188
- if (checkout && data.payload?.config) {
189
- await checkout.updateConfig(data.payload.config)
190
- sendToParent(MessageType.READY, { success: true }, data.requestId)
191
- }
192
- break
193
-
194
- default:
195
- console.warn('[Iframe] Unknown message type:', data.type)
196
- }
197
- } catch (error) {
198
- console.error('[Iframe] Error handling message:', error)
199
- sendToParent(MessageType.ERROR, {
200
- message: error.message,
201
- stack: error.stack
202
- }, data.requestId)
203
- }
204
- })
205
-
206
- // Setup resize observer to notify parent of height changes
207
- function setupResizeObserver() {
208
- const resizeObserver = new ResizeObserver((entries) => {
209
- for (const entry of entries) {
210
- const height = entry.contentRect.height
211
- sendToParent(MessageType.RESIZE, { height })
212
- }
213
- })
214
-
215
- resizeObserver.observe(document.body)
216
- }
217
-
218
- // Notify parent of current height
219
- function notifyResize() {
220
- const height = document.body.scrollHeight
221
- sendToParent(MessageType.RESIZE, { height })
222
- }
223
-
224
- // Send ready message when iframe loads
225
- window.addEventListener('load', () => {
226
- console.log('[Iframe] Iframe loaded and ready')
227
-
228
- // Wait a bit for parent to setup message listener
229
- setTimeout(() => {
230
- // Send ready to any origin initially
231
- window.parent.postMessage(
232
- { type: MessageType.READY, payload: { success: true } },
233
- '*'
234
- )
235
- }, 100)
236
- })
237
-
238
- // Log errors
239
- window.addEventListener('error', (event) => {
240
- console.error('[Iframe] Runtime error:', event.error)
241
- sendToParent(MessageType.ERROR, {
242
- message: event.error?.message || 'Unknown error',
243
- stack: event.error?.stack
244
- })
245
- })
246
-
247
- window.addEventListener('unhandledrejection', (event) => {
248
- console.error('[Iframe] Unhandled promise rejection:', event.reason)
249
- sendToParent(MessageType.ERROR, {
250
- message: event.reason?.message || 'Unhandled promise rejection',
251
- stack: event.reason?.stack
252
- })
253
- })
254
-
255
- console.log('[Iframe] PayNext Checkout iframe initialized')
256
- </script>
257
- </body>
258
- </html>
259
-