@funnelfox/billing 0.6.3 → 0.6.4-beta.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.
@@ -150,46 +150,64 @@ class NetworkError extends FunnefoxSDKError {
150
150
  }
151
151
 
152
152
  /**
153
- * @fileoverview Dynamic loader for Primer SDK
154
- * Loads Primer script and CSS from CDN independently of bundler
153
+ * @fileoverview Generic script and stylesheet loader utility to reduce bundle size
155
154
  */
156
- const PRIMER_CDN_BASE = 'https://sdk.primer.io/web';
157
- const DEFAULT_VERSION = '2.57.3';
158
- // Integrity hashes for specific versions (for SRI security)
159
- const INTEGRITY_HASHES = {
160
- '2.57.3': {
161
- js: 'sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4',
162
- },
163
- };
164
- let loadingPromise = null;
165
- let isLoaded = false;
166
155
  /**
167
- * Injects a script tag into the document head
156
+ * Dynamically loads an external script into the document.
157
+ * Checks if script already exists before loading to prevent duplicates.
158
+ *
159
+ * @param options - Script configuration options
160
+ * @returns Promise that resolves when script is loaded or rejects on error
168
161
  */
169
- function injectScript$1(src, integrity) {
162
+ function loadScript$1(options) {
163
+ const { id, src, async = true, type = 'text/javascript', attributes = {}, integrity, crossOrigin, appendTo = 'body', } = options;
170
164
  return new Promise((resolve, reject) => {
171
- // Check if script already exists
172
- const existingScript = document.querySelector(`script[src="${src}"]`);
165
+ // Check if script already exists (by ID or src)
166
+ let existingScript = null;
167
+ if (id) {
168
+ existingScript = document.getElementById(id);
169
+ }
170
+ if (!existingScript) {
171
+ existingScript = document.querySelector(`script[src="${src}"]`);
172
+ }
173
173
  if (existingScript) {
174
174
  resolve(existingScript);
175
175
  return;
176
176
  }
177
177
  const script = document.createElement('script');
178
+ if (id) {
179
+ script.id = id;
180
+ }
181
+ script.type = type;
178
182
  script.src = src;
179
- script.async = true;
180
- script.crossOrigin = 'anonymous';
183
+ if (async) {
184
+ script.async = true;
185
+ }
181
186
  if (integrity) {
182
187
  script.integrity = integrity;
183
188
  }
189
+ if (crossOrigin) {
190
+ script.crossOrigin = crossOrigin;
191
+ }
192
+ // Set additional attributes
193
+ Object.entries(attributes).forEach(([key, value]) => {
194
+ script.setAttribute(key, value);
195
+ });
184
196
  script.onload = () => resolve(script);
185
- script.onerror = () => reject(new Error(`Failed to load Primer SDK script from ${src}`));
186
- document.head.appendChild(script);
197
+ script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
198
+ const target = appendTo === 'head' ? document.head : document.body;
199
+ target.appendChild(script);
187
200
  });
188
201
  }
189
202
  /**
190
- * Injects a CSS link tag into the document head
203
+ * Dynamically loads an external stylesheet into the document head.
204
+ * Checks if stylesheet already exists before loading to prevent duplicates.
205
+ *
206
+ * @param options - Stylesheet configuration options
207
+ * @returns Promise that resolves when stylesheet is loaded or rejects on error
191
208
  */
192
- function injectCSS(href, integrity) {
209
+ function loadStylesheet(options) {
210
+ const { href, integrity, crossOrigin } = options;
193
211
  return new Promise((resolve, reject) => {
194
212
  // Check if stylesheet already exists
195
213
  const existingLink = document.querySelector(`link[href="${href}"]`);
@@ -200,15 +218,32 @@ function injectCSS(href, integrity) {
200
218
  const link = document.createElement('link');
201
219
  link.rel = 'stylesheet';
202
220
  link.href = href;
203
- link.crossOrigin = 'anonymous';
204
221
  if (integrity) {
205
222
  link.integrity = integrity;
206
223
  }
224
+ if (crossOrigin) {
225
+ link.crossOrigin = crossOrigin;
226
+ }
207
227
  link.onload = () => resolve(link);
208
- link.onerror = () => reject(new Error(`Failed to load Primer SDK CSS from ${href}`));
228
+ link.onerror = () => reject(new Error(`Failed to load stylesheet: ${href}`));
209
229
  document.head.appendChild(link);
210
230
  });
211
231
  }
232
+
233
+ /**
234
+ * @fileoverview Dynamic loader for Primer SDK
235
+ * Loads Primer script and CSS from CDN independently of bundler
236
+ */
237
+ const PRIMER_CDN_BASE = 'https://sdk.primer.io/web';
238
+ const DEFAULT_VERSION = '2.57.3';
239
+ // Integrity hashes for specific versions (for SRI security)
240
+ const INTEGRITY_HASHES = {
241
+ '2.57.3': {
242
+ js: 'sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4',
243
+ },
244
+ };
245
+ let loadingPromise = null;
246
+ let isLoaded = false;
212
247
  /**
213
248
  * Waits for window.Primer to be available
214
249
  */
@@ -260,8 +295,17 @@ async function loadPrimerSDK(version) {
260
295
  try {
261
296
  // Load CSS and JS in parallel
262
297
  await Promise.all([
263
- injectCSS(cssUrl, hashes?.css),
264
- injectScript$1(jsUrl, hashes?.js),
298
+ loadStylesheet({
299
+ href: cssUrl,
300
+ integrity: hashes?.css,
301
+ crossOrigin: 'anonymous',
302
+ }),
303
+ loadScript$1({
304
+ src: jsUrl,
305
+ integrity: hashes?.js,
306
+ crossOrigin: 'anonymous',
307
+ appendTo: 'head',
308
+ }),
265
309
  ]);
266
310
  // Wait for Primer to be available on window
267
311
  await waitForPrimer();
@@ -304,6 +348,28 @@ function generateId(prefix = '') {
304
348
  const random = Math.random().toString(36).substr(2, 5);
305
349
  return `${prefix}${timestamp}_${random}`;
306
350
  }
351
+ /**
352
+ * Generates a UUID v4 compliant string (RFC 4122).
353
+ * Meets Airwallex requirements:
354
+ * - Maximum 128 characters (UUID is 36 chars)
355
+ * - Only contains: a-z, A-Z, 0-9, underscore, hyphen
356
+ * - No prefix + timestamp pattern
357
+ * - Not a short series of numbers
358
+ *
359
+ * @returns UUID v4 string (e.g., "a3bb189e-8bf9-3888-9912-ace4e6543002")
360
+ */
361
+ function generateUUID() {
362
+ // Use crypto.randomUUID if available (modern browsers)
363
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
364
+ return crypto.randomUUID();
365
+ }
366
+ // Fallback: manual UUID v4 generation
367
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
368
+ const r = (Math.random() * 16) | 0;
369
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
370
+ return v.toString(16);
371
+ });
372
+ }
307
373
  function sleep(ms) {
308
374
  return new Promise(resolve => setTimeout(resolve, ms));
309
375
  }
@@ -422,7 +488,7 @@ exports.PaymentMethod = void 0;
422
488
  /**
423
489
  * @fileoverview Constants for Funnefox SDK
424
490
  */
425
- const SDK_VERSION = '0.6.3';
491
+ const SDK_VERSION = '0.6.4-beta.0';
426
492
  const DEFAULTS = {
427
493
  BASE_URL: 'https://billing.funnelfox.com',
428
494
  REGION: 'default',
@@ -1321,6 +1387,34 @@ const renderError = (container, reqId) => {
1321
1387
  }
1322
1388
  };
1323
1389
 
1390
+ /**
1391
+ * @fileoverview Airwallex device fingerprinting script loader
1392
+ */
1393
+ /**
1394
+ * Loads Airwallex device fingerprinting script for fraud prevention.
1395
+ * The script collects browser, screen, device, and interaction data.
1396
+ *
1397
+ * @param sessionId - Unique order session ID (UUID v4 format, max 128 chars)
1398
+ * @param isDemoMode - If true, uses demo environment URL for testing
1399
+ * @returns Promise that resolves when script is loaded
1400
+ *
1401
+ * @see https://www.airwallex.com/docs/payments/online-payments/native-api/device-fingerprinting
1402
+ */
1403
+ async function loadAirwallexDeviceFingerprint(sessionId, isDemoMode = false) {
1404
+ const scriptId = 'airwallex-fraud-api';
1405
+ const src = isDemoMode
1406
+ ? 'https://static-demo.airwallex.com/webapp/fraud/device-fingerprint/index.js'
1407
+ : 'https://static.airwallex.com/webapp/fraud/device-fingerprint/index.js';
1408
+ await loadScript$1({
1409
+ id: scriptId,
1410
+ src,
1411
+ async: true,
1412
+ attributes: {
1413
+ 'data-order-session-id': sessionId,
1414
+ },
1415
+ });
1416
+ }
1417
+
1324
1418
  /**
1325
1419
  * @fileoverview Checkout instance manager for Funnefox SDK
1326
1420
  */
@@ -1329,6 +1423,7 @@ class CheckoutInstance extends EventEmitter {
1329
1423
  super();
1330
1424
  this.counter = 0;
1331
1425
  this.radarSessionId = null;
1426
+ this.airwallexDeviceId = null;
1332
1427
  this.handleInputChange = (inputName, error) => {
1333
1428
  this.emit(EVENTS.INPUT_ERROR, { name: inputName, error });
1334
1429
  };
@@ -1350,12 +1445,16 @@ class CheckoutInstance extends EventEmitter {
1350
1445
  try {
1351
1446
  this.onLoaderChangeWithRace(true);
1352
1447
  this._setState('processing');
1353
- const radarSessionId = await this.radarSessionId;
1448
+ const [radarSessionId, airwallexDeviceId] = await Promise.all([
1449
+ this.radarSessionId,
1450
+ this.airwallexDeviceId,
1451
+ ]);
1354
1452
  const paymentResponse = await this.apiClient.createPayment({
1355
1453
  orderId: this.orderId,
1356
1454
  paymentMethodToken: paymentMethodTokenData.token,
1357
1455
  clientMetadata: {
1358
1456
  radarSessionId,
1457
+ airwallexDeviceId,
1359
1458
  },
1360
1459
  });
1361
1460
  const result = this.apiClient.processPaymentResponse(paymentResponse);
@@ -1503,6 +1602,16 @@ class CheckoutInstance extends EventEmitter {
1503
1602
  .catch(() => '');
1504
1603
  });
1505
1604
  }
1605
+ // Initialize Airwallex device fingerprinting if enabled by backend
1606
+ if (response.data?.airwallex_risk_enabled) {
1607
+ const deviceId = generateUUID();
1608
+ this.airwallexDeviceId = loadAirwallexDeviceFingerprint(deviceId, true)
1609
+ .then(() => deviceId)
1610
+ .catch(() => {
1611
+ // Silently fail - return deviceId anyway
1612
+ return deviceId;
1613
+ });
1614
+ }
1506
1615
  this.isCollectingApplePayEmail =
1507
1616
  !!response.data?.collect_apple_pay_email;
1508
1617
  return response;
@@ -148,46 +148,64 @@ class NetworkError extends FunnefoxSDKError {
148
148
  }
149
149
 
150
150
  /**
151
- * @fileoverview Dynamic loader for Primer SDK
152
- * Loads Primer script and CSS from CDN independently of bundler
151
+ * @fileoverview Generic script and stylesheet loader utility to reduce bundle size
153
152
  */
154
- const PRIMER_CDN_BASE = 'https://sdk.primer.io/web';
155
- const DEFAULT_VERSION = '2.57.3';
156
- // Integrity hashes for specific versions (for SRI security)
157
- const INTEGRITY_HASHES = {
158
- '2.57.3': {
159
- js: 'sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4',
160
- },
161
- };
162
- let loadingPromise = null;
163
- let isLoaded = false;
164
153
  /**
165
- * Injects a script tag into the document head
154
+ * Dynamically loads an external script into the document.
155
+ * Checks if script already exists before loading to prevent duplicates.
156
+ *
157
+ * @param options - Script configuration options
158
+ * @returns Promise that resolves when script is loaded or rejects on error
166
159
  */
167
- function injectScript$1(src, integrity) {
160
+ function loadScript$1(options) {
161
+ const { id, src, async = true, type = 'text/javascript', attributes = {}, integrity, crossOrigin, appendTo = 'body', } = options;
168
162
  return new Promise((resolve, reject) => {
169
- // Check if script already exists
170
- const existingScript = document.querySelector(`script[src="${src}"]`);
163
+ // Check if script already exists (by ID or src)
164
+ let existingScript = null;
165
+ if (id) {
166
+ existingScript = document.getElementById(id);
167
+ }
168
+ if (!existingScript) {
169
+ existingScript = document.querySelector(`script[src="${src}"]`);
170
+ }
171
171
  if (existingScript) {
172
172
  resolve(existingScript);
173
173
  return;
174
174
  }
175
175
  const script = document.createElement('script');
176
+ if (id) {
177
+ script.id = id;
178
+ }
179
+ script.type = type;
176
180
  script.src = src;
177
- script.async = true;
178
- script.crossOrigin = 'anonymous';
181
+ if (async) {
182
+ script.async = true;
183
+ }
179
184
  if (integrity) {
180
185
  script.integrity = integrity;
181
186
  }
187
+ if (crossOrigin) {
188
+ script.crossOrigin = crossOrigin;
189
+ }
190
+ // Set additional attributes
191
+ Object.entries(attributes).forEach(([key, value]) => {
192
+ script.setAttribute(key, value);
193
+ });
182
194
  script.onload = () => resolve(script);
183
- script.onerror = () => reject(new Error(`Failed to load Primer SDK script from ${src}`));
184
- document.head.appendChild(script);
195
+ script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
196
+ const target = appendTo === 'head' ? document.head : document.body;
197
+ target.appendChild(script);
185
198
  });
186
199
  }
187
200
  /**
188
- * Injects a CSS link tag into the document head
201
+ * Dynamically loads an external stylesheet into the document head.
202
+ * Checks if stylesheet already exists before loading to prevent duplicates.
203
+ *
204
+ * @param options - Stylesheet configuration options
205
+ * @returns Promise that resolves when stylesheet is loaded or rejects on error
189
206
  */
190
- function injectCSS(href, integrity) {
207
+ function loadStylesheet(options) {
208
+ const { href, integrity, crossOrigin } = options;
191
209
  return new Promise((resolve, reject) => {
192
210
  // Check if stylesheet already exists
193
211
  const existingLink = document.querySelector(`link[href="${href}"]`);
@@ -198,15 +216,32 @@ function injectCSS(href, integrity) {
198
216
  const link = document.createElement('link');
199
217
  link.rel = 'stylesheet';
200
218
  link.href = href;
201
- link.crossOrigin = 'anonymous';
202
219
  if (integrity) {
203
220
  link.integrity = integrity;
204
221
  }
222
+ if (crossOrigin) {
223
+ link.crossOrigin = crossOrigin;
224
+ }
205
225
  link.onload = () => resolve(link);
206
- link.onerror = () => reject(new Error(`Failed to load Primer SDK CSS from ${href}`));
226
+ link.onerror = () => reject(new Error(`Failed to load stylesheet: ${href}`));
207
227
  document.head.appendChild(link);
208
228
  });
209
229
  }
230
+
231
+ /**
232
+ * @fileoverview Dynamic loader for Primer SDK
233
+ * Loads Primer script and CSS from CDN independently of bundler
234
+ */
235
+ const PRIMER_CDN_BASE = 'https://sdk.primer.io/web';
236
+ const DEFAULT_VERSION = '2.57.3';
237
+ // Integrity hashes for specific versions (for SRI security)
238
+ const INTEGRITY_HASHES = {
239
+ '2.57.3': {
240
+ js: 'sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4',
241
+ },
242
+ };
243
+ let loadingPromise = null;
244
+ let isLoaded = false;
210
245
  /**
211
246
  * Waits for window.Primer to be available
212
247
  */
@@ -258,8 +293,17 @@ async function loadPrimerSDK(version) {
258
293
  try {
259
294
  // Load CSS and JS in parallel
260
295
  await Promise.all([
261
- injectCSS(cssUrl, hashes?.css),
262
- injectScript$1(jsUrl, hashes?.js),
296
+ loadStylesheet({
297
+ href: cssUrl,
298
+ integrity: hashes?.css,
299
+ crossOrigin: 'anonymous',
300
+ }),
301
+ loadScript$1({
302
+ src: jsUrl,
303
+ integrity: hashes?.js,
304
+ crossOrigin: 'anonymous',
305
+ appendTo: 'head',
306
+ }),
263
307
  ]);
264
308
  // Wait for Primer to be available on window
265
309
  await waitForPrimer();
@@ -302,6 +346,28 @@ function generateId(prefix = '') {
302
346
  const random = Math.random().toString(36).substr(2, 5);
303
347
  return `${prefix}${timestamp}_${random}`;
304
348
  }
349
+ /**
350
+ * Generates a UUID v4 compliant string (RFC 4122).
351
+ * Meets Airwallex requirements:
352
+ * - Maximum 128 characters (UUID is 36 chars)
353
+ * - Only contains: a-z, A-Z, 0-9, underscore, hyphen
354
+ * - No prefix + timestamp pattern
355
+ * - Not a short series of numbers
356
+ *
357
+ * @returns UUID v4 string (e.g., "a3bb189e-8bf9-3888-9912-ace4e6543002")
358
+ */
359
+ function generateUUID() {
360
+ // Use crypto.randomUUID if available (modern browsers)
361
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
362
+ return crypto.randomUUID();
363
+ }
364
+ // Fallback: manual UUID v4 generation
365
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
366
+ const r = (Math.random() * 16) | 0;
367
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
368
+ return v.toString(16);
369
+ });
370
+ }
305
371
  function sleep(ms) {
306
372
  return new Promise(resolve => setTimeout(resolve, ms));
307
373
  }
@@ -420,7 +486,7 @@ var PaymentMethod;
420
486
  /**
421
487
  * @fileoverview Constants for Funnefox SDK
422
488
  */
423
- const SDK_VERSION = '0.6.3';
489
+ const SDK_VERSION = '0.6.4-beta.0';
424
490
  const DEFAULTS = {
425
491
  BASE_URL: 'https://billing.funnelfox.com',
426
492
  REGION: 'default',
@@ -1319,6 +1385,34 @@ const renderError = (container, reqId) => {
1319
1385
  }
1320
1386
  };
1321
1387
 
1388
+ /**
1389
+ * @fileoverview Airwallex device fingerprinting script loader
1390
+ */
1391
+ /**
1392
+ * Loads Airwallex device fingerprinting script for fraud prevention.
1393
+ * The script collects browser, screen, device, and interaction data.
1394
+ *
1395
+ * @param sessionId - Unique order session ID (UUID v4 format, max 128 chars)
1396
+ * @param isDemoMode - If true, uses demo environment URL for testing
1397
+ * @returns Promise that resolves when script is loaded
1398
+ *
1399
+ * @see https://www.airwallex.com/docs/payments/online-payments/native-api/device-fingerprinting
1400
+ */
1401
+ async function loadAirwallexDeviceFingerprint(sessionId, isDemoMode = false) {
1402
+ const scriptId = 'airwallex-fraud-api';
1403
+ const src = isDemoMode
1404
+ ? 'https://static-demo.airwallex.com/webapp/fraud/device-fingerprint/index.js'
1405
+ : 'https://static.airwallex.com/webapp/fraud/device-fingerprint/index.js';
1406
+ await loadScript$1({
1407
+ id: scriptId,
1408
+ src,
1409
+ async: true,
1410
+ attributes: {
1411
+ 'data-order-session-id': sessionId,
1412
+ },
1413
+ });
1414
+ }
1415
+
1322
1416
  /**
1323
1417
  * @fileoverview Checkout instance manager for Funnefox SDK
1324
1418
  */
@@ -1327,6 +1421,7 @@ class CheckoutInstance extends EventEmitter {
1327
1421
  super();
1328
1422
  this.counter = 0;
1329
1423
  this.radarSessionId = null;
1424
+ this.airwallexDeviceId = null;
1330
1425
  this.handleInputChange = (inputName, error) => {
1331
1426
  this.emit(EVENTS.INPUT_ERROR, { name: inputName, error });
1332
1427
  };
@@ -1348,12 +1443,16 @@ class CheckoutInstance extends EventEmitter {
1348
1443
  try {
1349
1444
  this.onLoaderChangeWithRace(true);
1350
1445
  this._setState('processing');
1351
- const radarSessionId = await this.radarSessionId;
1446
+ const [radarSessionId, airwallexDeviceId] = await Promise.all([
1447
+ this.radarSessionId,
1448
+ this.airwallexDeviceId,
1449
+ ]);
1352
1450
  const paymentResponse = await this.apiClient.createPayment({
1353
1451
  orderId: this.orderId,
1354
1452
  paymentMethodToken: paymentMethodTokenData.token,
1355
1453
  clientMetadata: {
1356
1454
  radarSessionId,
1455
+ airwallexDeviceId,
1357
1456
  },
1358
1457
  });
1359
1458
  const result = this.apiClient.processPaymentResponse(paymentResponse);
@@ -1501,6 +1600,16 @@ class CheckoutInstance extends EventEmitter {
1501
1600
  .catch(() => '');
1502
1601
  });
1503
1602
  }
1603
+ // Initialize Airwallex device fingerprinting if enabled by backend
1604
+ if (response.data?.airwallex_risk_enabled) {
1605
+ const deviceId = generateUUID();
1606
+ this.airwallexDeviceId = loadAirwallexDeviceFingerprint(deviceId, true)
1607
+ .then(() => deviceId)
1608
+ .catch(() => {
1609
+ // Silently fail - return deviceId anyway
1610
+ return deviceId;
1611
+ });
1612
+ }
1504
1613
  this.isCollectingApplePayEmail =
1505
1614
  !!response.data?.collect_apple_pay_email;
1506
1615
  return response;
@@ -154,46 +154,64 @@
154
154
  }
155
155
 
156
156
  /**
157
- * @fileoverview Dynamic loader for Primer SDK
158
- * Loads Primer script and CSS from CDN independently of bundler
157
+ * @fileoverview Generic script and stylesheet loader utility to reduce bundle size
159
158
  */
160
- const PRIMER_CDN_BASE = 'https://sdk.primer.io/web';
161
- const DEFAULT_VERSION = '2.57.3';
162
- // Integrity hashes for specific versions (for SRI security)
163
- const INTEGRITY_HASHES = {
164
- '2.57.3': {
165
- js: 'sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4',
166
- },
167
- };
168
- let loadingPromise = null;
169
- let isLoaded = false;
170
159
  /**
171
- * Injects a script tag into the document head
160
+ * Dynamically loads an external script into the document.
161
+ * Checks if script already exists before loading to prevent duplicates.
162
+ *
163
+ * @param options - Script configuration options
164
+ * @returns Promise that resolves when script is loaded or rejects on error
172
165
  */
173
- function injectScript$1(src, integrity) {
166
+ function loadScript$1(options) {
167
+ const { id, src, async = true, type = 'text/javascript', attributes = {}, integrity, crossOrigin, appendTo = 'body', } = options;
174
168
  return new Promise((resolve, reject) => {
175
- // Check if script already exists
176
- const existingScript = document.querySelector(`script[src="${src}"]`);
169
+ // Check if script already exists (by ID or src)
170
+ let existingScript = null;
171
+ if (id) {
172
+ existingScript = document.getElementById(id);
173
+ }
174
+ if (!existingScript) {
175
+ existingScript = document.querySelector(`script[src="${src}"]`);
176
+ }
177
177
  if (existingScript) {
178
178
  resolve(existingScript);
179
179
  return;
180
180
  }
181
181
  const script = document.createElement('script');
182
+ if (id) {
183
+ script.id = id;
184
+ }
185
+ script.type = type;
182
186
  script.src = src;
183
- script.async = true;
184
- script.crossOrigin = 'anonymous';
187
+ if (async) {
188
+ script.async = true;
189
+ }
185
190
  if (integrity) {
186
191
  script.integrity = integrity;
187
192
  }
193
+ if (crossOrigin) {
194
+ script.crossOrigin = crossOrigin;
195
+ }
196
+ // Set additional attributes
197
+ Object.entries(attributes).forEach(([key, value]) => {
198
+ script.setAttribute(key, value);
199
+ });
188
200
  script.onload = () => resolve(script);
189
- script.onerror = () => reject(new Error(`Failed to load Primer SDK script from ${src}`));
190
- document.head.appendChild(script);
201
+ script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
202
+ const target = appendTo === 'head' ? document.head : document.body;
203
+ target.appendChild(script);
191
204
  });
192
205
  }
193
206
  /**
194
- * Injects a CSS link tag into the document head
207
+ * Dynamically loads an external stylesheet into the document head.
208
+ * Checks if stylesheet already exists before loading to prevent duplicates.
209
+ *
210
+ * @param options - Stylesheet configuration options
211
+ * @returns Promise that resolves when stylesheet is loaded or rejects on error
195
212
  */
196
- function injectCSS(href, integrity) {
213
+ function loadStylesheet(options) {
214
+ const { href, integrity, crossOrigin } = options;
197
215
  return new Promise((resolve, reject) => {
198
216
  // Check if stylesheet already exists
199
217
  const existingLink = document.querySelector(`link[href="${href}"]`);
@@ -204,15 +222,32 @@
204
222
  const link = document.createElement('link');
205
223
  link.rel = 'stylesheet';
206
224
  link.href = href;
207
- link.crossOrigin = 'anonymous';
208
225
  if (integrity) {
209
226
  link.integrity = integrity;
210
227
  }
228
+ if (crossOrigin) {
229
+ link.crossOrigin = crossOrigin;
230
+ }
211
231
  link.onload = () => resolve(link);
212
- link.onerror = () => reject(new Error(`Failed to load Primer SDK CSS from ${href}`));
232
+ link.onerror = () => reject(new Error(`Failed to load stylesheet: ${href}`));
213
233
  document.head.appendChild(link);
214
234
  });
215
235
  }
236
+
237
+ /**
238
+ * @fileoverview Dynamic loader for Primer SDK
239
+ * Loads Primer script and CSS from CDN independently of bundler
240
+ */
241
+ const PRIMER_CDN_BASE = 'https://sdk.primer.io/web';
242
+ const DEFAULT_VERSION = '2.57.3';
243
+ // Integrity hashes for specific versions (for SRI security)
244
+ const INTEGRITY_HASHES = {
245
+ '2.57.3': {
246
+ js: 'sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4',
247
+ },
248
+ };
249
+ let loadingPromise = null;
250
+ let isLoaded = false;
216
251
  /**
217
252
  * Waits for window.Primer to be available
218
253
  */
@@ -264,8 +299,17 @@
264
299
  try {
265
300
  // Load CSS and JS in parallel
266
301
  await Promise.all([
267
- injectCSS(cssUrl, hashes?.css),
268
- injectScript$1(jsUrl, hashes?.js),
302
+ loadStylesheet({
303
+ href: cssUrl,
304
+ integrity: hashes?.css,
305
+ crossOrigin: 'anonymous',
306
+ }),
307
+ loadScript$1({
308
+ src: jsUrl,
309
+ integrity: hashes?.js,
310
+ crossOrigin: 'anonymous',
311
+ appendTo: 'head',
312
+ }),
269
313
  ]);
270
314
  // Wait for Primer to be available on window
271
315
  await waitForPrimer();
@@ -308,6 +352,28 @@
308
352
  const random = Math.random().toString(36).substr(2, 5);
309
353
  return `${prefix}${timestamp}_${random}`;
310
354
  }
355
+ /**
356
+ * Generates a UUID v4 compliant string (RFC 4122).
357
+ * Meets Airwallex requirements:
358
+ * - Maximum 128 characters (UUID is 36 chars)
359
+ * - Only contains: a-z, A-Z, 0-9, underscore, hyphen
360
+ * - No prefix + timestamp pattern
361
+ * - Not a short series of numbers
362
+ *
363
+ * @returns UUID v4 string (e.g., "a3bb189e-8bf9-3888-9912-ace4e6543002")
364
+ */
365
+ function generateUUID() {
366
+ // Use crypto.randomUUID if available (modern browsers)
367
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
368
+ return crypto.randomUUID();
369
+ }
370
+ // Fallback: manual UUID v4 generation
371
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
372
+ const r = (Math.random() * 16) | 0;
373
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
374
+ return v.toString(16);
375
+ });
376
+ }
311
377
  function sleep(ms) {
312
378
  return new Promise(resolve => setTimeout(resolve, ms));
313
379
  }
@@ -426,7 +492,7 @@
426
492
  /**
427
493
  * @fileoverview Constants for Funnefox SDK
428
494
  */
429
- const SDK_VERSION = '0.6.3';
495
+ const SDK_VERSION = '0.6.4-beta.0';
430
496
  const DEFAULTS = {
431
497
  BASE_URL: 'https://billing.funnelfox.com',
432
498
  REGION: 'default',
@@ -1325,6 +1391,34 @@
1325
1391
  }
1326
1392
  };
1327
1393
 
1394
+ /**
1395
+ * @fileoverview Airwallex device fingerprinting script loader
1396
+ */
1397
+ /**
1398
+ * Loads Airwallex device fingerprinting script for fraud prevention.
1399
+ * The script collects browser, screen, device, and interaction data.
1400
+ *
1401
+ * @param sessionId - Unique order session ID (UUID v4 format, max 128 chars)
1402
+ * @param isDemoMode - If true, uses demo environment URL for testing
1403
+ * @returns Promise that resolves when script is loaded
1404
+ *
1405
+ * @see https://www.airwallex.com/docs/payments/online-payments/native-api/device-fingerprinting
1406
+ */
1407
+ async function loadAirwallexDeviceFingerprint(sessionId, isDemoMode = false) {
1408
+ const scriptId = 'airwallex-fraud-api';
1409
+ const src = isDemoMode
1410
+ ? 'https://static-demo.airwallex.com/webapp/fraud/device-fingerprint/index.js'
1411
+ : 'https://static.airwallex.com/webapp/fraud/device-fingerprint/index.js';
1412
+ await loadScript$1({
1413
+ id: scriptId,
1414
+ src,
1415
+ async: true,
1416
+ attributes: {
1417
+ 'data-order-session-id': sessionId,
1418
+ },
1419
+ });
1420
+ }
1421
+
1328
1422
  /**
1329
1423
  * @fileoverview Checkout instance manager for Funnefox SDK
1330
1424
  */
@@ -1333,6 +1427,7 @@
1333
1427
  super();
1334
1428
  this.counter = 0;
1335
1429
  this.radarSessionId = null;
1430
+ this.airwallexDeviceId = null;
1336
1431
  this.handleInputChange = (inputName, error) => {
1337
1432
  this.emit(EVENTS.INPUT_ERROR, { name: inputName, error });
1338
1433
  };
@@ -1354,12 +1449,16 @@
1354
1449
  try {
1355
1450
  this.onLoaderChangeWithRace(true);
1356
1451
  this._setState('processing');
1357
- const radarSessionId = await this.radarSessionId;
1452
+ const [radarSessionId, airwallexDeviceId] = await Promise.all([
1453
+ this.radarSessionId,
1454
+ this.airwallexDeviceId,
1455
+ ]);
1358
1456
  const paymentResponse = await this.apiClient.createPayment({
1359
1457
  orderId: this.orderId,
1360
1458
  paymentMethodToken: paymentMethodTokenData.token,
1361
1459
  clientMetadata: {
1362
1460
  radarSessionId,
1461
+ airwallexDeviceId,
1363
1462
  },
1364
1463
  });
1365
1464
  const result = this.apiClient.processPaymentResponse(paymentResponse);
@@ -1507,6 +1606,16 @@
1507
1606
  .catch(() => '');
1508
1607
  });
1509
1608
  }
1609
+ // Initialize Airwallex device fingerprinting if enabled by backend
1610
+ if (response.data?.airwallex_risk_enabled) {
1611
+ const deviceId = generateUUID();
1612
+ this.airwallexDeviceId = loadAirwallexDeviceFingerprint(deviceId, true)
1613
+ .then(() => deviceId)
1614
+ .catch(() => {
1615
+ // Silently fail - return deviceId anyway
1616
+ return deviceId;
1617
+ });
1618
+ }
1510
1619
  this.isCollectingApplePayEmail =
1511
1620
  !!response.data?.collect_apple_pay_email;
1512
1621
  return response;
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FunnelfoxSDK={})}(this,function(e){"use strict";class t{constructor(){this._events=new Map}on(e,t){if("function"!=typeof t)throw new Error("Event handler must be a function");return this._events.has(e)||this._events.set(e,[]),this._events.get(e).push(t),this}once(e,t){if("function"!=typeof t)throw new Error("Event handler must be a function");const n=(...r)=>{this.off(e,n),t.apply(this,r)};return this.on(e,n)}off(e,t=null){if(!this._events.has(e))return this;if(null===t)return this._events.delete(e),this;const n=this._events.get(e),r=n.indexOf(t);return-1!==r&&(n.splice(r,1),0===n.length&&this._events.delete(e)),this}emit(e,...t){if(!this._events.has(e))return!1;const n=this._events.get(e).slice();for(const r of n)try{r.apply(this,t)}catch(t){console.warn(`Error in event handler for "${String(e)}":`,t)}return!0}listenerCount(e){return this._events.has(e)?this._events.get(e).length:0}eventNames(){return Array.from(this._events.keys())}removeAllListeners(){return this._events.clear(),this}listeners(e){return this._events.has(e)?this._events.get(e).slice():[]}}class n extends Error{constructor(e,t=k.SDK_ERROR,r=null){super(e),this.name="FunnefoxSDKError",this.code=t,this.details=r,Error.captureStackTrace&&Error.captureStackTrace(this,n)}}class r extends n{constructor(e,t,n=null){super(`Invalid ${e}: ${t}`,k.VALIDATION_ERROR),this.name="ValidationError",this.field=e,this.value=n}}class o extends n{constructor(e,t=null,n={}){super(e,n.errorCode||k.API_ERROR),this.name="APIError",this.statusCode=t,this.errorCode=n.errorCode||null,this.errorType=n.errorType||null,this.requestId=n.requestId||null,this.response=n.response||null}}class a extends n{constructor(e,t=null){super(e,k.PRIMER_ERROR),this.name="PrimerError",this.primerError=t}}class i extends n{constructor(e,t=null){super(e,k.CHECKOUT_ERROR),this.name="CheckoutError",this.phase=t}}class s extends n{constructor(e,t=null){super(e,k.NETWORK_ERROR),this.name="NetworkError",this.originalError=t}}const d="https://sdk.primer.io/web",c={"2.57.3":{js:"sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4"}};let l=null,h=!1;function u(e,t){return new Promise((n,r)=>{const o=document.querySelector(`script[src="${e}"]`);if(o)return void n(o);const a=document.createElement("script");a.src=e,a.async=!0,a.crossOrigin="anonymous",t&&(a.integrity=t),a.onload=()=>n(a),a.onerror=()=>r(new Error(`Failed to load Primer SDK script from ${e}`)),document.head.appendChild(a)})}async function p(e){if(h)return;if(l)return l;if("undefined"!=typeof window&&window.Primer&&"function"==typeof window.Primer.createHeadless)return void(h=!0);const t=e||"2.57.3",n=`${d}/v${t}/Primer.min.js`,r=`${d}/v${t}/Checkout.css`,o=c[t];return l=(async()=>{try{await Promise.all([(e=r,t=o?.css,new Promise((n,r)=>{const o=document.querySelector(`link[href="${e}"]`);if(o)return void n(o);const a=document.createElement("link");a.rel="stylesheet",a.href=e,a.crossOrigin="anonymous",t&&(a.integrity=t),a.onload=()=>n(a),a.onerror=()=>r(new Error(`Failed to load Primer SDK CSS from ${e}`)),document.head.appendChild(a)})),u(n,o?.js)]),await function(e=1e4){return new Promise((t,n)=>{const r=Date.now(),o=()=>{"undefined"!=typeof window&&window.Primer&&"function"==typeof window.Primer.createHeadless?t():Date.now()-r>e?n(new Error("Timeout waiting for Primer SDK to initialize on window")):setTimeout(o,50)};o()})}(),h=!0}catch(e){throw l=null,e}var e,t})(),l}function m(...e){const t={};for(const n of e)if(n&&"object"==typeof n)for(const e in n)Object.prototype.hasOwnProperty.call(n,e)&&("object"!=typeof n[e]||Array.isArray(n[e])||null===n[e]?t[e]=n[e]:t[e]=m(t[e]||{},n[e]));return t}function f(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substr(2,5)}`}function y(e){return new Promise(t=>setTimeout(t,e))}var C;e.PaymentMethod=void 0,(C=e.PaymentMethod||(e.PaymentMethod={})).GOOGLE_PAY="GOOGLE_PAY",C.APPLE_PAY="APPLE_PAY",C.PAYPAL="PAYPAL",C.PAYMENT_CARD="PAYMENT_CARD";const g="0.6.3",E={BASE_URL:"https://billing.funnelfox.com",REGION:"default",SANDBOX:!1,REQUEST_TIMEOUT:3e4,RETRY_ATTEMPTS:3,RETRY_BASE_DELAY:1e3},M={SUCCESS:"success",ERROR:"error",STATUS_CHANGE:"status-change",DESTROY:"destroy",INPUT_ERROR:"input-error",LOADER_CHANGE:"loader-change",METHOD_RENDER:"method-render",METHOD_RENDER_ERROR:"method-render-error",START_PURCHASE:"start-purchase",PURCHASE_FAILURE:"purchase-failure",PURCHASE_COMPLETED:"purchase-completed",PURCHASE_CANCELLED:"purchase-cancelled",METHODS_AVAILABLE:"methods-available"},w="/v1/checkout/create_client_session",S="/v1/checkout/update_client_session",P="/v1/checkout/create_payment",v="/v1/checkout/resume_payment",I="/v1/checkout/one_click",R="/v1/checkout/create_simple_client_session",k={SDK_ERROR:"SDK_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",API_ERROR:"API_ERROR",PRIMER_ERROR:"PRIMER_ERROR",CHECKOUT_ERROR:"CHECKOUT_ERROR",CONFIGURATION_ERROR:"CONFIGURATION_ERROR",NETWORK_ERROR:"NETWORK_ERROR"},b=[...[e.PaymentMethod.GOOGLE_PAY,e.PaymentMethod.APPLE_PAY,e.PaymentMethod.PAYPAL],...[e.PaymentMethod.PAYMENT_CARD]],A={input:{error:{borderColor:"rgb(227, 47, 65)"},base:{borderWidth:"1px",borderStyle:"solid",borderColor:"rgb(0 0 0 / 10%)",height:"36px",paddingHorizontal:10,borderRadius:"6px"}}};A.input.base.paddingHorizontal,A.input.base.paddingHorizontal;const L=[e.PaymentMethod.APPLE_PAY,e.PaymentMethod.GOOGLE_PAY,e.PaymentMethod.PAYPAL,e.PaymentMethod.PAYMENT_CARD],_={[e.PaymentMethod.APPLE_PAY]:{buttonStyle:"black"},[e.PaymentMethod.PAYPAL]:{buttonColor:"gold",buttonShape:"pill",buttonLabel:"pay",buttonSize:"large",buttonHeight:54,paymentFlow:"PREFER_VAULT"},[e.PaymentMethod.GOOGLE_PAY]:{buttonColor:"black",buttonSizeMode:"fill",buttonType:"pay"}},D={billingOptions:{requiredBillingContactFields:["emailAddress"]},shippingOptions:{requiredShippingContactFields:["emailAddress"]}};class T{constructor(){this.isInitialized=!1,this.destroyCallbacks=[],this.currentHeadless=null,this.availableMethods=[],this.paymentMethodsInterfaces=[]}isPrimerAvailable(){return"undefined"!=typeof window&&window.Primer&&"function"==typeof window.Primer?.createHeadless}async ensurePrimerLoaded(e){if(!this.isPrimerAvailable())try{await p(e)}catch(e){throw new a("Failed to load Primer SDK",e)}}ensurePrimerAvailable(){if(!this.isPrimerAvailable())throw new a("Primer SDK not found. Please include the Primer SDK script before initializing FunnefoxSDK.")}async createHeadlessCheckout(e,t){return await this.ensurePrimerLoaded(),this.currentHeadless=T.headlessManager.getOrCreate(e,t),this.currentHeadless}disableButtons(e){if(this.paymentMethodsInterfaces)for(const t of this.paymentMethodsInterfaces)t.setDisabled(e)}async renderButton(e,{htmlNode:t,onMethodRenderError:n,onMethodRender:r}){let o;if(await this.ensurePrimerLoaded(),!this.currentHeadless)throw new a("Headless checkout not found");try{const n=await this.currentHeadless,a=await n.createPaymentMethodManager(e);if(!a)throw new Error("Payment method manager is not available");const i=document.createElement("div");i.className=f("funnefox-primer-button-wrapper");const s=document.createElement("style");document.head.appendChild(s);const d=s.sheet;return d&&(d.insertRule(`\n .${i.className} {\n width: 100% !important;\n }\n `),d.insertRule(`\n .${i.className} button {\n height: 54px !important;\n border-radius: 28px !important;\n }\n `)),t.appendChild(i),o=a.createButton(),await o.render(i,{}),this.destroyCallbacks.push(()=>o.clean()),r(e),{setDisabled:e=>{o.setDisabled(e)},destroy:()=>{s.remove(),o.clean()}}}catch(t){throw n(e),new a("Failed to initialize Primer checkout",t)}}async initMethod(t,n,r){try{if(t===e.PaymentMethod.PAYMENT_CARD){if(!r.cardElements||!r.onSubmit||!r.onInputChange)throw new a("Card elements, onSubmit, and onInputChange are required for PAYMENT_CARD method");const e=await this.renderCardCheckoutWithElements(r.cardElements,{onSubmit:r.onSubmit,onInputChange:r.onInputChange,onMethodRenderError:r.onMethodRenderError,onMethodRender:r.onMethodRender});return this.paymentMethodsInterfaces.push(e),e}{const e=await this.renderButton(t,{htmlNode:n,onMethodRenderError:r.onMethodRenderError,onMethodRender:r.onMethodRender});return this.paymentMethodsInterfaces.push(e),e}}catch(e){throw new a("Failed to initialize Primer checkout",e)}}async renderCardCheckoutWithElements(t,{onSubmit:n,onInputChange:r,onMethodRenderError:o,onMethodRender:i}){try{if(!this.currentHeadless)throw new a("Headless checkout not found");const o=await this.currentHeadless,s=await o.createPaymentMethodManager("PAYMENT_CARD");if(!s)throw new Error("Payment method manager is not available");const{cardNumberInput:d,expiryInput:c,cvvInput:l}=s.createHostedInputs(),h=async()=>{if(!s)return!1;const{valid:e,validationErrors:t}=await s.validate(),n=t.find(e=>"cardholderName"===e.name);return u("cardholderName",n?.message||null),e},u=(e,t)=>{r(e,t)},p=e=>t=>{const n=t;n.submitted&&u(e,n.error)},m=async e=>{s.setCardholderName(e.target.value),u("cardholderName",null)};t.cardholderName?.addEventListener("input",m),d.addEventListener("change",p("cardNumber")),c.addEventListener("change",p("expiryDate")),l.addEventListener("change",p("cvv"));const f=async()=>{if(await h())try{n(!0),await s.submit()}catch(e){throw new a("Failed to submit payment",e)}finally{n(!1)}};t.button?.addEventListener("click",f),await Promise.all([d.render(t.cardNumber,{placeholder:"1234 1234 1234 1234",ariaLabel:"Card number",style:A}),c.render(t.expiryDate,{placeholder:"MM/YY",ariaLabel:"Expiry date",style:A}),l.render(t.cvv,{placeholder:"123",ariaLabel:"CVV",style:A})]);const y=()=>{s.removeHostedInputs(),t.cardholderName?.removeEventListener("change",m),t.button?.removeEventListener("click",f)};return this.destroyCallbacks.push(y),i(e.PaymentMethod.PAYMENT_CARD),{setDisabled:e=>{d.setDisabled(e),c.setDisabled(e),l.setDisabled(e),t.button&&(t.button.disabled=e),t.cardholderName&&(t.cardholderName.disabled=e)},submit:()=>f(),destroy:()=>{this.destroyCallbacks=this.destroyCallbacks.filter(e=>e!==y),y()}}}catch(t){throw o(e.PaymentMethod.PAYMENT_CARD),new a("Failed to initialize Primer checkout",t)}}async initializeHeadlessCheckout(e,t){await this.createHeadlessCheckout(e,{...t,onTokenizeSuccess:this.wrapTokenizeHandler(t.onTokenizeSuccess),onResumeSuccess:this.wrapResumeHandler(t.onResumeSuccess),onAvailablePaymentMethodsLoad:this.wrapAvailablePaymentMethodsLoadHandler(t.onAvailablePaymentMethodsLoad)})}async renderCheckout(t,n,r){const{cardElements:o,paymentButtonElements:a,container:i,onSubmit:s,onInputChange:d,onMethodRender:c,onMethodRenderError:l,onMethodsAvailable:h}=r;await this.initializeHeadlessCheckout(t,n),h?.(this.availableMethods),await Promise.all(this.availableMethods.map(t=>{if(t===e.PaymentMethod.PAYMENT_CARD)return this.initMethod(t,i,{cardElements:o,onSubmit:s,onInputChange:d,onMethodRender:c,onMethodRenderError:l});{const n={[e.PaymentMethod.PAYPAL]:a.paypal,[e.PaymentMethod.GOOGLE_PAY]:a.googlePay,[e.PaymentMethod.APPLE_PAY]:a.applePay}[t];return this.initMethod(t,n,{onMethodRender:c,onMethodRenderError:l})}})),this.isInitialized=!0}wrapTokenizeHandler(e){return async(t,n)=>{try{await e(t,n)}catch(e){console.error("Error in tokenize handler:",e),n.handleFailure("Payment processing failed. Please try again.")}}}wrapResumeHandler(e){return async(t,n)=>{try{await e(t,n)}catch(e){console.error("Error in resume handler:",e),n.handleFailure("Payment processing failed. Please try again.")}}}wrapAvailablePaymentMethodsLoadHandler(t){return n=>{let r=!1;if(this.availableMethods=b.filter(t=>n.some(n=>(n.type===e.PaymentMethod.APPLE_PAY&&(r=!0),n.type===t))),r&&(this.availableMethods=this.availableMethods.filter(t=>t!==e.PaymentMethod.GOOGLE_PAY)),0===this.availableMethods.length)throw new a("No allowed payment methods found");t?.(this.availableMethods)}}async destroy(){if(this.currentHeadless&&(T.headlessManager.remove(this.currentHeadless),this.currentHeadless=null),this.destroyCallbacks)try{Promise.all(this.destroyCallbacks.map(e=>e()))}catch(e){console.warn("Error destroying Primer checkout:",e)}this.destroyCallbacks=[],this.isInitialized=!1}createHandlers(e){return{handleSuccess:()=>{e.onSuccess&&e.onSuccess()},handleFailure:t=>{e.onError&&e.onError(new Error(t))},continueWithNewClientToken:t=>{e.onActionRequired&&e.onActionRequired(t)}}}getCurrentCheckout(){return this.destroyCallbacks}isActive(){return this.isInitialized&&this.destroyCallbacks.length>0}validateContainer(e){const t=document.querySelector(e);if(!t)throw new a(`Checkout container not found: ${e}`);return"none"===window.getComputedStyle(t).display&&console.warn("Checkout container is hidden, this may cause display issues"),t}}T.headlessManager=new class{constructor(){this.cache=new Map,this.queue=Promise.resolve()}generateKey(e,t){const n={paymentHandling:t.paymentHandling,apiVersion:t.apiVersion,style:t.style,card:t.card,applePay:t.applePay,paypal:t.paypal,googlePay:t.googlePay};return`${e}:${JSON.stringify(n)}`}getOrCreate(e,t){const n=this.generateKey(e,t),r=this.cache.get(n);if(r)return r;const o=this.queue,i=(async()=>{await o;const r=m({paymentHandling:"MANUAL",apiVersion:"2.4"},t);try{const t=await window.Primer.createHeadless(e,r),n=await t;return await n.start(),n}catch(e){throw this.cache.delete(n),new a("Failed to create Primer headless checkout",e)}})();return this.cache.set(n,i),this.queue=i.catch(()=>{}),i}remove(e){for(const[t,n]of this.cache.entries())if(n===e){this.cache.delete(t);break}}clear(){this.cache.clear()}};class x{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.orgId=e.orgId,this.timeout=e.timeout||3e4,this.retryAttempts=e.retryAttempts||3}async request(e,t={}){const n=`${this.baseUrl}/${this.orgId}${e}`,r={method:"GET",headers:{"Content-Type":"application/json","X-SDK-Version":g,...t.headers||{}},...t};try{return await async function(e,t=3,n=1e3){let r;for(let o=1;o<=t;o++)try{return await e()}catch(e){if(r=e,o===t)throw r;const a=n*Math.pow(2,o-1);await y(a)}throw r}(async()=>await function(e,t,n="Operation timed out"){const r=new Promise((e,r)=>{setTimeout(()=>r(new Error(n)),t)});return Promise.race([e,r])}(this._makeRequest(n,r),this.timeout,"Request timed out"),this.retryAttempts)}catch(e){if(e instanceof Error&&"APIError"===e.name)throw e;throw new s("Network request failed",e)}}async _makeRequest(e,t){let n,r;try{n=await fetch(e,t)}catch(e){if(e instanceof Error&&"NetworkError"===e.name)throw e;throw new s("Network request failed",e)}try{r=await n.json()}catch{throw new o("Invalid JSON response",n.status,{})}if(!n.ok){const e=r,t=e.error?.[0]?.msg||"Failed to create payment";throw new o(t,n.status,{response:r})}return r}async createClientSession(e){const t={region:e.region||"default",integration_type:"primer",pp_ident:e.priceId,external_id:e.externalId,email_address:e.email,client_metadata:e.clientMetadata||{}};return void 0!==e.countryCode&&(t.country_code=e.countryCode),await this.request(w,{method:"POST",body:JSON.stringify(t)})}async updateClientSession(e){const t={order_id:e.orderId,client_token:e.clientToken,pp_ident:e.priceId,client_metadata:e.clientMetadata||{}};return await this.request(S,{method:"POST",body:JSON.stringify(t)})}async createPayment(e){const t={order_id:e.orderId,payment_method_token:e.paymentMethodToken,client_metadata:e.clientMetadata||{}};return await this.request(P,{method:"POST",body:JSON.stringify(t)})}async resumePayment(e){const t={order_id:e.orderId,resume_token:e.resumeToken};return await this.request(v,{method:"POST",body:JSON.stringify(t)})}processSessionResponse(e){if("error"===e.status){const t=e.error?.[0];throw new o(t?.msg||"Session creation failed",null,{errorCode:t?.code,errorType:t?.type,requestId:e.req_id,response:e})}const t=e.data;return{type:"session_created",orderId:t.order_id,clientToken:t.client_token}}processPaymentResponse(e){if("error"===e.status){const t=e.error?.[0];throw new o(t?.msg||"Payment request failed",null,{errorCode:t?.code,errorType:t?.type,response:e})}const t=e.data;if(t.action_required_token)return{type:"action_required",orderId:t.order_id,clientToken:t.action_required_token};if(t.checkout_status)switch(t.checkout_status){case"succeeded":return{type:"success",orderId:t.order_id,status:"succeeded"};case"failed":throw new o(t.failed_message_for_user||"Payment failed",null,{response:e});case"cancelled":throw new o("Payment was cancelled by user",null,{response:e});case"processing":return{type:"processing",orderId:t.order_id,status:"processing"};default:throw new o(`Unhandled checkout status: ${t.checkout_status}`,null,{response:e})}throw new o("Invalid payment response format",null,{response:e})}async oneClick(e){return await this.request(I,{method:"POST",body:JSON.stringify(e)})}async createSimpleClientSession(e){return await this.request(R,{method:"POST",body:JSON.stringify({region:"default",integration_type:"primer",...e})})}}"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent=".ff-sdk-loader-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255);\n z-index: 2;\n}\n\n.ff-sdk-loader {\n width: 24px;\n height: 24px;\n border: 4px solid #e32f41;\n border-top: 4px solid transparent;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n }");const N='<div class="ff-sdk-loader-container">\n <div class="ff-sdk-loader"></div>\n</div>\n',O={loaderContainer:".ff-sdk-loader-container"};var z,j="https://js.stripe.com/v3",H=/^https:\/\/js\.stripe\.com\/v3\/?(\?.*)?$/,U=function(e){var t=document.createElement("script");t.src="".concat(j).concat("");var n=document.head||document.body;if(!n)throw new Error("Expected document.body not to be null. Stripe.js requires a <body> element.");return n.appendChild(t),t},q=null,Y=null,F=null,B=function(e){return null!==q?q:(q=new Promise(function(t,n){if("undefined"!=typeof window&&"undefined"!=typeof document)if(window.Stripe)t(window.Stripe);else try{var r=function(){for(var e=document.querySelectorAll('script[src^="'.concat(j,'"]')),t=0;t<e.length;t++){var n=e[t];if(H.test(n.src))return n}return null}();if(r&&e);else if(r){if(r&&null!==F&&null!==Y){var o;r.removeEventListener("load",F),r.removeEventListener("error",Y),null===(o=r.parentNode)||void 0===o||o.removeChild(r),r=U()}}else r=U();F=function(e,t){return function(){window.Stripe?e(window.Stripe):t(new Error("Stripe.js not available"))}}(t,n),Y=function(e){return function(){e(new Error("Failed to load Stripe.js"))}}(n),r.addEventListener("load",F),r.addEventListener("error",Y)}catch(e){return void n(e)}else t(null)})).catch(function(e){return q=null,Promise.reject(e)})},G=!1,Q=function(){return z||(z=B(null).catch(function(e){return z=null,Promise.reject(e)}))};Promise.resolve().then(function(){return Q()}).catch(function(e){G||console.warn(e)});"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent=".ff-sdk-error-container {\n background-color: #d1000033;\n color: #d10000;\n font-size: 14px;\n padding: 16px 12px;\n border-radius: 8px;\n}");const Z='<div class="ff-sdk-error-container">\n <p class="ff-sdk-error-message">The payment form didn’t load correctly.</p>\n <p>Please refresh the page to try again.</p>\n <p>If the problem persists, please contact support.</p>\n <p class="ff-sdk-error-request-id"></p>\n</div>\n',$={errorRequestId:".ff-sdk-error-request-id"};class V extends t{constructor(e){super(),this.counter=0,this.radarSessionId=null,this.handleInputChange=(e,t)=>{this.emit(M.INPUT_ERROR,{name:e,error:t})},this.handleMethodRender=e=>{this.emit(M.METHOD_RENDER,e)},this.handleMethodRenderError=e=>{this.emit(M.METHOD_RENDER_ERROR,e)},this.handleSubmit=e=>{this.onLoaderChangeWithRace(e),this._setState(e?"processing":"ready")},this.handleTokenizeSuccess=async(e,t)=>{if(this.orderId)try{this.onLoaderChangeWithRace(!0),this._setState("processing");const n=await this.radarSessionId,r=await this.apiClient.createPayment({orderId:this.orderId,paymentMethodToken:e.token,clientMetadata:{radarSessionId:n}}),o=this.apiClient.processPaymentResponse(r);await this._processPaymentResult(o,t)}catch(e){this._setState("error"),this.emit(M.PURCHASE_FAILURE,new Error(e.message||"Payment processing failed")),t.handleFailure(e.message||"Payment processing failed")}finally{this.onLoaderChangeWithRace(!1),this._setState("ready")}else t.handleFailure("Order ID not found or checkout has been destroyed")},this.handleResumeSuccess=async(e,t)=>{if(this.orderId)try{this.onLoaderChangeWithRace(!0),this._setState("processing");const n=await this.apiClient.resumePayment({orderId:this.orderId,resumeToken:e.resumeToken}),r=this.apiClient.processPaymentResponse(n);await this._processPaymentResult(r,t)}catch(e){this._setState("error"),this.emit(M.PURCHASE_FAILURE,new Error(e.message||"Payment processing failed")),t.handleFailure(e.message||"Payment processing failed")}finally{this.emit(M.PURCHASE_COMPLETED),this.onLoaderChangeWithRace(!1),this._setState("ready")}else t.handleFailure("Order ID not found or checkout has been destroyed")},this.handleMethodsAvailable=e=>{this.emit(M.METHODS_AVAILABLE,e)},this.onLoaderChangeWithRace=e=>{const t=!!(e?++this.counter:--this.counter);this.primerWrapper.disableButtons(t),this.emit(M.LOADER_CHANGE,t)},this.id=f("checkout_"),this.orgId=e.orgId,this.baseUrl=e.baseUrl,this.region=e.region,this.checkoutConfig={...e.checkoutConfig},this.callbacks={onSuccess:this.checkoutConfig.onSuccess,onError:this.checkoutConfig.onError,onStatusChange:this.checkoutConfig.onStatusChange,onDestroy:this.checkoutConfig.onDestroy},delete this.checkoutConfig?.onSuccess,delete this.checkoutConfig?.onError,delete this.checkoutConfig?.onStatusChange,delete this.checkoutConfig?.onDestroy,this.state="initializing",this.orderId=null,this.clientToken=null,this.primerWrapper=new T,this.isDestroyed=!1,this._setupCallbackBridges()}_setupCallbackBridges(){this.callbacks.onSuccess&&this.on(M.SUCCESS,this.callbacks.onSuccess),this.callbacks.onError&&this.on(M.ERROR,this.callbacks.onError),this.callbacks.onStatusChange&&this.on(M.STATUS_CHANGE,this.callbacks.onStatusChange),this.callbacks.onDestroy&&this.on(M.DESTROY,this.callbacks.onDestroy)}removeAllListeners(){return super.removeAllListeners()}async initialize(){try{return this.showInitializingLoader(),this._setState("initializing"),await this.createSession(),await this._initializePrimerCheckout(),this._setState("ready"),this.checkoutConfig?.onInitialized?.(),this}catch(e){throw this._setState("error"),((e,t)=>{const n=document.querySelector(e);if(n&&(n.innerHTML=Z,t)){const e=n.querySelector($.errorRequestId);e&&(e.textContent=`Request ID: ${t}`)}})(this.checkoutConfig.container,e?.response?.req_id),this.emit(M.ERROR,e),e}finally{this.hideInitializingLoader()}}async createSession(){this.apiClient=new x({baseUrl:this.baseUrl||E.BASE_URL,orgId:this.orgId,timeout:E.REQUEST_TIMEOUT,retryAttempts:E.RETRY_ATTEMPTS});const e={priceId:this.checkoutConfig.priceId,externalId:this.checkoutConfig.customer.externalId,email:this.checkoutConfig.customer.email,region:this.region||E.REGION,clientMetadata:this.checkoutConfig.clientMetadata,countryCode:this.checkoutConfig.customer.countryCode},t=[this.orgId,this.checkoutConfig.priceId,this.checkoutConfig.customer.externalId,this.checkoutConfig.customer.email].join("-");let n;const r=V.sessionCache.get(t);if(r)n=await r;else{const r=this.apiClient.createClientSession(e).then(e=>(e.data?.stripe_public_key&&function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];G=!0;var r=Date.now();return Q().then(function(e){return function(e,t,n){if(null===e)return null;var r=e.apply(void 0,t);return function(e,t){e&&e._registerWrapper&&e._registerWrapper({name:"stripe-js",version:"4.6.0",startTime:t})}(r,n),r}(e,t,r)})}(e.data?.stripe_public_key).then(e=>{this.radarSessionId=e.createRadarSession().then(e=>e?.radarSession?.id).catch(()=>"")}),this.isCollectingApplePayEmail=!!e.data?.collect_apple_pay_email,e));V.sessionCache.set(t,r),n=await r}const o=this.apiClient.processSessionResponse(n);this.orderId=o.orderId,this.clientToken=o.clientToken}convertCardSelectorsToElements(e,t){const n=t.querySelector(e.cardNumber),r=t.querySelector(e.expiryDate),o=t.querySelector(e.cvv),a=t.querySelector(e.cardholderName),s=t.querySelector(e.button);if(!(n&&r&&o&&s))throw new i("Required card input elements not found in container");return{cardNumber:n,expiryDate:r,cvv:o,cardholderName:a,button:s}}convertPaymentButtonSelectorsToElements(e){const t=document.querySelector(e.paypal),n=document.querySelector(e.googlePay),r=document.querySelector(e.applePay);if(!t||!n||!r)throw new i("Required payment button elements not found in container");return{paypal:t,googlePay:n,applePay:r}}async _initializePrimerCheckout(){const e=this.getContainer();if(!e)throw new i(`Checkout container not found: ${this.checkoutConfig.container}`);let t,n,r;if(this.checkoutConfig.cardSelectors&&this.checkoutConfig.paymentButtonSelectors)this.checkoutConfig.paymentMethodOrder&&console.warn("paymentMethodOrder is using only for default skin and will be ignored if you are using custom checkout"),t=this.convertCardSelectorsToElements(this.checkoutConfig.cardSelectors,e),n=this.convertPaymentButtonSelectorsToElements(this.checkoutConfig.paymentButtonSelectors),r=this.getCheckoutOptions({});else{this.checkoutConfig.paymentMethodOrder=this.checkoutConfig.paymentMethodOrder||L;const e=await this.getDefaultSkinCheckoutOptions();if(!e.cardElements||!e.paymentButtonElements)throw new i("Default skin must provide cardSelectors and paymentButtonSelectors");t=e.cardElements,n=e.paymentButtonElements,r=this.getCheckoutOptions(e)}r=m(r,this.isCollectingApplePayEmail?{applePay:D}:{}),await this.primerWrapper.renderCheckout(this.clientToken,r,{container:e,cardElements:t,paymentButtonElements:n,onSubmit:this.handleSubmit,onInputChange:this.handleInputChange,onMethodRender:this.handleMethodRender,onMethodsAvailable:this.handleMethodsAvailable,onMethodRenderError:this.handleMethodRenderError})}async _processPaymentResult(e,t){switch(e.orderId&&(this.orderId=e.orderId),e.type){case"success":this._setState("completed"),this.emit(M.SUCCESS,{orderId:e.orderId,status:e.status}),t.handleSuccess();break;case"action_required":this._setState("action_required"),this.clientToken=e.clientToken,t.continueWithNewClientToken(e.clientToken);break;case"processing":this._setState("processing"),setTimeout(()=>{t.handleFailure("Payment is still processing. Please check back later.")},3e4);break;default:throw new i(`Unknown payment result type: ${e.type}`)}}getCheckoutOptions(e){let t=!1;return{...this.checkoutConfig,...e,onTokenizeSuccess:this.handleTokenizeSuccess,onResumeSuccess:this.handleResumeSuccess,onResumeError:e=>{e.stack?.includes("PROCESSOR_3DS")&&"RESUME_ERROR"===e.code&&e.message?.includes("fetch resume key")||this.emit(M.PURCHASE_FAILURE,e)},onCheckoutFail:e=>{this.emit(M.PURCHASE_FAILURE,e)},onTokenizeError:e=>{this.emit(M.PURCHASE_FAILURE,e)},onTokenizeStart:()=>{t=!0},onTokenizeShouldStart:e=>(this.emit(M.ERROR,void 0),this.emit(M.START_PURCHASE,e.paymentMethodType),!0),onPaymentMethodAction:e=>{switch(e){case"PAYMENT_METHOD_SELECTED":this.emit(M.ERROR,void 0);break;case"PAYMENT_METHOD_UNSELECTED":t||this.emit(M.PURCHASE_CANCELLED),t=!1}}}}async updatePrice(e,t){if(this._ensureNotDestroyed(),function(e,t){var n;if(0===(n=e,n?.trim()||"").length)throw new r(t,"must be a non-empty string",e)}(e,"priceId"),"processing"===this.state)throw new i("Cannot update price while payment is processing");try{this._setState("updating"),V.sessionCache.clear(),await this.apiClient.updateClientSession({orderId:this.orderId,clientToken:this.clientToken,priceId:e,clientMetadata:t}),this.checkoutConfig.priceId=e,this._setState("ready")}catch(e){throw this._setState("error"),this.emit(M.ERROR,e),e}}getStatus(){return{id:this.id,state:this.state,orderId:this.orderId,priceId:this.checkoutConfig.priceId,isDestroyed:this.isDestroyed}}async destroy(){if(!this.isDestroyed)try{V.sessionCache.clear(),await this.primerWrapper.destroy(),this._setState("destroyed"),this.orderId=null,this.clientToken=null,this.isDestroyed=!0,this.emit(M.DESTROY),this.removeAllListeners()}catch(e){console.warn("Error during checkout cleanup:",e)}}_setState(e){if(this.state!==e){const t=this.state;this.state=e,this.emit(M.STATUS_CHANGE,e,t)}}_ensureNotDestroyed(){if(this.isDestroyed)throw new i("Checkout instance has been destroyed")}getContainer(){return document.querySelector(this.checkoutConfig.container)}isInState(e){return this.state===e}isReady(){return"ready"===this.state&&!this.isDestroyed}isProcessing(){return["processing","action_required"].includes(this.state)}async getDefaultSkinCheckoutOptions(){const e=(await Promise.resolve().then(function(){return de})).default,t=await e(this.checkoutConfig);return this.on(M.INPUT_ERROR,t.onInputError),this.on(M.STATUS_CHANGE,t.onStatusChange),this.on(M.ERROR,e=>t.onError(e)),this.on(M.LOADER_CHANGE,t.onLoaderChange),this.on(M.DESTROY,t.onDestroy),this.on(M.SUCCESS,t.onSuccess),this.on(M.START_PURCHASE,t.onStartPurchase),this.on(M.PURCHASE_FAILURE,t.onPurchaseFailure),this.on(M.PURCHASE_COMPLETED,t.onPurchaseCompleted),this.on(M.METHODS_AVAILABLE,t.onMethodsAvailable),this.on(M.METHODS_AVAILABLE,this.hideInitializingLoader),t.getCheckoutOptions()}async getCardDefaultSkinCheckoutOptions(e){const t=new(0,(await Promise.resolve().then(function(){return ae})).default)(e,this.checkoutConfig);return t.init(),this.on(M.INPUT_ERROR,t.onInputError),this.on(M.METHOD_RENDER,t.onMethodRender),this.on(M.SUCCESS,t.onDestroy),this.on(M.DESTROY,t.onDestroy),t.getCheckoutOptions()}showInitializingLoader(){(e=>{const t=document.querySelector(e);t&&(t.innerHTML=N)})(this.checkoutConfig.container)}hideInitializingLoader(){(()=>{const e=document.querySelector(O.loaderContainer);e&&e.remove()})()}async initMethod(t,n,r){this._ensureNotDestroyed(),this.isReady()||await this.createSession(),r.onRenderSuccess&&this.on(M.METHOD_RENDER,r.onRenderSuccess),r.onRenderError&&this.on(M.METHOD_RENDER_ERROR,r.onRenderError),r.onLoaderChange&&this.on(M.LOADER_CHANGE,r.onLoaderChange),r.onPaymentSuccess&&this.on(M.SUCCESS,r.onPaymentSuccess),r.onPaymentFail&&this.on(M.PURCHASE_FAILURE,r.onPaymentFail),r.onPaymentCancel&&this.on(M.PURCHASE_CANCELLED,r.onPaymentCancel),r.onErrorMessageChange&&this.on(M.ERROR,r.onErrorMessageChange),r.onPaymentStarted&&this.on(M.START_PURCHASE,r.onPaymentStarted),r.onMethodsAvailable&&this.on(M.METHODS_AVAILABLE,r.onMethodsAvailable);let o=this.getCheckoutOptions(this.isCollectingApplePayEmail?{applePay:D}:{}),a={onMethodRender:this.handleMethodRender,onMethodRenderError:this.handleMethodRenderError};if(t===e.PaymentMethod.PAYMENT_CARD){const e=await this.getCardDefaultSkinCheckoutOptions(n);o=this.getCheckoutOptions({...e}),a={cardElements:e.cardElements,onSubmit:this.handleSubmit,onInputChange:this.handleInputChange,onMethodRender:this.handleMethodRender,onMethodRenderError:this.handleMethodRenderError}}await this.primerWrapper.initializeHeadlessCheckout(this.clientToken,o);const i=await this.primerWrapper.initMethod(t,n,a);return{...i,destroy:async()=>{await i.destroy(),await this.destroy()}}}}function K(e,t){const n=new URLSearchParams({message:t.message,code:t.code,timestamp:Date.now().toString(),sdk_version:g});t.req_id&&n.append("req_id",t.req_id);const r=`https://billing.funnelfox.com/sdk_report/${encodeURIComponent(e)}/crash?${n.toString()}`,o=new Image;o.src=r,o.style.display="none",document.body.appendChild(o)}V.sessionCache=new Map;let W=null;function J(e){W=e}function X(e,t){const{orgId:n,apiConfig:r}=e||{},o=n||W?.orgId;if(!o)throw new Error(`orgId is required. Pass it to ${t}() or call configure() first.`);return{orgId:o,baseUrl:r?.baseUrl||W?.baseUrl||E.BASE_URL,region:r?.region||W?.region||E.REGION}}async function ee(e){try{const{...t}=e,n=new T;await n.ensurePrimerLoaded();const r=X(e,"createCheckout"),o=new V({...r,checkoutConfig:{...t}});return await o.initialize(),o}catch(t){throw K(e.orgId,{message:t.message,code:t.code,req_id:t?.response?.req_id}),t}}async function te(e){const{priceId:t,externalId:n,email:r,clientMetadata:o,countryCode:a}=e,i=X(e,"createClientSession"),s=new x({baseUrl:i.baseUrl,orgId:i.orgId,timeout:E.REQUEST_TIMEOUT,retryAttempts:E.RETRY_ATTEMPTS}),d=await s.createClientSession({priceId:t,externalId:n,email:r,region:i.region,clientMetadata:o,countryCode:a});return s.processSessionResponse(d)}async function ne(t){try{const n=new x({baseUrl:t.baseUrl,orgId:t.orgId}),r=await n.createSimpleClientSession({countryCode:t.countryCode}),o=r?.data?.client_token;if(!o)throw new Error("Error creating simple client session");return await new Promise((t,n)=>{const r=new T;r.initializeHeadlessCheckout(o,{onTokenizeSuccess:()=>{},onResumeSuccess:()=>{},onAvailablePaymentMethodsLoad:e=>{t(e),r.destroy()},paypal:_[e.PaymentMethod.PAYPAL]}).catch(n)})}catch(e){throw K(t.orgId,{message:e.message,code:e.code,req_id:e?.response?.req_id}),e}}const re={configure:J,createCheckout:ee,createClientSession:te,initMethod:async function(t,n,r){try{const o=new V({orgId:r.orgId,baseUrl:r.baseUrl,checkoutConfig:{priceId:r.priceId,customer:{externalId:r.externalId,email:r.email},container:"",clientMetadata:r.meta,card:r.card,style:r.style,applePay:{..._[e.PaymentMethod.APPLE_PAY],...r.applePay||{}},paypal:{..._[e.PaymentMethod.PAYPAL],...r.paypal||{}},googlePay:{..._[e.PaymentMethod.GOOGLE_PAY],...r.googlePay||{}}}});return await o.initMethod(t,n,{onRenderSuccess:r.onRenderSuccess,onRenderError:r.onRenderError,onLoaderChange:r.onLoaderChange,onPaymentSuccess:r.onPaymentSuccess,onPaymentFail:r.onPaymentFail,onPaymentCancel:r.onPaymentCancel,onErrorMessageChange:r.onErrorMessageChange,onPaymentStarted:r.onPaymentStarted,onMethodsAvailable:r.onMethodsAvailable})}catch(e){throw K(r.orgId,{message:e.message,code:e.code,req_id:e?.response?.req_id}),e}},silentPurchase:async function(e){const{priceId:t,externalId:n,clientMetadata:r,orgId:a,baseUrl:i}=e,s=new x({baseUrl:i,orgId:a,timeout:E.REQUEST_TIMEOUT,retryAttempts:E.RETRY_ATTEMPTS});try{const e=await s.oneClick({pp_ident:t,external_id:n,client_metadata:r});if("success"!==e.status&&e.error.some(({code:e})=>"double_purchase"===e))throw new o("This product was already purchased");return"success"===e.status}catch(e){throw K(a,{message:e.message,code:e.code,req_id:e?.response?.req_id}),e}},getAvailablePaymentMethods:ne};"undefined"!=typeof window&&(window.Billing=re);"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent="/* Main container */\n.ff-skin-default {\n display: flex;\n flex-direction: column;\n text-align: left;\n gap: 8px;\n width: 100%;\n max-width: 400px;\n margin: 0 auto;\n color: #000000;\n}\n\n/* Payment method cards */\n.ff-payment-method-card {\n display: none;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n background-color: #ffffff;\n padding: 20px;\n transition: border-color 0.2s ease;\n height: auto;\n box-shadow: 0px 0px 10px 0px #eee;\n}\n\n.ff-payment-method-card.visible {\n display: block;\n}\n\n.payment-errors-container {\n background-color: #d1000033;\n color: #d10000;\n font-size: 14px;\n padding: 16px 12px;\n border-radius: 8px;\n}\n.payment-errors-container:empty {\n display: none;\n}\n\n/* Label wrapper */\n.ff-payment-method-label {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n cursor: pointer;\n width: 100%;\n}\n\n.ff-google-pay-header {\n align-items: center;\n}\n\n/* Custom radio button styling */\n.ff-payment-method-radio {\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n width: 24px;\n height: 24px;\n min-width: 24px;\n min-height: 24px;\n border: 1px solid #9e9e9e;\n border-radius: 50%;\n background-color: #ffffff;\n cursor: pointer;\n position: relative;\n margin: 0;\n flex-shrink: 0;\n transition: border-color 0.2s ease;\n}\n\n.ff-card-form-submit-button {\n display: block;\n cursor: pointer;\n width: 100%;\n padding: 16px 0;\n border-radius: 16px;\n background-color: #000000;\n color: #ffffff;\n border: none;\n font-size: 16px;\n margin: 12px 0 16px;\n}\n\n.ff-payment-method-radio:checked {\n border-color: #e32f41;\n background-color: #ffffff;\n}\n\n.ff-payment-method-radio:checked::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background-color: #e32f41;\n}\n\n/* Payment method content */\n.ff-payment-method-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-height: 0;\n height: 0;\n overflow: hidden;\n opacity: 0;\n transition:\n opacity 0.3s ease,\n margin-top 0.3s ease;\n margin-top: 0;\n}\n\n.ff-payment-method-card.expanded .ff-payment-method-content {\n max-height: 2000px;\n height: auto;\n opacity: 1;\n margin-top: 16px;\n}\n.ff-payment-method-card.expanded .ff-payment-method-label {\n margin-bottom: 16px;\n}\n\n/* Payment method header */\n.ff-payment-method-header {\n display: flex;\n align-items: center;\n}\n\n/* Google Pay Logo */\n.ff-google-pay-logo {\n display: flex;\n align-items: center;\n gap: 4px;\n font-weight: 500;\n font-size: 18px;\n}\n.ff-google-pay-logo img {\n height: 38px;\n}\n\n/* Payment features list */\n.ff-payment-features {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.ff-payment-feature {\n display: flex;\n align-items: baseline;\n text-align: left;\n gap: 8px;\n}\n\n.ff-checkmark-icon {\n width: 20px;\n height: 20px;\n min-width: 20px;\n color: #e32f41;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.ff-payment-feature span {\n color: #333333;\n font-size: 14px;\n line-height: 1.5;\n}\n\n/* Google Pay button container */\n.ff-google-pay-button-container {\n display: flex;\n justify-content: center;\n}\n\n/* Security message */\n.ff-security-message {\n text-align: center;\n color: #999999;\n font-size: 14px;\n padding: 0;\n margin: 0\n}\n\n/* Card logos container */\n.ff-card-logos {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n/* Card form container */\n.ff-card-form-container {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.loader-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255);\n z-index: 2;\n}\n\n.payment-button-loader {\n position: relative;\n height: 50px;\n}\n\n.loader {\n width: 24px;\n height: 24px;\n border: 4px solid #e32f41;\n border-top: 4px solid transparent;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .ff-payment-method-card {\n padding: 16px;\n }\n\n .ff-payment-method-label {\n gap: 12px;\n }\n\n .ff-card-logos {\n gap: 8px;\n }\n}\n\n.ff-payment-container {\n position: relative;\n}\n\n.success {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n}\n");"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent="\n\n.ff-card-form-label {\n display: block;\n font-size: 16px;\n margin-bottom: 5px;\n }\n \n .card-form-row {\n display: flex;\n flex-direction: row;\n gap: 10px;\n }\n \n .ff-card-form-cardholder-input {\n margin: 0 0 3px;\n padding-left: 10px;\n padding-right: 10px;\n box-sizing: border-box;\n height: 36px;\n width: 100%;\n font-size: 1rem;\n background-color: transparent;\n border: 1px solid rgb(0 0 0 / 10%);\n border-radius: 6px;\n transition: all 0.3s ease;\n box-shadow: none;\n outline: none;\n }\n .ff-card-form-cardholder-input.error {\n border-color: #e32f41;\n }\n \n .errorContainer:not(:empty) {\n color: #d10000;\n font-size: 16px;\n line-height: 1;\n margin: 0 0 10px;\n }\n\n #cvvInput {\n position: relative;\n }\n \n #cvvInput > svg {\n z-index: 1;\n position: absolute;\n top: 5px;\n right: 5px;\n width: 26px;\n height: 26px;\n }");class oe{constructor(e,t){if(this.onInputError=e=>{const{name:t,error:n}=e,r=this.getCardInputElements(),o={cardNumber:r.cardNumber.parentElement,expiryDate:r.expiryDate.parentElement,cvv:r.cvv.parentElement,cardholderName:r.cardholderName?.parentElement},a=o[t]?.querySelector(".errorContainer");a&&(a.textContent=n||""),"cardholderName"===t&&(n?r.cardholderName?.classList?.add("error"):r.cardholderName?.classList?.remove("error"))},this.onMethodRender=()=>{this.containerEl.style.display="block"},this.onDestroy=()=>{this.containerEl.innerHTML&&(this.containerEl.innerHTML="")},!e)throw new Error("Container element not found");this.containerEl=e,this.checkoutConfig=t,this.containerEl.style.display="none"}wireCardInputs(){const e=this.containerEl.querySelector("#cardNumberInput"),t=this.containerEl.querySelector("#expiryInput"),n=this.containerEl.querySelector("#cvvInput"),r=!!this.checkoutConfig?.card?.cardholderName?.required;let o;if(r?o=this.containerEl.querySelector("#cardHolderInput"):this.containerEl.querySelector("#cardHolderInput").parentElement.style.display="none",!e||!t||!n||r&&!o)throw new Error("One or more card input elements are missing in the default skin");this.cardInputElements={cardNumber:e,expiryDate:t,cvv:n,cardholderName:o}}async init(){this.containerEl.insertAdjacentHTML("afterbegin",'<div>\n <label class="ff-card-form-label" for="cardNumberInput">Card number</label>\n <div id="cardNumberInput"></div>\n <div class="errorContainer"></div>\n</div>\n<div class="card-form-row">\n <div>\n <label class="ff-card-form-label" for="expiryInput">Expiration date</label>\n <div id="expiryInput"></div>\n <div class="errorContainer"></div>\n </div>\n <div>\n <label class="ff-card-form-label" for="cvvInput">Security code</label>\n <div id="cvvInput">\n <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">\n <rect width="200" height="200" fill="transparent"/>\n <g clip-path="url(#clip0_0_1)">\n <path d="M157.555 23C168.279 23.0002 177 31.7394 177 42.4854V80.5889C171.946 72.0151 164.749 64.8558 156.146 59.8457H166.394V42.4854C166.393 37.6004 162.43 33.6291 157.555 33.6289H27.4453C22.5704 33.6291 18.6066 37.6004 18.6064 42.4854V59.8457H97.8535C88.9153 65.0512 81.4954 72.5771 76.4189 81.5986H18.6064V127.515C18.6066 132.4 22.5704 136.371 27.4453 136.371H75.3281C77.2742 140.177 79.6285 143.739 82.333 147H27.4453C16.7215 147 8.00019 138.261 8 127.515V42.4854C8.0002 31.7394 16.7215 23.0002 27.4453 23H157.555Z" fill="#93939A"/>\n <mask id="path-2-outside-1_0_1" maskUnits="userSpaceOnUse" x="68.5012" y="52.0311" width="135" height="135" fill="black">\n <rect fill="white" x="68.5012" y="52.0311" width="135" height="135"/>\n <path d="M190.242 160.457L170.136 140.351C166.533 145.552 162.023 150.063 156.821 153.666L176.927 173.772C178.693 175.538 181.088 176.53 183.585 176.53C186.082 176.53 188.477 175.538 190.242 173.772C192.008 172.007 193 169.612 193 167.115C193 164.618 192.008 162.223 190.242 160.457ZM126.436 157.901C116.955 157.901 107.688 155.089 99.8048 149.822C91.922 144.555 85.7781 137.069 82.15 128.31C78.5219 119.551 77.5727 109.913 79.4222 100.614C81.2718 91.3158 85.8371 82.7746 92.5409 76.0708C99.2447 69.367 107.786 64.8017 117.084 62.9521C126.383 61.1026 136.021 62.0518 144.78 65.6799C153.539 69.308 161.025 75.4519 166.292 83.3347C171.559 91.2175 174.371 100.485 174.371 109.966C174.371 122.679 169.32 134.871 160.331 143.861C151.341 152.85 139.149 157.901 126.436 157.901ZM163.719 109.966C163.719 102.592 161.532 95.3838 157.435 89.2527C153.339 83.1216 147.516 78.343 140.703 75.5212C133.891 72.6994 126.395 71.9611 119.162 73.3996C111.93 74.8382 105.287 78.389 100.073 83.6031C94.8591 88.8171 91.3083 95.4602 89.8697 102.692C88.4312 109.924 89.1695 117.421 91.9913 124.233C94.8131 131.046 99.5918 136.869 105.723 140.965C111.854 145.062 119.062 147.248 126.436 147.248C136.324 147.248 145.807 143.32 152.799 136.329C159.791 129.337 163.719 119.854 163.719 109.966ZM133.645 102.757C133.398 102.51 133.104 102.313 132.781 102.179C132.458 102.046 132.112 101.977 131.762 101.977C131.412 101.977 131.066 102.046 130.743 102.179C130.42 102.313 130.126 102.51 129.879 102.757L126.436 106.2L122.993 102.757C122.49 102.272 121.818 102.003 121.119 102.01C120.421 102.016 119.753 102.296 119.26 102.789C118.766 103.283 118.486 103.951 118.48 104.649C118.474 105.348 118.742 106.02 119.227 106.523L122.67 109.966L119.227 113.409C118.973 113.655 118.77 113.949 118.63 114.274C118.491 114.598 118.417 114.948 118.414 115.301C118.411 115.655 118.479 116.006 118.612 116.333C118.746 116.66 118.944 116.958 119.194 117.208C119.444 117.458 119.741 117.655 120.069 117.789C120.396 117.923 120.747 117.991 121.1 117.988C121.454 117.985 121.803 117.911 122.128 117.771C122.453 117.632 122.747 117.429 122.993 117.175L126.436 113.732L129.879 117.175C130.382 117.66 131.054 117.928 131.752 117.922C132.451 117.916 133.119 117.636 133.612 117.142C134.106 116.648 134.386 115.981 134.392 115.282C134.398 114.584 134.13 113.911 133.645 113.409L130.202 109.966L133.645 106.523C133.892 106.275 134.088 105.982 134.222 105.659C134.356 105.336 134.425 104.989 134.425 104.64C134.425 104.29 134.356 103.944 134.222 103.621C134.088 103.298 133.892 103.004 133.645 102.757ZM112.34 102.757C112.093 102.51 111.8 102.313 111.477 102.179C111.154 102.046 110.807 101.977 110.458 101.977C110.108 101.977 109.762 102.046 109.439 102.179C109.116 102.313 108.822 102.51 108.575 102.757L105.132 106.2L101.688 102.757C101.186 102.272 100.513 102.003 99.8151 102.01C99.1169 102.016 98.4489 102.296 97.9552 102.789C97.4614 103.283 97.1814 103.951 97.1753 104.649C97.1692 105.348 97.4377 106.02 97.9227 106.523L101.366 109.966L97.9227 113.409C97.6684 113.655 97.4655 113.949 97.326 114.274C97.1864 114.598 97.1129 114.948 97.1098 115.301C97.1068 115.655 97.1742 116.006 97.3081 116.333C97.442 116.66 97.6397 116.958 97.8897 117.208C98.1398 117.458 98.4371 117.655 98.7644 117.789C99.0917 117.923 99.4423 117.991 99.7959 117.988C100.15 117.985 100.499 117.911 100.824 117.771C101.149 117.632 101.443 117.429 101.688 117.175L105.132 113.732L108.575 117.175C109.077 117.66 109.75 117.928 110.448 117.922C111.146 117.916 111.814 117.636 112.308 117.142C112.802 116.648 113.082 115.981 113.088 115.282C113.094 114.584 112.826 113.911 112.34 113.409L108.897 109.966L112.34 106.523C112.588 106.275 112.784 105.982 112.918 105.659C113.052 105.336 113.121 104.989 113.121 104.64C113.121 104.29 113.052 103.944 112.918 103.621C112.784 103.298 112.588 103.004 112.34 102.757ZM151.506 109.966L154.949 106.523C155.434 106.02 155.703 105.348 155.697 104.649C155.691 103.951 155.41 103.283 154.917 102.789C154.423 102.296 153.755 102.016 153.057 102.01C152.359 102.003 151.686 102.272 151.184 102.757L147.74 106.2L144.297 102.757C143.795 102.272 143.122 102.003 142.424 102.01C141.726 102.016 141.058 102.296 140.564 102.789C140.07 103.283 139.79 103.951 139.784 104.649C139.778 105.348 140.046 106.02 140.531 106.523L143.974 109.966L140.531 113.409C140.277 113.655 140.074 113.949 139.935 114.274C139.795 114.598 139.722 114.948 139.719 115.301C139.715 115.655 139.783 116.006 139.917 116.333C140.051 116.66 140.248 116.958 140.498 117.208C140.748 117.458 141.046 117.655 141.373 117.789C141.7 117.923 142.051 117.991 142.405 117.988C142.758 117.985 143.108 117.911 143.433 117.771C143.757 117.632 144.051 117.429 144.297 117.175L147.74 113.732L151.184 117.175C151.686 117.66 152.359 117.928 153.057 117.922C153.755 117.916 154.423 117.636 154.917 117.142C155.41 116.648 155.691 115.981 155.697 115.282C155.703 114.584 155.434 113.911 154.949 113.409L151.506 109.966Z"/>\n </mask>\n <path d="M190.242 160.457L170.136 140.351C166.533 145.552 162.023 150.063 156.821 153.666L176.927 173.772C178.693 175.538 181.088 176.53 183.585 176.53C186.082 176.53 188.477 175.538 190.242 173.772C192.008 172.007 193 169.612 193 167.115C193 164.618 192.008 162.223 190.242 160.457ZM126.436 157.901C116.955 157.901 107.688 155.089 99.8048 149.822C91.922 144.555 85.7781 137.069 82.15 128.31C78.5219 119.551 77.5727 109.913 79.4222 100.614C81.2718 91.3158 85.8371 82.7746 92.5409 76.0708C99.2447 69.367 107.786 64.8017 117.084 62.9521C126.383 61.1026 136.021 62.0518 144.78 65.6799C153.539 69.308 161.025 75.4519 166.292 83.3347C171.559 91.2175 174.371 100.485 174.371 109.966C174.371 122.679 169.32 134.871 160.331 143.861C151.341 152.85 139.149 157.901 126.436 157.901ZM163.719 109.966C163.719 102.592 161.532 95.3838 157.435 89.2527C153.339 83.1216 147.516 78.343 140.703 75.5212C133.891 72.6994 126.395 71.9611 119.162 73.3996C111.93 74.8382 105.287 78.389 100.073 83.6031C94.8591 88.8171 91.3083 95.4602 89.8697 102.692C88.4312 109.924 89.1695 117.421 91.9913 124.233C94.8131 131.046 99.5918 136.869 105.723 140.965C111.854 145.062 119.062 147.248 126.436 147.248C136.324 147.248 145.807 143.32 152.799 136.329C159.791 129.337 163.719 119.854 163.719 109.966ZM133.645 102.757C133.398 102.51 133.104 102.313 132.781 102.179C132.458 102.046 132.112 101.977 131.762 101.977C131.412 101.977 131.066 102.046 130.743 102.179C130.42 102.313 130.126 102.51 129.879 102.757L126.436 106.2L122.993 102.757C122.49 102.272 121.818 102.003 121.119 102.01C120.421 102.016 119.753 102.296 119.26 102.789C118.766 103.283 118.486 103.951 118.48 104.649C118.474 105.348 118.742 106.02 119.227 106.523L122.67 109.966L119.227 113.409C118.973 113.655 118.77 113.949 118.63 114.274C118.491 114.598 118.417 114.948 118.414 115.301C118.411 115.655 118.479 116.006 118.612 116.333C118.746 116.66 118.944 116.958 119.194 117.208C119.444 117.458 119.741 117.655 120.069 117.789C120.396 117.923 120.747 117.991 121.1 117.988C121.454 117.985 121.803 117.911 122.128 117.771C122.453 117.632 122.747 117.429 122.993 117.175L126.436 113.732L129.879 117.175C130.382 117.66 131.054 117.928 131.752 117.922C132.451 117.916 133.119 117.636 133.612 117.142C134.106 116.648 134.386 115.981 134.392 115.282C134.398 114.584 134.13 113.911 133.645 113.409L130.202 109.966L133.645 106.523C133.892 106.275 134.088 105.982 134.222 105.659C134.356 105.336 134.425 104.989 134.425 104.64C134.425 104.29 134.356 103.944 134.222 103.621C134.088 103.298 133.892 103.004 133.645 102.757ZM112.34 102.757C112.093 102.51 111.8 102.313 111.477 102.179C111.154 102.046 110.807 101.977 110.458 101.977C110.108 101.977 109.762 102.046 109.439 102.179C109.116 102.313 108.822 102.51 108.575 102.757L105.132 106.2L101.688 102.757C101.186 102.272 100.513 102.003 99.8151 102.01C99.1169 102.016 98.4489 102.296 97.9552 102.789C97.4614 103.283 97.1814 103.951 97.1753 104.649C97.1692 105.348 97.4377 106.02 97.9227 106.523L101.366 109.966L97.9227 113.409C97.6684 113.655 97.4655 113.949 97.326 114.274C97.1864 114.598 97.1129 114.948 97.1098 115.301C97.1068 115.655 97.1742 116.006 97.3081 116.333C97.442 116.66 97.6397 116.958 97.8897 117.208C98.1398 117.458 98.4371 117.655 98.7644 117.789C99.0917 117.923 99.4423 117.991 99.7959 117.988C100.15 117.985 100.499 117.911 100.824 117.771C101.149 117.632 101.443 117.429 101.688 117.175L105.132 113.732L108.575 117.175C109.077 117.66 109.75 117.928 110.448 117.922C111.146 117.916 111.814 117.636 112.308 117.142C112.802 116.648 113.082 115.981 113.088 115.282C113.094 114.584 112.826 113.911 112.34 113.409L108.897 109.966L112.34 106.523C112.588 106.275 112.784 105.982 112.918 105.659C113.052 105.336 113.121 104.989 113.121 104.64C113.121 104.29 113.052 103.944 112.918 103.621C112.784 103.298 112.588 103.004 112.34 102.757ZM151.506 109.966L154.949 106.523C155.434 106.02 155.703 105.348 155.697 104.649C155.691 103.951 155.41 103.283 154.917 102.789C154.423 102.296 153.755 102.016 153.057 102.01C152.359 102.003 151.686 102.272 151.184 102.757L147.74 106.2L144.297 102.757C143.795 102.272 143.122 102.003 142.424 102.01C141.726 102.016 141.058 102.296 140.564 102.789C140.07 103.283 139.79 103.951 139.784 104.649C139.778 105.348 140.046 106.02 140.531 106.523L143.974 109.966L140.531 113.409C140.277 113.655 140.074 113.949 139.935 114.274C139.795 114.598 139.722 114.948 139.719 115.301C139.715 115.655 139.783 116.006 139.917 116.333C140.051 116.66 140.248 116.958 140.498 117.208C140.748 117.458 141.046 117.655 141.373 117.789C141.7 117.923 142.051 117.991 142.405 117.988C142.758 117.985 143.108 117.911 143.433 117.771C143.757 117.632 144.051 117.429 144.297 117.175L147.74 113.732L151.184 117.175C151.686 117.66 152.359 117.928 153.057 117.922C153.755 117.916 154.423 117.636 154.917 117.142C155.41 116.648 155.691 115.981 155.697 115.282C155.703 114.584 155.434 113.911 154.949 113.409L151.506 109.966Z" fill="#93939A"/>\n <path d="M190.242 160.457L170.136 140.351C166.533 145.552 162.023 150.063 156.821 153.666L176.927 173.772C178.693 175.538 181.088 176.53 183.585 176.53C186.082 176.53 188.477 175.538 190.242 173.772C192.008 172.007 193 169.612 193 167.115C193 164.618 192.008 162.223 190.242 160.457ZM126.436 157.901C116.955 157.901 107.688 155.089 99.8048 149.822C91.922 144.555 85.7781 137.069 82.15 128.31C78.5219 119.551 77.5727 109.913 79.4222 100.614C81.2718 91.3158 85.8371 82.7746 92.5409 76.0708C99.2447 69.367 107.786 64.8017 117.084 62.9521C126.383 61.1026 136.021 62.0518 144.78 65.6799C153.539 69.308 161.025 75.4519 166.292 83.3347C171.559 91.2175 174.371 100.485 174.371 109.966C174.371 122.679 169.32 134.871 160.331 143.861C151.341 152.85 139.149 157.901 126.436 157.901ZM163.719 109.966C163.719 102.592 161.532 95.3838 157.435 89.2527C153.339 83.1216 147.516 78.343 140.703 75.5212C133.891 72.6994 126.395 71.9611 119.162 73.3996C111.93 74.8382 105.287 78.389 100.073 83.6031C94.8591 88.8171 91.3083 95.4602 89.8697 102.692C88.4312 109.924 89.1695 117.421 91.9913 124.233C94.8131 131.046 99.5918 136.869 105.723 140.965C111.854 145.062 119.062 147.248 126.436 147.248C136.324 147.248 145.807 143.32 152.799 136.329C159.791 129.337 163.719 119.854 163.719 109.966ZM133.645 102.757C133.398 102.51 133.104 102.313 132.781 102.179C132.458 102.046 132.112 101.977 131.762 101.977C131.412 101.977 131.066 102.046 130.743 102.179C130.42 102.313 130.126 102.51 129.879 102.757L126.436 106.2L122.993 102.757C122.49 102.272 121.818 102.003 121.119 102.01C120.421 102.016 119.753 102.296 119.26 102.789C118.766 103.283 118.486 103.951 118.48 104.649C118.474 105.348 118.742 106.02 119.227 106.523L122.67 109.966L119.227 113.409C118.973 113.655 118.77 113.949 118.63 114.274C118.491 114.598 118.417 114.948 118.414 115.301C118.411 115.655 118.479 116.006 118.612 116.333C118.746 116.66 118.944 116.958 119.194 117.208C119.444 117.458 119.741 117.655 120.069 117.789C120.396 117.923 120.747 117.991 121.1 117.988C121.454 117.985 121.803 117.911 122.128 117.771C122.453 117.632 122.747 117.429 122.993 117.175L126.436 113.732L129.879 117.175C130.382 117.66 131.054 117.928 131.752 117.922C132.451 117.916 133.119 117.636 133.612 117.142C134.106 116.648 134.386 115.981 134.392 115.282C134.398 114.584 134.13 113.911 133.645 113.409L130.202 109.966L133.645 106.523C133.892 106.275 134.088 105.982 134.222 105.659C134.356 105.336 134.425 104.989 134.425 104.64C134.425 104.29 134.356 103.944 134.222 103.621C134.088 103.298 133.892 103.004 133.645 102.757ZM112.34 102.757C112.093 102.51 111.8 102.313 111.477 102.179C111.154 102.046 110.807 101.977 110.458 101.977C110.108 101.977 109.762 102.046 109.439 102.179C109.116 102.313 108.822 102.51 108.575 102.757L105.132 106.2L101.688 102.757C101.186 102.272 100.513 102.003 99.8151 102.01C99.1169 102.016 98.4489 102.296 97.9552 102.789C97.4614 103.283 97.1814 103.951 97.1753 104.649C97.1692 105.348 97.4377 106.02 97.9227 106.523L101.366 109.966L97.9227 113.409C97.6684 113.655 97.4655 113.949 97.326 114.274C97.1864 114.598 97.1129 114.948 97.1098 115.301C97.1068 115.655 97.1742 116.006 97.3081 116.333C97.442 116.66 97.6397 116.958 97.8897 117.208C98.1398 117.458 98.4371 117.655 98.7644 117.789C99.0917 117.923 99.4423 117.991 99.7959 117.988C100.15 117.985 100.499 117.911 100.824 117.771C101.149 117.632 101.443 117.429 101.688 117.175L105.132 113.732L108.575 117.175C109.077 117.66 109.75 117.928 110.448 117.922C111.146 117.916 111.814 117.636 112.308 117.142C112.802 116.648 113.082 115.981 113.088 115.282C113.094 114.584 112.826 113.911 112.34 113.409L108.897 109.966L112.34 106.523C112.588 106.275 112.784 105.982 112.918 105.659C113.052 105.336 113.121 104.989 113.121 104.64C113.121 104.29 113.052 103.944 112.918 103.621C112.784 103.298 112.588 103.004 112.34 102.757ZM151.506 109.966L154.949 106.523C155.434 106.02 155.703 105.348 155.697 104.649C155.691 103.951 155.41 103.283 154.917 102.789C154.423 102.296 153.755 102.016 153.057 102.01C152.359 102.003 151.686 102.272 151.184 102.757L147.74 106.2L144.297 102.757C143.795 102.272 143.122 102.003 142.424 102.01C141.726 102.016 141.058 102.296 140.564 102.789C140.07 103.283 139.79 103.951 139.784 104.649C139.778 105.348 140.046 106.02 140.531 106.523L143.974 109.966L140.531 113.409C140.277 113.655 140.074 113.949 139.935 114.274C139.795 114.598 139.722 114.948 139.719 115.301C139.715 115.655 139.783 116.006 139.917 116.333C140.051 116.66 140.248 116.958 140.498 117.208C140.748 117.458 141.046 117.655 141.373 117.789C141.7 117.923 142.051 117.991 142.405 117.988C142.758 117.985 143.108 117.911 143.433 117.771C143.757 117.632 144.051 117.429 144.297 117.175L147.74 113.732L151.184 117.175C151.686 117.66 152.359 117.928 153.057 117.922C153.755 117.916 154.423 117.636 154.917 117.142C155.41 116.648 155.691 115.981 155.697 115.282C155.703 114.584 155.434 113.911 154.949 113.409L151.506 109.966Z" stroke="transparent" stroke-width="20" mask="url(#path-2-outside-1_0_1)"/>\n </g>\n <defs>\n <clipPath id="clip0_0_1">\n <rect width="200" height="200" fill="white"/>\n </clipPath>\n </defs>\n </svg>\n </div>\n <div class="errorContainer"></div>\n </div>\n</div>\n<div>\n <label class="ff-card-form-label" for="cardHolderInput">Card holder</label>\n <input class="ff-card-form-cardholder-input" id="cardHolderInput" placeholder="Card holder">\n <div class="errorContainer"></div>\n</div>\n'),this.wireCardInputs()}renderCardForm(){}getCardInputElements(){return this.cardInputElements}getCheckoutOptions(){return{cardElements:this.getCardInputElements(),card:{cardholderName:{required:!!this.checkoutConfig?.card?.cardholderName?.required}}}}}var ae=Object.freeze({__proto__:null,default:oe});const ie={[e.PaymentMethod.PAYMENT_CARD]:'\x3c!-- Card Payments Section --\x3e\n<div class="ff-payment-method-card ff-payment-method-payment-card">\n <label class="ff-payment-method-label">\n <input type="radio" name="payment-method" value="PAYMENT_CARD" class="ff-payment-method-radio">\n <div class="ff-payment-method-header">\n <div class="ff-card-logos">\n <img class="payment-method-icon" style="max-height: 30px" src="https://assets.fnlfx.com/common/checkout/cards.webp" alt="visa, mastercard">\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <div class="ff-card-form-container ff-payment-container" id="cardForm">\n <div class="loader-container">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <button class="ff-card-form-submit-button" id="submitButton">\n Continue\n </button>\n <p class="ff-security-message">\n Your payment information is secure with SSL/TLS encryption\n </p>\n </div>\n </div>\n</div>\n',[e.PaymentMethod.PAYPAL]:'<div class="ff-payment-method-card ff-payment-method-paypal">\n <label class="ff-payment-method-label">\n <input type="radio" name="payment-method" value="PAYPAL" class="ff-payment-method-radio">\n <div class="ff-payment-method-header">\n <div class="ff-payment-logo ff-paypal-logo">\n <img class="payment-method-icon" style="max-height: 22px" src="https://assets.fnlfx.com/common/checkout/paypal.webp" alt="PayPal logo">\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <ul class="ff-payment-features">\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span> Fast, convenient payment option </span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span> Keeps your financial info safe with end-to-end encryption </span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span> Backed by PayPal’s industry-leading fraud protection </span>\n </li>\n </ul>\n <div class="ff-paypal-button-container ff-payment-container" id="paypalButton"></div>\n <div class="loader-container payment-button-loader">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <p class="ff-security-message">\n Your payment information is secure with SSL/TLS encryption\n </p>\n </div>\n</div>\n',[e.PaymentMethod.GOOGLE_PAY]:'\x3c!-- Google Pay Section --\x3e\n<div class="ff-payment-method-card ff-payment-method-google-pay">\n <label class="ff-payment-method-label ff-google-pay-header">\n <input type="radio" name="payment-method" value="GOOGLE_PAY" class="ff-payment-method-radio" checked="checked">\n <div class="ff-payment-method-header">\n <div class="ff-payment-logo ff-google-pay-logo">\n <img src="https://developers.google.com/static/pay/api/images/brand-guidelines/google-pay-mark.png" alt="Google Pay">\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <ul class="ff-payment-features">\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Easy and private payments with Face/Touch ID</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Keeps your financial info safe with end-to-end encryption</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Protected by Google Pay\'s unique Device Account Number</span>\n </li>\n </ul>\n <div class="ff-google-pay-button-container ff-payment-container" id="googlePayButton"></div>\n <div class="loader-container payment-button-loader">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <p class="ff-security-message">\n Your payment information is secure with SSL/TLS encryption\n </p>\n </div>\n</div>\n',[e.PaymentMethod.APPLE_PAY]:'\x3c!-- Apple Pay Section --\x3e\n<div class="ff-payment-method-card ff-payment-method-apple-pay">\n <label class="ff-payment-method-label">\n <input type="radio" name="payment-method" value="APPLE_PAY" class="ff-payment-method-radio">\n <div class="ff-payment-method-header">\n <div class="ff-payment-logo ff-apple-pay-logo">\n <svg class="payment-method-icon" height="26" viewBox="0 0 63 26" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path fill-rule="evenodd" clip-rule="evenodd" d="M8.41022 4.82398C9.5916 4.92293 10.773 4.23026 11.5113 3.35205C12.2374 2.4491 12.7173 1.23692 12.5943 0C11.5483 0.0494767 10.2561 0.692674 9.51777 1.59562C8.84093 2.37488 8.26255 3.63654 8.41022 4.82398ZM22.4638 20.7555V1.47193H29.6628C33.3793 1.47193 35.9758 4.04471 35.9758 7.80494C35.9758 11.5652 33.33 14.1627 29.5644 14.1627H25.4418V20.7555H22.4638ZM12.5819 5.05898C11.5411 4.99877 10.5914 5.37358 9.82438 5.67633C9.33075 5.87116 8.91274 6.03614 8.59472 6.03614C8.23784 6.03614 7.80257 5.86234 7.31387 5.66719C6.6735 5.4115 5.94138 5.11916 5.17364 5.13319C3.41387 5.15793 1.77716 6.15983 0.878819 7.75545C-0.967091 10.9467 0.398882 15.6717 2.18326 18.2693C3.05699 19.5556 4.10301 20.9657 5.48129 20.9163C6.08765 20.8933 6.52383 20.7072 6.97524 20.5147C7.49492 20.293 8.0348 20.0628 8.87776 20.0628C9.69151 20.0628 10.2078 20.287 10.7033 20.5023C11.1746 20.707 11.6271 20.9036 12.2989 20.8915C13.7264 20.8668 14.6247 19.6051 15.4984 18.3187C16.4413 16.9381 16.8557 15.5906 16.9186 15.3861C16.9222 15.3745 16.9246 15.3665 16.9259 15.3625C16.9244 15.361 16.9128 15.3556 16.8922 15.3462C16.577 15.2011 14.1679 14.0926 14.1448 11.1199C14.1216 8.62473 16.0556 7.36054 16.3601 7.16153C16.3786 7.14944 16.3911 7.14125 16.3968 7.137C15.1662 5.30636 13.2464 5.10845 12.5819 5.05898ZM41.4153 20.9039C43.2858 20.9039 45.0209 19.9515 45.8085 18.4424H45.8701V20.7555H48.6266V11.157C48.6266 8.37393 46.4115 6.5804 43.0027 6.5804C39.8401 6.5804 37.5019 8.39866 37.4158 10.8972H40.0985C40.32 9.70979 41.4153 8.93054 42.9166 8.93054C44.7379 8.93054 45.7593 9.78401 45.7593 11.3549V12.4186L42.0429 12.6413C38.5849 12.8516 36.7143 14.274 36.7143 16.7479C36.7143 19.2464 38.6464 20.9039 41.4153 20.9039ZM42.215 18.6156C40.6275 18.6156 39.6184 17.8487 39.6184 16.6736C39.6184 15.4615 40.5906 14.7564 42.4488 14.6451L45.7591 14.4348V15.5233C45.7591 17.3292 44.2332 18.6156 42.215 18.6156ZM57.7699 21.51C56.5762 24.8868 55.2103 26 52.306 26C52.0845 26 51.3461 25.9753 51.1739 25.9258V23.6127C51.3585 23.6375 51.8138 23.6622 52.0476 23.6622C53.3643 23.6622 54.1027 23.1056 54.558 21.6584L54.8288 20.8049L49.7833 6.76594H52.8967L56.4039 18.1579H56.4655L59.9727 6.76594H63L57.7699 21.51ZM25.4416 3.99524H28.875C31.4592 3.99524 32.936 5.38059 32.936 7.81731C32.936 10.254 31.4592 11.6518 28.8627 11.6518H25.4416V3.99524Z" fill="currentColor"/>\n </svg>\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <ul class="ff-payment-features">\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Easy and private payments with Face/Touch ID</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Keeps your financial info safe with end-to-end encryption</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Protected by Apple Pay’s unique Device Account Number</span>\n </li>\n </ul>\n <div class="ff-apple-pay-button-container ff-payment-container" id="applePayButton"></div>\n <div class="loader-container payment-button-loader">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <p class="ff-security-message">\n Your payment information is secure with Apple Pay encryption\n </p>\n </div>\n</div>\n'};class se{constructor(t){this.onLoaderChange=e=>{document.querySelectorAll(`${this.containerSelector} .loader-container`)?.forEach(t=>{t.style.display=e?"flex":"none"})},this.onError=(e,t)=>{if(!e)return void this.containerEl.querySelectorAll(".payment-errors-container")?.forEach(e=>{e.innerHTML=""});let n=null;if(t){const e=t.replace("_","-").toLowerCase();n=this.containerEl.querySelector(`.ff-payment-method-${e} .payment-errors-container`)}n&&(n.textContent=e?.message||"")},this.onStatusChange=(e,t)=>{["initializing"].includes(e)||"initializing"!==t||this.onLoaderChange(!1),"updating"===e&&this.onLoaderChange(!0),"ready"===e&&"updating"===t&&this.onLoaderChange(!1)},this.onSuccess=()=>{const e=document.querySelector("#success-screen")?.innerHTML;document.querySelectorAll(".ff-payment-container").forEach(t=>{t.innerHTML=e}),this.onLoaderChange(!1)},this.onDestroy=()=>{this.containerEl.innerHTML&&(this.containerEl.innerHTML="")},this.onInputError=e=>{this.cardInstance.onInputError(e)},this.onMethodRender=t=>{const n=t.replace("_","-").toLowerCase(),r=this.containerEl.querySelector(`.ff-payment-method-${n}`);t===e.PaymentMethod.PAYMENT_CARD&&this.cardInstance.onMethodRender(),r&&r.classList.add("visible")},this.onMethodsAvailable=e=>{this.availableMethods=e,this.initAccordion(),e.forEach(this.onMethodRender)},this.onStartPurchase=e=>{this.currentPurchaseMethod=e},this.onPurchaseFailure=e=>{this.currentPurchaseMethod&&this.onError(e,this.currentPurchaseMethod),this.currentPurchaseMethod=null},this.onPurchaseCompleted=()=>{this.currentPurchaseMethod=null},this.containerSelector=t.container,this.paymentMethodOrder=t.paymentMethodOrder;const n=document.querySelector(this.containerSelector);if(!n)throw new Error(`Container element not found for selector: ${this.containerSelector}`);this.containerEl=n,this.checkoutConfig=t}initAccordion(){const e=this.containerEl.querySelectorAll(".ff-payment-method-card"),t=this.containerEl.querySelectorAll(".ff-payment-method-radio"),n=t=>{e.forEach(e=>{const n=e.querySelector(".ff-payment-method-radio");n===t&&n?.checked?e.classList.add("expanded"):e.classList.remove("expanded")})},r=Array.from(t).find(e=>this.availableMethods.includes(e.value));if(!r)throw new Error("Default skin accordion initialization error: No radio button found");setTimeout(()=>{r.checked=!0,n(r)},0),t.forEach(e=>{e.addEventListener("change",()=>{e.checked&&n(e)})})}wireCardInputs(){this.cardInstance.wireCardInputs();const e=this.containerEl.querySelector("#submitButton");if(!e)throw new Error("One or more card input elements are missing in the default skin");this.cardInputElements={...this.cardInstance.getCardInputElements(),button:e}}async init(){this.containerEl.insertAdjacentHTML("beforeend",'<div class="ff-skin-default" id="ff-payment-method-containers">\n <div id="success-screen" style="display: none">\n <div class="success">\n <img alt="Loading" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI1IDAuMTExMzI4QzIwLjA3NzQgMC4xMTEzMjggMTUuMjY1NCAxLjU3MTA0IDExLjE3MjUgNC4zMDU4NkM3LjA3OTUyIDcuMDQwNjkgMy44ODk0NSAxMC45Mjc4IDIuMDA1NjYgMTUuNDc1N0MwLjEyMTg4MyAyMC4wMjM1IC0wLjM3MSAyNS4wMjc4IDAuNTg5MzQzIDI5Ljg1NThDMS41NDk2OSAzNC42ODM4IDMuOTIwMTIgMzkuMTE4NSA3LjQwMDkgNDIuNTk5M0MxMC44ODE3IDQ2LjA4MDEgMTUuMzE2NCA0OC40NTA1IDIwLjE0NDQgNDkuNDEwOUMyNC45NzI0IDUwLjM3MTIgMjkuOTc2NyA0OS44NzgzIDM0LjUyNDYgNDcuOTk0NkMzOS4wNzI0IDQ2LjExMDggNDIuOTU5NSA0Mi45MjA3IDQ1LjY5NDQgMzguODI3N0M0OC40MjkyIDM0LjczNDggNDkuODg4OSAyOS45MjI4IDQ5Ljg4ODkgMjUuMDAwMkM0OS44ODg5IDE4LjM5OTMgNDcuMjY2NyAxMi4wNjg3IDQyLjU5OTEgNy40MDExMkMzNy45MzE1IDIuNzMzNTQgMzEuNjAwOSAwLjExMTMyOCAyNSAwLjExMTMyOFpNNDEuMjU1NiAxNi42NDY5TDIwLjgxNTYgMzcuMDcxM0w4Ljc0NDQ0IDI1LjAwMDJDOC4zMzE4OCAyNC41ODc3IDguMTAwMTEgMjQuMDI4MSA4LjEwMDExIDIzLjQ0NDdDOC4xMDAxMSAyMi44NjEyIDguMzMxODggMjIuMzAxNyA4Ljc0NDQ0IDIxLjg4OTFDOS4xNTcgMjEuNDc2NSA5LjcxNjU1IDIxLjI0NDggMTAuMyAyMS4yNDQ4QzEwLjg4MzQgMjEuMjQ0OCAxMS40NDMgMjEuNDc2NSAxMS44NTU2IDIxLjg4OTFMMjAuODQ2NyAzMC44ODAyTDM4LjE3NTYgMTMuNTY2OUMzOC4zNzk4IDEzLjM2MjYgMzguNjIyMyAxMy4yMDA2IDM4Ljg4OTIgMTMuMDlDMzkuMTU2MiAxMi45Nzk1IDM5LjQ0MjIgMTIuOTIyNiAzOS43MzExIDEyLjkyMjZDNDAuMDIgMTIuOTIyNiA0MC4zMDYxIDEyLjk3OTUgNDAuNTczIDEzLjA5QzQwLjgzOTkgMTMuMjAwNiA0MS4wODI0IDEzLjM2MjYgNDEuMjg2NyAxMy41NjY5QzQxLjQ5MDkgMTMuNzcxMiA0MS42NTMgMTQuMDEzNyA0MS43NjM1IDE0LjI4MDZDNDEuODc0MSAxNC41NDc1IDQxLjkzMSAxNC44MzM1IDQxLjkzMSAxNS4xMjI0QzQxLjkzMSAxNS40MTEzIDQxLjg3NDEgMTUuNjk3NCA0MS43NjM1IDE1Ljk2NDNDNDEuNjUzIDE2LjIzMTIgNDEuNDkwOSAxNi40NzM3IDQxLjI4NjcgMTYuNjc4TDQxLjI1NTYgMTYuNjQ2OVoiIGZpbGw9IiM4RURGQzIiLz4KPC9zdmc+Cg==">\n <div>Payment completed successfully</div>\n </div>\n </div>\n</div>\n');const e=this.containerEl.querySelector("#ff-payment-method-containers");this.paymentMethodOrder.forEach(t=>{e.insertAdjacentHTML("beforeend",ie[t])}),this.cardInstance=new oe(document.querySelector("#cardForm"),this.checkoutConfig),this.cardInstance.init(),this.wireCardInputs()}renderCardForm(){}getCardInputElements(){return{...this.cardInstance.getCardInputElements(),button:this.cardInputElements.button}}getPaymentButtonElements(){return{paypal:this.containerEl.querySelector("#paypalButton"),googlePay:this.containerEl.querySelector("#googlePayButton"),applePay:this.containerEl.querySelector("#applePayButton")}}getCheckoutOptions(){return{...this.cardInstance.getCheckoutOptions(),cardElements:this.getCardInputElements(),paymentButtonElements:this.getPaymentButtonElements(),applePay:_[e.PaymentMethod.APPLE_PAY],paypal:_[e.PaymentMethod.PAYPAL],googlePay:_[e.PaymentMethod.GOOGLE_PAY]}}}var de=Object.freeze({__proto__:null,default:async e=>{const t=new se(e);return await t.init(),t}});e.APIError=o,e.Billing=re,e.CHECKOUT_STATES={INITIALIZING:"initializing",READY:"ready",PROCESSING:"processing",ACTION_REQUIRED:"action_required",UPDATING:"updating",COMPLETED:"completed",ERROR:"error",DESTROYED:"destroyed"},e.CheckoutError=i,e.ConfigurationError=class extends n{constructor(e){super(e,k.CONFIGURATION_ERROR),this.name="ConfigurationError"}},e.DEFAULTS=E,e.ERROR_CODES=k,e.EVENTS=M,e.FunnefoxSDKError=n,e.NetworkError=s,e.PrimerError=a,e.SDK_VERSION=g,e.ValidationError=r,e.configure=J,e.createCheckout=ee,e.createClientSession=te,e.default=re,e.getAvailablePaymentMethods=ne,Object.defineProperty(e,"__esModule",{value:!0})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FunnelfoxSDK={})}(this,function(e){"use strict";class t{constructor(){this._events=new Map}on(e,t){if("function"!=typeof t)throw new Error("Event handler must be a function");return this._events.has(e)||this._events.set(e,[]),this._events.get(e).push(t),this}once(e,t){if("function"!=typeof t)throw new Error("Event handler must be a function");const n=(...r)=>{this.off(e,n),t.apply(this,r)};return this.on(e,n)}off(e,t=null){if(!this._events.has(e))return this;if(null===t)return this._events.delete(e),this;const n=this._events.get(e),r=n.indexOf(t);return-1!==r&&(n.splice(r,1),0===n.length&&this._events.delete(e)),this}emit(e,...t){if(!this._events.has(e))return!1;const n=this._events.get(e).slice();for(const r of n)try{r.apply(this,t)}catch(t){console.warn(`Error in event handler for "${String(e)}":`,t)}return!0}listenerCount(e){return this._events.has(e)?this._events.get(e).length:0}eventNames(){return Array.from(this._events.keys())}removeAllListeners(){return this._events.clear(),this}listeners(e){return this._events.has(e)?this._events.get(e).slice():[]}}class n extends Error{constructor(e,t=R.SDK_ERROR,r=null){super(e),this.name="FunnefoxSDKError",this.code=t,this.details=r,Error.captureStackTrace&&Error.captureStackTrace(this,n)}}class r extends n{constructor(e,t,n=null){super(`Invalid ${e}: ${t}`,R.VALIDATION_ERROR),this.name="ValidationError",this.field=e,this.value=n}}class o extends n{constructor(e,t=null,n={}){super(e,n.errorCode||R.API_ERROR),this.name="APIError",this.statusCode=t,this.errorCode=n.errorCode||null,this.errorType=n.errorType||null,this.requestId=n.requestId||null,this.response=n.response||null}}class a extends n{constructor(e,t=null){super(e,R.PRIMER_ERROR),this.name="PrimerError",this.primerError=t}}class i extends n{constructor(e,t=null){super(e,R.CHECKOUT_ERROR),this.name="CheckoutError",this.phase=t}}class s extends n{constructor(e,t=null){super(e,R.NETWORK_ERROR),this.name="NetworkError",this.originalError=t}}function d(e){const{id:t,src:n,async:r=!0,type:o="text/javascript",attributes:a={},integrity:i,crossOrigin:s,appendTo:d="body"}=e;return new Promise((e,c)=>{let l=null;if(t&&(l=document.getElementById(t)),l||(l=document.querySelector(`script[src="${n}"]`)),l)return void e(l);const h=document.createElement("script");t&&(h.id=t),h.type=o,h.src=n,r&&(h.async=!0),i&&(h.integrity=i),s&&(h.crossOrigin=s),Object.entries(a).forEach(([e,t])=>{h.setAttribute(e,t)}),h.onload=()=>e(h),h.onerror=()=>c(new Error(`Failed to load script: ${n}`));("head"===d?document.head:document.body).appendChild(h)})}function c(e){const{href:t,integrity:n,crossOrigin:r}=e;return new Promise((e,o)=>{const a=document.querySelector(`link[href="${t}"]`);if(a)return void e(a);const i=document.createElement("link");i.rel="stylesheet",i.href=t,n&&(i.integrity=n),r&&(i.crossOrigin=r),i.onload=()=>e(i),i.onerror=()=>o(new Error(`Failed to load stylesheet: ${t}`)),document.head.appendChild(i)})}const l="https://sdk.primer.io/web",h={"2.57.3":{js:"sha384-xq2SWkYvTlKOMpuXQUXq1QI3eZN7JiqQ3Sc72U9wY1IE30MW3HkwQWg/1n6BTMz4"}};let u=null,p=!1;async function m(e){if(p)return;if(u)return u;if("undefined"!=typeof window&&window.Primer&&"function"==typeof window.Primer.createHeadless)return void(p=!0);const t=e||"2.57.3",n=`${l}/v${t}/Primer.min.js`,r=`${l}/v${t}/Checkout.css`,o=h[t];return u=(async()=>{try{await Promise.all([c({href:r,integrity:o?.css,crossOrigin:"anonymous"}),d({src:n,integrity:o?.js,crossOrigin:"anonymous",appendTo:"head"})]),await function(e=1e4){return new Promise((t,n)=>{const r=Date.now(),o=()=>{"undefined"!=typeof window&&window.Primer&&"function"==typeof window.Primer.createHeadless?t():Date.now()-r>e?n(new Error("Timeout waiting for Primer SDK to initialize on window")):setTimeout(o,50)};o()})}(),p=!0}catch(e){throw u=null,e}})(),u}function y(...e){const t={};for(const n of e)if(n&&"object"==typeof n)for(const e in n)Object.prototype.hasOwnProperty.call(n,e)&&("object"!=typeof n[e]||Array.isArray(n[e])||null===n[e]?t[e]=n[e]:t[e]=y(t[e]||{},n[e]));return t}function f(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substr(2,5)}`}function C(e){return new Promise(t=>setTimeout(t,e))}var g;e.PaymentMethod=void 0,(g=e.PaymentMethod||(e.PaymentMethod={})).GOOGLE_PAY="GOOGLE_PAY",g.APPLE_PAY="APPLE_PAY",g.PAYPAL="PAYPAL",g.PAYMENT_CARD="PAYMENT_CARD";const E="0.6.4-beta.0",M={BASE_URL:"https://billing.funnelfox.com",REGION:"default",SANDBOX:!1,REQUEST_TIMEOUT:3e4,RETRY_ATTEMPTS:3,RETRY_BASE_DELAY:1e3},w={SUCCESS:"success",ERROR:"error",STATUS_CHANGE:"status-change",DESTROY:"destroy",INPUT_ERROR:"input-error",LOADER_CHANGE:"loader-change",METHOD_RENDER:"method-render",METHOD_RENDER_ERROR:"method-render-error",START_PURCHASE:"start-purchase",PURCHASE_FAILURE:"purchase-failure",PURCHASE_COMPLETED:"purchase-completed",PURCHASE_CANCELLED:"purchase-cancelled",METHODS_AVAILABLE:"methods-available"},S="/v1/checkout/create_client_session",P="/v1/checkout/update_client_session",v="/v1/checkout/create_payment",b="/v1/checkout/resume_payment",I="/v1/checkout/one_click",k="/v1/checkout/create_simple_client_session",R={SDK_ERROR:"SDK_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",API_ERROR:"API_ERROR",PRIMER_ERROR:"PRIMER_ERROR",CHECKOUT_ERROR:"CHECKOUT_ERROR",CONFIGURATION_ERROR:"CONFIGURATION_ERROR",NETWORK_ERROR:"NETWORK_ERROR"},A=[...[e.PaymentMethod.GOOGLE_PAY,e.PaymentMethod.APPLE_PAY,e.PaymentMethod.PAYPAL],...[e.PaymentMethod.PAYMENT_CARD]],L={input:{error:{borderColor:"rgb(227, 47, 65)"},base:{borderWidth:"1px",borderStyle:"solid",borderColor:"rgb(0 0 0 / 10%)",height:"36px",paddingHorizontal:10,borderRadius:"6px"}}};L.input.base.paddingHorizontal,L.input.base.paddingHorizontal;const x=[e.PaymentMethod.APPLE_PAY,e.PaymentMethod.GOOGLE_PAY,e.PaymentMethod.PAYPAL,e.PaymentMethod.PAYMENT_CARD],_={[e.PaymentMethod.APPLE_PAY]:{buttonStyle:"black"},[e.PaymentMethod.PAYPAL]:{buttonColor:"gold",buttonShape:"pill",buttonLabel:"pay",buttonSize:"large",buttonHeight:54,paymentFlow:"PREFER_VAULT"},[e.PaymentMethod.GOOGLE_PAY]:{buttonColor:"black",buttonSizeMode:"fill",buttonType:"pay"}},D={billingOptions:{requiredBillingContactFields:["emailAddress"]},shippingOptions:{requiredShippingContactFields:["emailAddress"]}};class T{constructor(){this.isInitialized=!1,this.destroyCallbacks=[],this.currentHeadless=null,this.availableMethods=[],this.paymentMethodsInterfaces=[]}isPrimerAvailable(){return"undefined"!=typeof window&&window.Primer&&"function"==typeof window.Primer?.createHeadless}async ensurePrimerLoaded(e){if(!this.isPrimerAvailable())try{await m(e)}catch(e){throw new a("Failed to load Primer SDK",e)}}ensurePrimerAvailable(){if(!this.isPrimerAvailable())throw new a("Primer SDK not found. Please include the Primer SDK script before initializing FunnefoxSDK.")}async createHeadlessCheckout(e,t){return await this.ensurePrimerLoaded(),this.currentHeadless=T.headlessManager.getOrCreate(e,t),this.currentHeadless}disableButtons(e){if(this.paymentMethodsInterfaces)for(const t of this.paymentMethodsInterfaces)t.setDisabled(e)}async renderButton(e,{htmlNode:t,onMethodRenderError:n,onMethodRender:r}){let o;if(await this.ensurePrimerLoaded(),!this.currentHeadless)throw new a("Headless checkout not found");try{const n=await this.currentHeadless,a=await n.createPaymentMethodManager(e);if(!a)throw new Error("Payment method manager is not available");const i=document.createElement("div");i.className=f("funnefox-primer-button-wrapper");const s=document.createElement("style");document.head.appendChild(s);const d=s.sheet;return d&&(d.insertRule(`\n .${i.className} {\n width: 100% !important;\n }\n `),d.insertRule(`\n .${i.className} button {\n height: 54px !important;\n border-radius: 28px !important;\n }\n `)),t.appendChild(i),o=a.createButton(),await o.render(i,{}),this.destroyCallbacks.push(()=>o.clean()),r(e),{setDisabled:e=>{o.setDisabled(e)},destroy:()=>{s.remove(),o.clean()}}}catch(t){throw n(e),new a("Failed to initialize Primer checkout",t)}}async initMethod(t,n,r){try{if(t===e.PaymentMethod.PAYMENT_CARD){if(!r.cardElements||!r.onSubmit||!r.onInputChange)throw new a("Card elements, onSubmit, and onInputChange are required for PAYMENT_CARD method");const e=await this.renderCardCheckoutWithElements(r.cardElements,{onSubmit:r.onSubmit,onInputChange:r.onInputChange,onMethodRenderError:r.onMethodRenderError,onMethodRender:r.onMethodRender});return this.paymentMethodsInterfaces.push(e),e}{const e=await this.renderButton(t,{htmlNode:n,onMethodRenderError:r.onMethodRenderError,onMethodRender:r.onMethodRender});return this.paymentMethodsInterfaces.push(e),e}}catch(e){throw new a("Failed to initialize Primer checkout",e)}}async renderCardCheckoutWithElements(t,{onSubmit:n,onInputChange:r,onMethodRenderError:o,onMethodRender:i}){try{if(!this.currentHeadless)throw new a("Headless checkout not found");const o=await this.currentHeadless,s=await o.createPaymentMethodManager("PAYMENT_CARD");if(!s)throw new Error("Payment method manager is not available");const{cardNumberInput:d,expiryInput:c,cvvInput:l}=s.createHostedInputs(),h=async()=>{if(!s)return!1;const{valid:e,validationErrors:t}=await s.validate(),n=t.find(e=>"cardholderName"===e.name);return u("cardholderName",n?.message||null),e},u=(e,t)=>{r(e,t)},p=e=>t=>{const n=t;n.submitted&&u(e,n.error)},m=async e=>{s.setCardholderName(e.target.value),u("cardholderName",null)};t.cardholderName?.addEventListener("input",m),d.addEventListener("change",p("cardNumber")),c.addEventListener("change",p("expiryDate")),l.addEventListener("change",p("cvv"));const y=async()=>{if(await h())try{n(!0),await s.submit()}catch(e){throw new a("Failed to submit payment",e)}finally{n(!1)}};t.button?.addEventListener("click",y),await Promise.all([d.render(t.cardNumber,{placeholder:"1234 1234 1234 1234",ariaLabel:"Card number",style:L}),c.render(t.expiryDate,{placeholder:"MM/YY",ariaLabel:"Expiry date",style:L}),l.render(t.cvv,{placeholder:"123",ariaLabel:"CVV",style:L})]);const f=()=>{s.removeHostedInputs(),t.cardholderName?.removeEventListener("change",m),t.button?.removeEventListener("click",y)};return this.destroyCallbacks.push(f),i(e.PaymentMethod.PAYMENT_CARD),{setDisabled:e=>{d.setDisabled(e),c.setDisabled(e),l.setDisabled(e),t.button&&(t.button.disabled=e),t.cardholderName&&(t.cardholderName.disabled=e)},submit:()=>y(),destroy:()=>{this.destroyCallbacks=this.destroyCallbacks.filter(e=>e!==f),f()}}}catch(t){throw o(e.PaymentMethod.PAYMENT_CARD),new a("Failed to initialize Primer checkout",t)}}async initializeHeadlessCheckout(e,t){await this.createHeadlessCheckout(e,{...t,onTokenizeSuccess:this.wrapTokenizeHandler(t.onTokenizeSuccess),onResumeSuccess:this.wrapResumeHandler(t.onResumeSuccess),onAvailablePaymentMethodsLoad:this.wrapAvailablePaymentMethodsLoadHandler(t.onAvailablePaymentMethodsLoad)})}async renderCheckout(t,n,r){const{cardElements:o,paymentButtonElements:a,container:i,onSubmit:s,onInputChange:d,onMethodRender:c,onMethodRenderError:l,onMethodsAvailable:h}=r;await this.initializeHeadlessCheckout(t,n),h?.(this.availableMethods),await Promise.all(this.availableMethods.map(t=>{if(t===e.PaymentMethod.PAYMENT_CARD)return this.initMethod(t,i,{cardElements:o,onSubmit:s,onInputChange:d,onMethodRender:c,onMethodRenderError:l});{const n={[e.PaymentMethod.PAYPAL]:a.paypal,[e.PaymentMethod.GOOGLE_PAY]:a.googlePay,[e.PaymentMethod.APPLE_PAY]:a.applePay}[t];return this.initMethod(t,n,{onMethodRender:c,onMethodRenderError:l})}})),this.isInitialized=!0}wrapTokenizeHandler(e){return async(t,n)=>{try{await e(t,n)}catch(e){console.error("Error in tokenize handler:",e),n.handleFailure("Payment processing failed. Please try again.")}}}wrapResumeHandler(e){return async(t,n)=>{try{await e(t,n)}catch(e){console.error("Error in resume handler:",e),n.handleFailure("Payment processing failed. Please try again.")}}}wrapAvailablePaymentMethodsLoadHandler(t){return n=>{let r=!1;if(this.availableMethods=A.filter(t=>n.some(n=>(n.type===e.PaymentMethod.APPLE_PAY&&(r=!0),n.type===t))),r&&(this.availableMethods=this.availableMethods.filter(t=>t!==e.PaymentMethod.GOOGLE_PAY)),0===this.availableMethods.length)throw new a("No allowed payment methods found");t?.(this.availableMethods)}}async destroy(){if(this.currentHeadless&&(T.headlessManager.remove(this.currentHeadless),this.currentHeadless=null),this.destroyCallbacks)try{Promise.all(this.destroyCallbacks.map(e=>e()))}catch(e){console.warn("Error destroying Primer checkout:",e)}this.destroyCallbacks=[],this.isInitialized=!1}createHandlers(e){return{handleSuccess:()=>{e.onSuccess&&e.onSuccess()},handleFailure:t=>{e.onError&&e.onError(new Error(t))},continueWithNewClientToken:t=>{e.onActionRequired&&e.onActionRequired(t)}}}getCurrentCheckout(){return this.destroyCallbacks}isActive(){return this.isInitialized&&this.destroyCallbacks.length>0}validateContainer(e){const t=document.querySelector(e);if(!t)throw new a(`Checkout container not found: ${e}`);return"none"===window.getComputedStyle(t).display&&console.warn("Checkout container is hidden, this may cause display issues"),t}}T.headlessManager=new class{constructor(){this.cache=new Map,this.queue=Promise.resolve()}generateKey(e,t){const n={paymentHandling:t.paymentHandling,apiVersion:t.apiVersion,style:t.style,card:t.card,applePay:t.applePay,paypal:t.paypal,googlePay:t.googlePay};return`${e}:${JSON.stringify(n)}`}getOrCreate(e,t){const n=this.generateKey(e,t),r=this.cache.get(n);if(r)return r;const o=this.queue,i=(async()=>{await o;const r=y({paymentHandling:"MANUAL",apiVersion:"2.4"},t);try{const t=await window.Primer.createHeadless(e,r),n=await t;return await n.start(),n}catch(e){throw this.cache.delete(n),new a("Failed to create Primer headless checkout",e)}})();return this.cache.set(n,i),this.queue=i.catch(()=>{}),i}remove(e){for(const[t,n]of this.cache.entries())if(n===e){this.cache.delete(t);break}}clear(){this.cache.clear()}};class N{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.orgId=e.orgId,this.timeout=e.timeout||3e4,this.retryAttempts=e.retryAttempts||3}async request(e,t={}){const n=`${this.baseUrl}/${this.orgId}${e}`,r={method:"GET",headers:{"Content-Type":"application/json","X-SDK-Version":E,...t.headers||{}},...t};try{return await async function(e,t=3,n=1e3){let r;for(let o=1;o<=t;o++)try{return await e()}catch(e){if(r=e,o===t)throw r;const a=n*Math.pow(2,o-1);await C(a)}throw r}(async()=>await function(e,t,n="Operation timed out"){const r=new Promise((e,r)=>{setTimeout(()=>r(new Error(n)),t)});return Promise.race([e,r])}(this._makeRequest(n,r),this.timeout,"Request timed out"),this.retryAttempts)}catch(e){if(e instanceof Error&&"APIError"===e.name)throw e;throw new s("Network request failed",e)}}async _makeRequest(e,t){let n,r;try{n=await fetch(e,t)}catch(e){if(e instanceof Error&&"NetworkError"===e.name)throw e;throw new s("Network request failed",e)}try{r=await n.json()}catch{throw new o("Invalid JSON response",n.status,{})}if(!n.ok){const e=r,t=e.error?.[0]?.msg||"Failed to create payment";throw new o(t,n.status,{response:r})}return r}async createClientSession(e){const t={region:e.region||"default",integration_type:"primer",pp_ident:e.priceId,external_id:e.externalId,email_address:e.email,client_metadata:e.clientMetadata||{}};return void 0!==e.countryCode&&(t.country_code=e.countryCode),await this.request(S,{method:"POST",body:JSON.stringify(t)})}async updateClientSession(e){const t={order_id:e.orderId,client_token:e.clientToken,pp_ident:e.priceId,client_metadata:e.clientMetadata||{}};return await this.request(P,{method:"POST",body:JSON.stringify(t)})}async createPayment(e){const t={order_id:e.orderId,payment_method_token:e.paymentMethodToken,client_metadata:e.clientMetadata||{}};return await this.request(v,{method:"POST",body:JSON.stringify(t)})}async resumePayment(e){const t={order_id:e.orderId,resume_token:e.resumeToken};return await this.request(b,{method:"POST",body:JSON.stringify(t)})}processSessionResponse(e){if("error"===e.status){const t=e.error?.[0];throw new o(t?.msg||"Session creation failed",null,{errorCode:t?.code,errorType:t?.type,requestId:e.req_id,response:e})}const t=e.data;return{type:"session_created",orderId:t.order_id,clientToken:t.client_token}}processPaymentResponse(e){if("error"===e.status){const t=e.error?.[0];throw new o(t?.msg||"Payment request failed",null,{errorCode:t?.code,errorType:t?.type,response:e})}const t=e.data;if(t.action_required_token)return{type:"action_required",orderId:t.order_id,clientToken:t.action_required_token};if(t.checkout_status)switch(t.checkout_status){case"succeeded":return{type:"success",orderId:t.order_id,status:"succeeded"};case"failed":throw new o(t.failed_message_for_user||"Payment failed",null,{response:e});case"cancelled":throw new o("Payment was cancelled by user",null,{response:e});case"processing":return{type:"processing",orderId:t.order_id,status:"processing"};default:throw new o(`Unhandled checkout status: ${t.checkout_status}`,null,{response:e})}throw new o("Invalid payment response format",null,{response:e})}async oneClick(e){return await this.request(I,{method:"POST",body:JSON.stringify(e)})}async createSimpleClientSession(e){return await this.request(k,{method:"POST",body:JSON.stringify({region:"default",integration_type:"primer",...e})})}}"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent=".ff-sdk-loader-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255);\n z-index: 2;\n}\n\n.ff-sdk-loader {\n width: 24px;\n height: 24px;\n border: 4px solid #e32f41;\n border-top: 4px solid transparent;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n }");const O='<div class="ff-sdk-loader-container">\n <div class="ff-sdk-loader"></div>\n</div>\n',j={loaderContainer:".ff-sdk-loader-container"};var z,H="https://js.stripe.com/v3",U=/^https:\/\/js\.stripe\.com\/v3\/?(\?.*)?$/,q=function(e){var t=document.createElement("script");t.src="".concat(H).concat("");var n=document.head||document.body;if(!n)throw new Error("Expected document.body not to be null. Stripe.js requires a <body> element.");return n.appendChild(t),t},Y=null,F=null,B=null,G=function(e){return null!==Y?Y:(Y=new Promise(function(t,n){if("undefined"!=typeof window&&"undefined"!=typeof document)if(window.Stripe)t(window.Stripe);else try{var r=function(){for(var e=document.querySelectorAll('script[src^="'.concat(H,'"]')),t=0;t<e.length;t++){var n=e[t];if(U.test(n.src))return n}return null}();if(r&&e);else if(r){if(r&&null!==B&&null!==F){var o;r.removeEventListener("load",B),r.removeEventListener("error",F),null===(o=r.parentNode)||void 0===o||o.removeChild(r),r=q()}}else r=q();B=function(e,t){return function(){window.Stripe?e(window.Stripe):t(new Error("Stripe.js not available"))}}(t,n),F=function(e){return function(){e(new Error("Failed to load Stripe.js"))}}(n),r.addEventListener("load",B),r.addEventListener("error",F)}catch(e){return void n(e)}else t(null)})).catch(function(e){return Y=null,Promise.reject(e)})},Q=!1,Z=function(){return z||(z=G(null).catch(function(e){return z=null,Promise.reject(e)}))};Promise.resolve().then(function(){return Z()}).catch(function(e){Q||console.warn(e)});"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent=".ff-sdk-error-container {\n background-color: #d1000033;\n color: #d10000;\n font-size: 14px;\n padding: 16px 12px;\n border-radius: 8px;\n}");const $='<div class="ff-sdk-error-container">\n <p class="ff-sdk-error-message">The payment form didn’t load correctly.</p>\n <p>Please refresh the page to try again.</p>\n <p>If the problem persists, please contact support.</p>\n <p class="ff-sdk-error-request-id"></p>\n</div>\n',V={errorRequestId:".ff-sdk-error-request-id"};class K extends t{constructor(e){super(),this.counter=0,this.radarSessionId=null,this.airwallexDeviceId=null,this.handleInputChange=(e,t)=>{this.emit(w.INPUT_ERROR,{name:e,error:t})},this.handleMethodRender=e=>{this.emit(w.METHOD_RENDER,e)},this.handleMethodRenderError=e=>{this.emit(w.METHOD_RENDER_ERROR,e)},this.handleSubmit=e=>{this.onLoaderChangeWithRace(e),this._setState(e?"processing":"ready")},this.handleTokenizeSuccess=async(e,t)=>{if(this.orderId)try{this.onLoaderChangeWithRace(!0),this._setState("processing");const[n,r]=await Promise.all([this.radarSessionId,this.airwallexDeviceId]),o=await this.apiClient.createPayment({orderId:this.orderId,paymentMethodToken:e.token,clientMetadata:{radarSessionId:n,airwallexDeviceId:r}}),a=this.apiClient.processPaymentResponse(o);await this._processPaymentResult(a,t)}catch(e){this._setState("error"),this.emit(w.PURCHASE_FAILURE,new Error(e.message||"Payment processing failed")),t.handleFailure(e.message||"Payment processing failed")}finally{this.onLoaderChangeWithRace(!1),this._setState("ready")}else t.handleFailure("Order ID not found or checkout has been destroyed")},this.handleResumeSuccess=async(e,t)=>{if(this.orderId)try{this.onLoaderChangeWithRace(!0),this._setState("processing");const n=await this.apiClient.resumePayment({orderId:this.orderId,resumeToken:e.resumeToken}),r=this.apiClient.processPaymentResponse(n);await this._processPaymentResult(r,t)}catch(e){this._setState("error"),this.emit(w.PURCHASE_FAILURE,new Error(e.message||"Payment processing failed")),t.handleFailure(e.message||"Payment processing failed")}finally{this.emit(w.PURCHASE_COMPLETED),this.onLoaderChangeWithRace(!1),this._setState("ready")}else t.handleFailure("Order ID not found or checkout has been destroyed")},this.handleMethodsAvailable=e=>{this.emit(w.METHODS_AVAILABLE,e)},this.onLoaderChangeWithRace=e=>{const t=!!(e?++this.counter:--this.counter);this.primerWrapper.disableButtons(t),this.emit(w.LOADER_CHANGE,t)},this.id=f("checkout_"),this.orgId=e.orgId,this.baseUrl=e.baseUrl,this.region=e.region,this.checkoutConfig={...e.checkoutConfig},this.callbacks={onSuccess:this.checkoutConfig.onSuccess,onError:this.checkoutConfig.onError,onStatusChange:this.checkoutConfig.onStatusChange,onDestroy:this.checkoutConfig.onDestroy},delete this.checkoutConfig?.onSuccess,delete this.checkoutConfig?.onError,delete this.checkoutConfig?.onStatusChange,delete this.checkoutConfig?.onDestroy,this.state="initializing",this.orderId=null,this.clientToken=null,this.primerWrapper=new T,this.isDestroyed=!1,this._setupCallbackBridges()}_setupCallbackBridges(){this.callbacks.onSuccess&&this.on(w.SUCCESS,this.callbacks.onSuccess),this.callbacks.onError&&this.on(w.ERROR,this.callbacks.onError),this.callbacks.onStatusChange&&this.on(w.STATUS_CHANGE,this.callbacks.onStatusChange),this.callbacks.onDestroy&&this.on(w.DESTROY,this.callbacks.onDestroy)}removeAllListeners(){return super.removeAllListeners()}async initialize(){try{return this.showInitializingLoader(),this._setState("initializing"),await this.createSession(),await this._initializePrimerCheckout(),this._setState("ready"),this.checkoutConfig?.onInitialized?.(),this}catch(e){throw this._setState("error"),((e,t)=>{const n=document.querySelector(e);if(n&&(n.innerHTML=$,t)){const e=n.querySelector(V.errorRequestId);e&&(e.textContent=`Request ID: ${t}`)}})(this.checkoutConfig.container,e?.response?.req_id),this.emit(w.ERROR,e),e}finally{this.hideInitializingLoader()}}async createSession(){this.apiClient=new N({baseUrl:this.baseUrl||M.BASE_URL,orgId:this.orgId,timeout:M.REQUEST_TIMEOUT,retryAttempts:M.RETRY_ATTEMPTS});const e={priceId:this.checkoutConfig.priceId,externalId:this.checkoutConfig.customer.externalId,email:this.checkoutConfig.customer.email,region:this.region||M.REGION,clientMetadata:this.checkoutConfig.clientMetadata,countryCode:this.checkoutConfig.customer.countryCode},t=[this.orgId,this.checkoutConfig.priceId,this.checkoutConfig.customer.externalId,this.checkoutConfig.customer.email].join("-");let n;const r=K.sessionCache.get(t);if(r)n=await r;else{const r=this.apiClient.createClientSession(e).then(e=>{if(e.data?.stripe_public_key&&function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];Q=!0;var r=Date.now();return Z().then(function(e){return function(e,t,n){if(null===e)return null;var r=e.apply(void 0,t);return function(e,t){e&&e._registerWrapper&&e._registerWrapper({name:"stripe-js",version:"4.6.0",startTime:t})}(r,n),r}(e,t,r)})}(e.data?.stripe_public_key).then(e=>{this.radarSessionId=e.createRadarSession().then(e=>e?.radarSession?.id).catch(()=>"")}),e.data?.airwallex_risk_enabled){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)});this.airwallexDeviceId=async function(e,t=!1){const n=t?"https://static-demo.airwallex.com/webapp/fraud/device-fingerprint/index.js":"https://static.airwallex.com/webapp/fraud/device-fingerprint/index.js";await d({id:"airwallex-fraud-api",src:n,async:!0,attributes:{"data-order-session-id":e}})}(e,!0).then(()=>e).catch(()=>e)}return this.isCollectingApplePayEmail=!!e.data?.collect_apple_pay_email,e});K.sessionCache.set(t,r),n=await r}const o=this.apiClient.processSessionResponse(n);this.orderId=o.orderId,this.clientToken=o.clientToken}convertCardSelectorsToElements(e,t){const n=t.querySelector(e.cardNumber),r=t.querySelector(e.expiryDate),o=t.querySelector(e.cvv),a=t.querySelector(e.cardholderName),s=t.querySelector(e.button);if(!(n&&r&&o&&s))throw new i("Required card input elements not found in container");return{cardNumber:n,expiryDate:r,cvv:o,cardholderName:a,button:s}}convertPaymentButtonSelectorsToElements(e){const t=document.querySelector(e.paypal),n=document.querySelector(e.googlePay),r=document.querySelector(e.applePay);if(!t||!n||!r)throw new i("Required payment button elements not found in container");return{paypal:t,googlePay:n,applePay:r}}async _initializePrimerCheckout(){const e=this.getContainer();if(!e)throw new i(`Checkout container not found: ${this.checkoutConfig.container}`);let t,n,r;if(this.checkoutConfig.cardSelectors&&this.checkoutConfig.paymentButtonSelectors)this.checkoutConfig.paymentMethodOrder&&console.warn("paymentMethodOrder is using only for default skin and will be ignored if you are using custom checkout"),t=this.convertCardSelectorsToElements(this.checkoutConfig.cardSelectors,e),n=this.convertPaymentButtonSelectorsToElements(this.checkoutConfig.paymentButtonSelectors),r=this.getCheckoutOptions({});else{this.checkoutConfig.paymentMethodOrder=this.checkoutConfig.paymentMethodOrder||x;const e=await this.getDefaultSkinCheckoutOptions();if(!e.cardElements||!e.paymentButtonElements)throw new i("Default skin must provide cardSelectors and paymentButtonSelectors");t=e.cardElements,n=e.paymentButtonElements,r=this.getCheckoutOptions(e)}r=y(r,this.isCollectingApplePayEmail?{applePay:D}:{}),await this.primerWrapper.renderCheckout(this.clientToken,r,{container:e,cardElements:t,paymentButtonElements:n,onSubmit:this.handleSubmit,onInputChange:this.handleInputChange,onMethodRender:this.handleMethodRender,onMethodsAvailable:this.handleMethodsAvailable,onMethodRenderError:this.handleMethodRenderError})}async _processPaymentResult(e,t){switch(e.orderId&&(this.orderId=e.orderId),e.type){case"success":this._setState("completed"),this.emit(w.SUCCESS,{orderId:e.orderId,status:e.status}),t.handleSuccess();break;case"action_required":this._setState("action_required"),this.clientToken=e.clientToken,t.continueWithNewClientToken(e.clientToken);break;case"processing":this._setState("processing"),setTimeout(()=>{t.handleFailure("Payment is still processing. Please check back later.")},3e4);break;default:throw new i(`Unknown payment result type: ${e.type}`)}}getCheckoutOptions(e){let t=!1;return{...this.checkoutConfig,...e,onTokenizeSuccess:this.handleTokenizeSuccess,onResumeSuccess:this.handleResumeSuccess,onResumeError:e=>{e.stack?.includes("PROCESSOR_3DS")&&"RESUME_ERROR"===e.code&&e.message?.includes("fetch resume key")||this.emit(w.PURCHASE_FAILURE,e)},onCheckoutFail:e=>{this.emit(w.PURCHASE_FAILURE,e)},onTokenizeError:e=>{this.emit(w.PURCHASE_FAILURE,e)},onTokenizeStart:()=>{t=!0},onTokenizeShouldStart:e=>(this.emit(w.ERROR,void 0),this.emit(w.START_PURCHASE,e.paymentMethodType),!0),onPaymentMethodAction:e=>{switch(e){case"PAYMENT_METHOD_SELECTED":this.emit(w.ERROR,void 0);break;case"PAYMENT_METHOD_UNSELECTED":t||this.emit(w.PURCHASE_CANCELLED),t=!1}}}}async updatePrice(e,t){if(this._ensureNotDestroyed(),function(e,t){var n;if(0===(n=e,n?.trim()||"").length)throw new r(t,"must be a non-empty string",e)}(e,"priceId"),"processing"===this.state)throw new i("Cannot update price while payment is processing");try{this._setState("updating"),K.sessionCache.clear(),await this.apiClient.updateClientSession({orderId:this.orderId,clientToken:this.clientToken,priceId:e,clientMetadata:t}),this.checkoutConfig.priceId=e,this._setState("ready")}catch(e){throw this._setState("error"),this.emit(w.ERROR,e),e}}getStatus(){return{id:this.id,state:this.state,orderId:this.orderId,priceId:this.checkoutConfig.priceId,isDestroyed:this.isDestroyed}}async destroy(){if(!this.isDestroyed)try{K.sessionCache.clear(),await this.primerWrapper.destroy(),this._setState("destroyed"),this.orderId=null,this.clientToken=null,this.isDestroyed=!0,this.emit(w.DESTROY),this.removeAllListeners()}catch(e){console.warn("Error during checkout cleanup:",e)}}_setState(e){if(this.state!==e){const t=this.state;this.state=e,this.emit(w.STATUS_CHANGE,e,t)}}_ensureNotDestroyed(){if(this.isDestroyed)throw new i("Checkout instance has been destroyed")}getContainer(){return document.querySelector(this.checkoutConfig.container)}isInState(e){return this.state===e}isReady(){return"ready"===this.state&&!this.isDestroyed}isProcessing(){return["processing","action_required"].includes(this.state)}async getDefaultSkinCheckoutOptions(){const e=(await Promise.resolve().then(function(){return ce})).default,t=await e(this.checkoutConfig);return this.on(w.INPUT_ERROR,t.onInputError),this.on(w.STATUS_CHANGE,t.onStatusChange),this.on(w.ERROR,e=>t.onError(e)),this.on(w.LOADER_CHANGE,t.onLoaderChange),this.on(w.DESTROY,t.onDestroy),this.on(w.SUCCESS,t.onSuccess),this.on(w.START_PURCHASE,t.onStartPurchase),this.on(w.PURCHASE_FAILURE,t.onPurchaseFailure),this.on(w.PURCHASE_COMPLETED,t.onPurchaseCompleted),this.on(w.METHODS_AVAILABLE,t.onMethodsAvailable),this.on(w.METHODS_AVAILABLE,this.hideInitializingLoader),t.getCheckoutOptions()}async getCardDefaultSkinCheckoutOptions(e){const t=new(0,(await Promise.resolve().then(function(){return ie})).default)(e,this.checkoutConfig);return t.init(),this.on(w.INPUT_ERROR,t.onInputError),this.on(w.METHOD_RENDER,t.onMethodRender),this.on(w.SUCCESS,t.onDestroy),this.on(w.DESTROY,t.onDestroy),t.getCheckoutOptions()}showInitializingLoader(){(e=>{const t=document.querySelector(e);t&&(t.innerHTML=O)})(this.checkoutConfig.container)}hideInitializingLoader(){(()=>{const e=document.querySelector(j.loaderContainer);e&&e.remove()})()}async initMethod(t,n,r){this._ensureNotDestroyed(),this.isReady()||await this.createSession(),r.onRenderSuccess&&this.on(w.METHOD_RENDER,r.onRenderSuccess),r.onRenderError&&this.on(w.METHOD_RENDER_ERROR,r.onRenderError),r.onLoaderChange&&this.on(w.LOADER_CHANGE,r.onLoaderChange),r.onPaymentSuccess&&this.on(w.SUCCESS,r.onPaymentSuccess),r.onPaymentFail&&this.on(w.PURCHASE_FAILURE,r.onPaymentFail),r.onPaymentCancel&&this.on(w.PURCHASE_CANCELLED,r.onPaymentCancel),r.onErrorMessageChange&&this.on(w.ERROR,r.onErrorMessageChange),r.onPaymentStarted&&this.on(w.START_PURCHASE,r.onPaymentStarted),r.onMethodsAvailable&&this.on(w.METHODS_AVAILABLE,r.onMethodsAvailable);let o=this.getCheckoutOptions(this.isCollectingApplePayEmail?{applePay:D}:{}),a={onMethodRender:this.handleMethodRender,onMethodRenderError:this.handleMethodRenderError};if(t===e.PaymentMethod.PAYMENT_CARD){const e=await this.getCardDefaultSkinCheckoutOptions(n);o=this.getCheckoutOptions({...e}),a={cardElements:e.cardElements,onSubmit:this.handleSubmit,onInputChange:this.handleInputChange,onMethodRender:this.handleMethodRender,onMethodRenderError:this.handleMethodRenderError}}await this.primerWrapper.initializeHeadlessCheckout(this.clientToken,o);const i=await this.primerWrapper.initMethod(t,n,a);return{...i,destroy:async()=>{await i.destroy(),await this.destroy()}}}}function W(e,t){const n=new URLSearchParams({message:t.message,code:t.code,timestamp:Date.now().toString(),sdk_version:E});t.req_id&&n.append("req_id",t.req_id);const r=`https://billing.funnelfox.com/sdk_report/${encodeURIComponent(e)}/crash?${n.toString()}`,o=new Image;o.src=r,o.style.display="none",document.body.appendChild(o)}K.sessionCache=new Map;let J=null;function X(e){J=e}function ee(e,t){const{orgId:n,apiConfig:r}=e||{},o=n||J?.orgId;if(!o)throw new Error(`orgId is required. Pass it to ${t}() or call configure() first.`);return{orgId:o,baseUrl:r?.baseUrl||J?.baseUrl||M.BASE_URL,region:r?.region||J?.region||M.REGION}}async function te(e){try{const{...t}=e,n=new T;await n.ensurePrimerLoaded();const r=ee(e,"createCheckout"),o=new K({...r,checkoutConfig:{...t}});return await o.initialize(),o}catch(t){throw W(e.orgId,{message:t.message,code:t.code,req_id:t?.response?.req_id}),t}}async function ne(e){const{priceId:t,externalId:n,email:r,clientMetadata:o,countryCode:a}=e,i=ee(e,"createClientSession"),s=new N({baseUrl:i.baseUrl,orgId:i.orgId,timeout:M.REQUEST_TIMEOUT,retryAttempts:M.RETRY_ATTEMPTS}),d=await s.createClientSession({priceId:t,externalId:n,email:r,region:i.region,clientMetadata:o,countryCode:a});return s.processSessionResponse(d)}async function re(t){try{const n=new N({baseUrl:t.baseUrl,orgId:t.orgId}),r=await n.createSimpleClientSession({countryCode:t.countryCode}),o=r?.data?.client_token;if(!o)throw new Error("Error creating simple client session");return await new Promise((t,n)=>{const r=new T;r.initializeHeadlessCheckout(o,{onTokenizeSuccess:()=>{},onResumeSuccess:()=>{},onAvailablePaymentMethodsLoad:e=>{t(e),r.destroy()},paypal:_[e.PaymentMethod.PAYPAL]}).catch(n)})}catch(e){throw W(t.orgId,{message:e.message,code:e.code,req_id:e?.response?.req_id}),e}}const oe={configure:X,createCheckout:te,createClientSession:ne,initMethod:async function(t,n,r){try{const o=new K({orgId:r.orgId,baseUrl:r.baseUrl,checkoutConfig:{priceId:r.priceId,customer:{externalId:r.externalId,email:r.email},container:"",clientMetadata:r.meta,card:r.card,style:r.style,applePay:{..._[e.PaymentMethod.APPLE_PAY],...r.applePay||{}},paypal:{..._[e.PaymentMethod.PAYPAL],...r.paypal||{}},googlePay:{..._[e.PaymentMethod.GOOGLE_PAY],...r.googlePay||{}}}});return await o.initMethod(t,n,{onRenderSuccess:r.onRenderSuccess,onRenderError:r.onRenderError,onLoaderChange:r.onLoaderChange,onPaymentSuccess:r.onPaymentSuccess,onPaymentFail:r.onPaymentFail,onPaymentCancel:r.onPaymentCancel,onErrorMessageChange:r.onErrorMessageChange,onPaymentStarted:r.onPaymentStarted,onMethodsAvailable:r.onMethodsAvailable})}catch(e){throw W(r.orgId,{message:e.message,code:e.code,req_id:e?.response?.req_id}),e}},silentPurchase:async function(e){const{priceId:t,externalId:n,clientMetadata:r,orgId:a,baseUrl:i}=e,s=new N({baseUrl:i,orgId:a,timeout:M.REQUEST_TIMEOUT,retryAttempts:M.RETRY_ATTEMPTS});try{const e=await s.oneClick({pp_ident:t,external_id:n,client_metadata:r});if("success"!==e.status&&e.error.some(({code:e})=>"double_purchase"===e))throw new o("This product was already purchased");return"success"===e.status}catch(e){throw W(a,{message:e.message,code:e.code,req_id:e?.response?.req_id}),e}},getAvailablePaymentMethods:re};"undefined"!=typeof window&&(window.Billing=oe);"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent="/* Main container */\n.ff-skin-default {\n display: flex;\n flex-direction: column;\n text-align: left;\n gap: 8px;\n width: 100%;\n max-width: 400px;\n margin: 0 auto;\n color: #000000;\n}\n\n/* Payment method cards */\n.ff-payment-method-card {\n display: none;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n background-color: #ffffff;\n padding: 20px;\n transition: border-color 0.2s ease;\n height: auto;\n box-shadow: 0px 0px 10px 0px #eee;\n}\n\n.ff-payment-method-card.visible {\n display: block;\n}\n\n.payment-errors-container {\n background-color: #d1000033;\n color: #d10000;\n font-size: 14px;\n padding: 16px 12px;\n border-radius: 8px;\n}\n.payment-errors-container:empty {\n display: none;\n}\n\n/* Label wrapper */\n.ff-payment-method-label {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n cursor: pointer;\n width: 100%;\n}\n\n.ff-google-pay-header {\n align-items: center;\n}\n\n/* Custom radio button styling */\n.ff-payment-method-radio {\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n width: 24px;\n height: 24px;\n min-width: 24px;\n min-height: 24px;\n border: 1px solid #9e9e9e;\n border-radius: 50%;\n background-color: #ffffff;\n cursor: pointer;\n position: relative;\n margin: 0;\n flex-shrink: 0;\n transition: border-color 0.2s ease;\n}\n\n.ff-card-form-submit-button {\n display: block;\n cursor: pointer;\n width: 100%;\n padding: 16px 0;\n border-radius: 16px;\n background-color: #000000;\n color: #ffffff;\n border: none;\n font-size: 16px;\n margin: 12px 0 16px;\n}\n\n.ff-payment-method-radio:checked {\n border-color: #e32f41;\n background-color: #ffffff;\n}\n\n.ff-payment-method-radio:checked::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background-color: #e32f41;\n}\n\n/* Payment method content */\n.ff-payment-method-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-height: 0;\n height: 0;\n overflow: hidden;\n opacity: 0;\n transition:\n opacity 0.3s ease,\n margin-top 0.3s ease;\n margin-top: 0;\n}\n\n.ff-payment-method-card.expanded .ff-payment-method-content {\n max-height: 2000px;\n height: auto;\n opacity: 1;\n margin-top: 16px;\n}\n.ff-payment-method-card.expanded .ff-payment-method-label {\n margin-bottom: 16px;\n}\n\n/* Payment method header */\n.ff-payment-method-header {\n display: flex;\n align-items: center;\n}\n\n/* Google Pay Logo */\n.ff-google-pay-logo {\n display: flex;\n align-items: center;\n gap: 4px;\n font-weight: 500;\n font-size: 18px;\n}\n.ff-google-pay-logo img {\n height: 38px;\n}\n\n/* Payment features list */\n.ff-payment-features {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.ff-payment-feature {\n display: flex;\n align-items: baseline;\n text-align: left;\n gap: 8px;\n}\n\n.ff-checkmark-icon {\n width: 20px;\n height: 20px;\n min-width: 20px;\n color: #e32f41;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.ff-payment-feature span {\n color: #333333;\n font-size: 14px;\n line-height: 1.5;\n}\n\n/* Google Pay button container */\n.ff-google-pay-button-container {\n display: flex;\n justify-content: center;\n}\n\n/* Security message */\n.ff-security-message {\n text-align: center;\n color: #999999;\n font-size: 14px;\n padding: 0;\n margin: 0\n}\n\n/* Card logos container */\n.ff-card-logos {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n/* Card form container */\n.ff-card-form-container {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.loader-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255);\n z-index: 2;\n}\n\n.payment-button-loader {\n position: relative;\n height: 50px;\n}\n\n.loader {\n width: 24px;\n height: 24px;\n border: 4px solid #e32f41;\n border-top: 4px solid transparent;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .ff-payment-method-card {\n padding: 16px;\n }\n\n .ff-payment-method-label {\n gap: 12px;\n }\n\n .ff-card-logos {\n gap: 8px;\n }\n}\n\n.ff-payment-container {\n position: relative;\n}\n\n.success {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n}\n");"undefined"!=typeof document&&(document.head.appendChild(document.createElement("style")).textContent="\n\n.ff-card-form-label {\n display: block;\n font-size: 16px;\n margin-bottom: 5px;\n }\n \n .card-form-row {\n display: flex;\n flex-direction: row;\n gap: 10px;\n }\n \n .ff-card-form-cardholder-input {\n margin: 0 0 3px;\n padding-left: 10px;\n padding-right: 10px;\n box-sizing: border-box;\n height: 36px;\n width: 100%;\n font-size: 1rem;\n background-color: transparent;\n border: 1px solid rgb(0 0 0 / 10%);\n border-radius: 6px;\n transition: all 0.3s ease;\n box-shadow: none;\n outline: none;\n }\n .ff-card-form-cardholder-input.error {\n border-color: #e32f41;\n }\n \n .errorContainer:not(:empty) {\n color: #d10000;\n font-size: 16px;\n line-height: 1;\n margin: 0 0 10px;\n }\n\n #cvvInput {\n position: relative;\n }\n \n #cvvInput > svg {\n z-index: 1;\n position: absolute;\n top: 5px;\n right: 5px;\n width: 26px;\n height: 26px;\n }");class ae{constructor(e,t){if(this.onInputError=e=>{const{name:t,error:n}=e,r=this.getCardInputElements(),o={cardNumber:r.cardNumber.parentElement,expiryDate:r.expiryDate.parentElement,cvv:r.cvv.parentElement,cardholderName:r.cardholderName?.parentElement},a=o[t]?.querySelector(".errorContainer");a&&(a.textContent=n||""),"cardholderName"===t&&(n?r.cardholderName?.classList?.add("error"):r.cardholderName?.classList?.remove("error"))},this.onMethodRender=()=>{this.containerEl.style.display="block"},this.onDestroy=()=>{this.containerEl.innerHTML&&(this.containerEl.innerHTML="")},!e)throw new Error("Container element not found");this.containerEl=e,this.checkoutConfig=t,this.containerEl.style.display="none"}wireCardInputs(){const e=this.containerEl.querySelector("#cardNumberInput"),t=this.containerEl.querySelector("#expiryInput"),n=this.containerEl.querySelector("#cvvInput"),r=!!this.checkoutConfig?.card?.cardholderName?.required;let o;if(r?o=this.containerEl.querySelector("#cardHolderInput"):this.containerEl.querySelector("#cardHolderInput").parentElement.style.display="none",!e||!t||!n||r&&!o)throw new Error("One or more card input elements are missing in the default skin");this.cardInputElements={cardNumber:e,expiryDate:t,cvv:n,cardholderName:o}}async init(){this.containerEl.insertAdjacentHTML("afterbegin",'<div>\n <label class="ff-card-form-label" for="cardNumberInput">Card number</label>\n <div id="cardNumberInput"></div>\n <div class="errorContainer"></div>\n</div>\n<div class="card-form-row">\n <div>\n <label class="ff-card-form-label" for="expiryInput">Expiration date</label>\n <div id="expiryInput"></div>\n <div class="errorContainer"></div>\n </div>\n <div>\n <label class="ff-card-form-label" for="cvvInput">Security code</label>\n <div id="cvvInput">\n <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">\n <rect width="200" height="200" fill="transparent"/>\n <g clip-path="url(#clip0_0_1)">\n <path d="M157.555 23C168.279 23.0002 177 31.7394 177 42.4854V80.5889C171.946 72.0151 164.749 64.8558 156.146 59.8457H166.394V42.4854C166.393 37.6004 162.43 33.6291 157.555 33.6289H27.4453C22.5704 33.6291 18.6066 37.6004 18.6064 42.4854V59.8457H97.8535C88.9153 65.0512 81.4954 72.5771 76.4189 81.5986H18.6064V127.515C18.6066 132.4 22.5704 136.371 27.4453 136.371H75.3281C77.2742 140.177 79.6285 143.739 82.333 147H27.4453C16.7215 147 8.00019 138.261 8 127.515V42.4854C8.0002 31.7394 16.7215 23.0002 27.4453 23H157.555Z" fill="#93939A"/>\n <mask id="path-2-outside-1_0_1" maskUnits="userSpaceOnUse" x="68.5012" y="52.0311" width="135" height="135" fill="black">\n <rect fill="white" x="68.5012" y="52.0311" width="135" height="135"/>\n <path d="M190.242 160.457L170.136 140.351C166.533 145.552 162.023 150.063 156.821 153.666L176.927 173.772C178.693 175.538 181.088 176.53 183.585 176.53C186.082 176.53 188.477 175.538 190.242 173.772C192.008 172.007 193 169.612 193 167.115C193 164.618 192.008 162.223 190.242 160.457ZM126.436 157.901C116.955 157.901 107.688 155.089 99.8048 149.822C91.922 144.555 85.7781 137.069 82.15 128.31C78.5219 119.551 77.5727 109.913 79.4222 100.614C81.2718 91.3158 85.8371 82.7746 92.5409 76.0708C99.2447 69.367 107.786 64.8017 117.084 62.9521C126.383 61.1026 136.021 62.0518 144.78 65.6799C153.539 69.308 161.025 75.4519 166.292 83.3347C171.559 91.2175 174.371 100.485 174.371 109.966C174.371 122.679 169.32 134.871 160.331 143.861C151.341 152.85 139.149 157.901 126.436 157.901ZM163.719 109.966C163.719 102.592 161.532 95.3838 157.435 89.2527C153.339 83.1216 147.516 78.343 140.703 75.5212C133.891 72.6994 126.395 71.9611 119.162 73.3996C111.93 74.8382 105.287 78.389 100.073 83.6031C94.8591 88.8171 91.3083 95.4602 89.8697 102.692C88.4312 109.924 89.1695 117.421 91.9913 124.233C94.8131 131.046 99.5918 136.869 105.723 140.965C111.854 145.062 119.062 147.248 126.436 147.248C136.324 147.248 145.807 143.32 152.799 136.329C159.791 129.337 163.719 119.854 163.719 109.966ZM133.645 102.757C133.398 102.51 133.104 102.313 132.781 102.179C132.458 102.046 132.112 101.977 131.762 101.977C131.412 101.977 131.066 102.046 130.743 102.179C130.42 102.313 130.126 102.51 129.879 102.757L126.436 106.2L122.993 102.757C122.49 102.272 121.818 102.003 121.119 102.01C120.421 102.016 119.753 102.296 119.26 102.789C118.766 103.283 118.486 103.951 118.48 104.649C118.474 105.348 118.742 106.02 119.227 106.523L122.67 109.966L119.227 113.409C118.973 113.655 118.77 113.949 118.63 114.274C118.491 114.598 118.417 114.948 118.414 115.301C118.411 115.655 118.479 116.006 118.612 116.333C118.746 116.66 118.944 116.958 119.194 117.208C119.444 117.458 119.741 117.655 120.069 117.789C120.396 117.923 120.747 117.991 121.1 117.988C121.454 117.985 121.803 117.911 122.128 117.771C122.453 117.632 122.747 117.429 122.993 117.175L126.436 113.732L129.879 117.175C130.382 117.66 131.054 117.928 131.752 117.922C132.451 117.916 133.119 117.636 133.612 117.142C134.106 116.648 134.386 115.981 134.392 115.282C134.398 114.584 134.13 113.911 133.645 113.409L130.202 109.966L133.645 106.523C133.892 106.275 134.088 105.982 134.222 105.659C134.356 105.336 134.425 104.989 134.425 104.64C134.425 104.29 134.356 103.944 134.222 103.621C134.088 103.298 133.892 103.004 133.645 102.757ZM112.34 102.757C112.093 102.51 111.8 102.313 111.477 102.179C111.154 102.046 110.807 101.977 110.458 101.977C110.108 101.977 109.762 102.046 109.439 102.179C109.116 102.313 108.822 102.51 108.575 102.757L105.132 106.2L101.688 102.757C101.186 102.272 100.513 102.003 99.8151 102.01C99.1169 102.016 98.4489 102.296 97.9552 102.789C97.4614 103.283 97.1814 103.951 97.1753 104.649C97.1692 105.348 97.4377 106.02 97.9227 106.523L101.366 109.966L97.9227 113.409C97.6684 113.655 97.4655 113.949 97.326 114.274C97.1864 114.598 97.1129 114.948 97.1098 115.301C97.1068 115.655 97.1742 116.006 97.3081 116.333C97.442 116.66 97.6397 116.958 97.8897 117.208C98.1398 117.458 98.4371 117.655 98.7644 117.789C99.0917 117.923 99.4423 117.991 99.7959 117.988C100.15 117.985 100.499 117.911 100.824 117.771C101.149 117.632 101.443 117.429 101.688 117.175L105.132 113.732L108.575 117.175C109.077 117.66 109.75 117.928 110.448 117.922C111.146 117.916 111.814 117.636 112.308 117.142C112.802 116.648 113.082 115.981 113.088 115.282C113.094 114.584 112.826 113.911 112.34 113.409L108.897 109.966L112.34 106.523C112.588 106.275 112.784 105.982 112.918 105.659C113.052 105.336 113.121 104.989 113.121 104.64C113.121 104.29 113.052 103.944 112.918 103.621C112.784 103.298 112.588 103.004 112.34 102.757ZM151.506 109.966L154.949 106.523C155.434 106.02 155.703 105.348 155.697 104.649C155.691 103.951 155.41 103.283 154.917 102.789C154.423 102.296 153.755 102.016 153.057 102.01C152.359 102.003 151.686 102.272 151.184 102.757L147.74 106.2L144.297 102.757C143.795 102.272 143.122 102.003 142.424 102.01C141.726 102.016 141.058 102.296 140.564 102.789C140.07 103.283 139.79 103.951 139.784 104.649C139.778 105.348 140.046 106.02 140.531 106.523L143.974 109.966L140.531 113.409C140.277 113.655 140.074 113.949 139.935 114.274C139.795 114.598 139.722 114.948 139.719 115.301C139.715 115.655 139.783 116.006 139.917 116.333C140.051 116.66 140.248 116.958 140.498 117.208C140.748 117.458 141.046 117.655 141.373 117.789C141.7 117.923 142.051 117.991 142.405 117.988C142.758 117.985 143.108 117.911 143.433 117.771C143.757 117.632 144.051 117.429 144.297 117.175L147.74 113.732L151.184 117.175C151.686 117.66 152.359 117.928 153.057 117.922C153.755 117.916 154.423 117.636 154.917 117.142C155.41 116.648 155.691 115.981 155.697 115.282C155.703 114.584 155.434 113.911 154.949 113.409L151.506 109.966Z"/>\n </mask>\n <path d="M190.242 160.457L170.136 140.351C166.533 145.552 162.023 150.063 156.821 153.666L176.927 173.772C178.693 175.538 181.088 176.53 183.585 176.53C186.082 176.53 188.477 175.538 190.242 173.772C192.008 172.007 193 169.612 193 167.115C193 164.618 192.008 162.223 190.242 160.457ZM126.436 157.901C116.955 157.901 107.688 155.089 99.8048 149.822C91.922 144.555 85.7781 137.069 82.15 128.31C78.5219 119.551 77.5727 109.913 79.4222 100.614C81.2718 91.3158 85.8371 82.7746 92.5409 76.0708C99.2447 69.367 107.786 64.8017 117.084 62.9521C126.383 61.1026 136.021 62.0518 144.78 65.6799C153.539 69.308 161.025 75.4519 166.292 83.3347C171.559 91.2175 174.371 100.485 174.371 109.966C174.371 122.679 169.32 134.871 160.331 143.861C151.341 152.85 139.149 157.901 126.436 157.901ZM163.719 109.966C163.719 102.592 161.532 95.3838 157.435 89.2527C153.339 83.1216 147.516 78.343 140.703 75.5212C133.891 72.6994 126.395 71.9611 119.162 73.3996C111.93 74.8382 105.287 78.389 100.073 83.6031C94.8591 88.8171 91.3083 95.4602 89.8697 102.692C88.4312 109.924 89.1695 117.421 91.9913 124.233C94.8131 131.046 99.5918 136.869 105.723 140.965C111.854 145.062 119.062 147.248 126.436 147.248C136.324 147.248 145.807 143.32 152.799 136.329C159.791 129.337 163.719 119.854 163.719 109.966ZM133.645 102.757C133.398 102.51 133.104 102.313 132.781 102.179C132.458 102.046 132.112 101.977 131.762 101.977C131.412 101.977 131.066 102.046 130.743 102.179C130.42 102.313 130.126 102.51 129.879 102.757L126.436 106.2L122.993 102.757C122.49 102.272 121.818 102.003 121.119 102.01C120.421 102.016 119.753 102.296 119.26 102.789C118.766 103.283 118.486 103.951 118.48 104.649C118.474 105.348 118.742 106.02 119.227 106.523L122.67 109.966L119.227 113.409C118.973 113.655 118.77 113.949 118.63 114.274C118.491 114.598 118.417 114.948 118.414 115.301C118.411 115.655 118.479 116.006 118.612 116.333C118.746 116.66 118.944 116.958 119.194 117.208C119.444 117.458 119.741 117.655 120.069 117.789C120.396 117.923 120.747 117.991 121.1 117.988C121.454 117.985 121.803 117.911 122.128 117.771C122.453 117.632 122.747 117.429 122.993 117.175L126.436 113.732L129.879 117.175C130.382 117.66 131.054 117.928 131.752 117.922C132.451 117.916 133.119 117.636 133.612 117.142C134.106 116.648 134.386 115.981 134.392 115.282C134.398 114.584 134.13 113.911 133.645 113.409L130.202 109.966L133.645 106.523C133.892 106.275 134.088 105.982 134.222 105.659C134.356 105.336 134.425 104.989 134.425 104.64C134.425 104.29 134.356 103.944 134.222 103.621C134.088 103.298 133.892 103.004 133.645 102.757ZM112.34 102.757C112.093 102.51 111.8 102.313 111.477 102.179C111.154 102.046 110.807 101.977 110.458 101.977C110.108 101.977 109.762 102.046 109.439 102.179C109.116 102.313 108.822 102.51 108.575 102.757L105.132 106.2L101.688 102.757C101.186 102.272 100.513 102.003 99.8151 102.01C99.1169 102.016 98.4489 102.296 97.9552 102.789C97.4614 103.283 97.1814 103.951 97.1753 104.649C97.1692 105.348 97.4377 106.02 97.9227 106.523L101.366 109.966L97.9227 113.409C97.6684 113.655 97.4655 113.949 97.326 114.274C97.1864 114.598 97.1129 114.948 97.1098 115.301C97.1068 115.655 97.1742 116.006 97.3081 116.333C97.442 116.66 97.6397 116.958 97.8897 117.208C98.1398 117.458 98.4371 117.655 98.7644 117.789C99.0917 117.923 99.4423 117.991 99.7959 117.988C100.15 117.985 100.499 117.911 100.824 117.771C101.149 117.632 101.443 117.429 101.688 117.175L105.132 113.732L108.575 117.175C109.077 117.66 109.75 117.928 110.448 117.922C111.146 117.916 111.814 117.636 112.308 117.142C112.802 116.648 113.082 115.981 113.088 115.282C113.094 114.584 112.826 113.911 112.34 113.409L108.897 109.966L112.34 106.523C112.588 106.275 112.784 105.982 112.918 105.659C113.052 105.336 113.121 104.989 113.121 104.64C113.121 104.29 113.052 103.944 112.918 103.621C112.784 103.298 112.588 103.004 112.34 102.757ZM151.506 109.966L154.949 106.523C155.434 106.02 155.703 105.348 155.697 104.649C155.691 103.951 155.41 103.283 154.917 102.789C154.423 102.296 153.755 102.016 153.057 102.01C152.359 102.003 151.686 102.272 151.184 102.757L147.74 106.2L144.297 102.757C143.795 102.272 143.122 102.003 142.424 102.01C141.726 102.016 141.058 102.296 140.564 102.789C140.07 103.283 139.79 103.951 139.784 104.649C139.778 105.348 140.046 106.02 140.531 106.523L143.974 109.966L140.531 113.409C140.277 113.655 140.074 113.949 139.935 114.274C139.795 114.598 139.722 114.948 139.719 115.301C139.715 115.655 139.783 116.006 139.917 116.333C140.051 116.66 140.248 116.958 140.498 117.208C140.748 117.458 141.046 117.655 141.373 117.789C141.7 117.923 142.051 117.991 142.405 117.988C142.758 117.985 143.108 117.911 143.433 117.771C143.757 117.632 144.051 117.429 144.297 117.175L147.74 113.732L151.184 117.175C151.686 117.66 152.359 117.928 153.057 117.922C153.755 117.916 154.423 117.636 154.917 117.142C155.41 116.648 155.691 115.981 155.697 115.282C155.703 114.584 155.434 113.911 154.949 113.409L151.506 109.966Z" fill="#93939A"/>\n <path d="M190.242 160.457L170.136 140.351C166.533 145.552 162.023 150.063 156.821 153.666L176.927 173.772C178.693 175.538 181.088 176.53 183.585 176.53C186.082 176.53 188.477 175.538 190.242 173.772C192.008 172.007 193 169.612 193 167.115C193 164.618 192.008 162.223 190.242 160.457ZM126.436 157.901C116.955 157.901 107.688 155.089 99.8048 149.822C91.922 144.555 85.7781 137.069 82.15 128.31C78.5219 119.551 77.5727 109.913 79.4222 100.614C81.2718 91.3158 85.8371 82.7746 92.5409 76.0708C99.2447 69.367 107.786 64.8017 117.084 62.9521C126.383 61.1026 136.021 62.0518 144.78 65.6799C153.539 69.308 161.025 75.4519 166.292 83.3347C171.559 91.2175 174.371 100.485 174.371 109.966C174.371 122.679 169.32 134.871 160.331 143.861C151.341 152.85 139.149 157.901 126.436 157.901ZM163.719 109.966C163.719 102.592 161.532 95.3838 157.435 89.2527C153.339 83.1216 147.516 78.343 140.703 75.5212C133.891 72.6994 126.395 71.9611 119.162 73.3996C111.93 74.8382 105.287 78.389 100.073 83.6031C94.8591 88.8171 91.3083 95.4602 89.8697 102.692C88.4312 109.924 89.1695 117.421 91.9913 124.233C94.8131 131.046 99.5918 136.869 105.723 140.965C111.854 145.062 119.062 147.248 126.436 147.248C136.324 147.248 145.807 143.32 152.799 136.329C159.791 129.337 163.719 119.854 163.719 109.966ZM133.645 102.757C133.398 102.51 133.104 102.313 132.781 102.179C132.458 102.046 132.112 101.977 131.762 101.977C131.412 101.977 131.066 102.046 130.743 102.179C130.42 102.313 130.126 102.51 129.879 102.757L126.436 106.2L122.993 102.757C122.49 102.272 121.818 102.003 121.119 102.01C120.421 102.016 119.753 102.296 119.26 102.789C118.766 103.283 118.486 103.951 118.48 104.649C118.474 105.348 118.742 106.02 119.227 106.523L122.67 109.966L119.227 113.409C118.973 113.655 118.77 113.949 118.63 114.274C118.491 114.598 118.417 114.948 118.414 115.301C118.411 115.655 118.479 116.006 118.612 116.333C118.746 116.66 118.944 116.958 119.194 117.208C119.444 117.458 119.741 117.655 120.069 117.789C120.396 117.923 120.747 117.991 121.1 117.988C121.454 117.985 121.803 117.911 122.128 117.771C122.453 117.632 122.747 117.429 122.993 117.175L126.436 113.732L129.879 117.175C130.382 117.66 131.054 117.928 131.752 117.922C132.451 117.916 133.119 117.636 133.612 117.142C134.106 116.648 134.386 115.981 134.392 115.282C134.398 114.584 134.13 113.911 133.645 113.409L130.202 109.966L133.645 106.523C133.892 106.275 134.088 105.982 134.222 105.659C134.356 105.336 134.425 104.989 134.425 104.64C134.425 104.29 134.356 103.944 134.222 103.621C134.088 103.298 133.892 103.004 133.645 102.757ZM112.34 102.757C112.093 102.51 111.8 102.313 111.477 102.179C111.154 102.046 110.807 101.977 110.458 101.977C110.108 101.977 109.762 102.046 109.439 102.179C109.116 102.313 108.822 102.51 108.575 102.757L105.132 106.2L101.688 102.757C101.186 102.272 100.513 102.003 99.8151 102.01C99.1169 102.016 98.4489 102.296 97.9552 102.789C97.4614 103.283 97.1814 103.951 97.1753 104.649C97.1692 105.348 97.4377 106.02 97.9227 106.523L101.366 109.966L97.9227 113.409C97.6684 113.655 97.4655 113.949 97.326 114.274C97.1864 114.598 97.1129 114.948 97.1098 115.301C97.1068 115.655 97.1742 116.006 97.3081 116.333C97.442 116.66 97.6397 116.958 97.8897 117.208C98.1398 117.458 98.4371 117.655 98.7644 117.789C99.0917 117.923 99.4423 117.991 99.7959 117.988C100.15 117.985 100.499 117.911 100.824 117.771C101.149 117.632 101.443 117.429 101.688 117.175L105.132 113.732L108.575 117.175C109.077 117.66 109.75 117.928 110.448 117.922C111.146 117.916 111.814 117.636 112.308 117.142C112.802 116.648 113.082 115.981 113.088 115.282C113.094 114.584 112.826 113.911 112.34 113.409L108.897 109.966L112.34 106.523C112.588 106.275 112.784 105.982 112.918 105.659C113.052 105.336 113.121 104.989 113.121 104.64C113.121 104.29 113.052 103.944 112.918 103.621C112.784 103.298 112.588 103.004 112.34 102.757ZM151.506 109.966L154.949 106.523C155.434 106.02 155.703 105.348 155.697 104.649C155.691 103.951 155.41 103.283 154.917 102.789C154.423 102.296 153.755 102.016 153.057 102.01C152.359 102.003 151.686 102.272 151.184 102.757L147.74 106.2L144.297 102.757C143.795 102.272 143.122 102.003 142.424 102.01C141.726 102.016 141.058 102.296 140.564 102.789C140.07 103.283 139.79 103.951 139.784 104.649C139.778 105.348 140.046 106.02 140.531 106.523L143.974 109.966L140.531 113.409C140.277 113.655 140.074 113.949 139.935 114.274C139.795 114.598 139.722 114.948 139.719 115.301C139.715 115.655 139.783 116.006 139.917 116.333C140.051 116.66 140.248 116.958 140.498 117.208C140.748 117.458 141.046 117.655 141.373 117.789C141.7 117.923 142.051 117.991 142.405 117.988C142.758 117.985 143.108 117.911 143.433 117.771C143.757 117.632 144.051 117.429 144.297 117.175L147.74 113.732L151.184 117.175C151.686 117.66 152.359 117.928 153.057 117.922C153.755 117.916 154.423 117.636 154.917 117.142C155.41 116.648 155.691 115.981 155.697 115.282C155.703 114.584 155.434 113.911 154.949 113.409L151.506 109.966Z" stroke="transparent" stroke-width="20" mask="url(#path-2-outside-1_0_1)"/>\n </g>\n <defs>\n <clipPath id="clip0_0_1">\n <rect width="200" height="200" fill="white"/>\n </clipPath>\n </defs>\n </svg>\n </div>\n <div class="errorContainer"></div>\n </div>\n</div>\n<div>\n <label class="ff-card-form-label" for="cardHolderInput">Card holder</label>\n <input class="ff-card-form-cardholder-input" id="cardHolderInput" placeholder="Card holder">\n <div class="errorContainer"></div>\n</div>\n'),this.wireCardInputs()}renderCardForm(){}getCardInputElements(){return this.cardInputElements}getCheckoutOptions(){return{cardElements:this.getCardInputElements(),card:{cardholderName:{required:!!this.checkoutConfig?.card?.cardholderName?.required}}}}}var ie=Object.freeze({__proto__:null,default:ae});const se={[e.PaymentMethod.PAYMENT_CARD]:'\x3c!-- Card Payments Section --\x3e\n<div class="ff-payment-method-card ff-payment-method-payment-card">\n <label class="ff-payment-method-label">\n <input type="radio" name="payment-method" value="PAYMENT_CARD" class="ff-payment-method-radio">\n <div class="ff-payment-method-header">\n <div class="ff-card-logos">\n <img class="payment-method-icon" style="max-height: 30px" src="https://assets.fnlfx.com/common/checkout/cards.webp" alt="visa, mastercard">\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <div class="ff-card-form-container ff-payment-container" id="cardForm">\n <div class="loader-container">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <button class="ff-card-form-submit-button" id="submitButton">\n Continue\n </button>\n <p class="ff-security-message">\n Your payment information is secure with SSL/TLS encryption\n </p>\n </div>\n </div>\n</div>\n',[e.PaymentMethod.PAYPAL]:'<div class="ff-payment-method-card ff-payment-method-paypal">\n <label class="ff-payment-method-label">\n <input type="radio" name="payment-method" value="PAYPAL" class="ff-payment-method-radio">\n <div class="ff-payment-method-header">\n <div class="ff-payment-logo ff-paypal-logo">\n <img class="payment-method-icon" style="max-height: 22px" src="https://assets.fnlfx.com/common/checkout/paypal.webp" alt="PayPal logo">\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <ul class="ff-payment-features">\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span> Fast, convenient payment option </span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span> Keeps your financial info safe with end-to-end encryption </span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span> Backed by PayPal’s industry-leading fraud protection </span>\n </li>\n </ul>\n <div class="ff-paypal-button-container ff-payment-container" id="paypalButton"></div>\n <div class="loader-container payment-button-loader">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <p class="ff-security-message">\n Your payment information is secure with SSL/TLS encryption\n </p>\n </div>\n</div>\n',[e.PaymentMethod.GOOGLE_PAY]:'\x3c!-- Google Pay Section --\x3e\n<div class="ff-payment-method-card ff-payment-method-google-pay">\n <label class="ff-payment-method-label ff-google-pay-header">\n <input type="radio" name="payment-method" value="GOOGLE_PAY" class="ff-payment-method-radio" checked="checked">\n <div class="ff-payment-method-header">\n <div class="ff-payment-logo ff-google-pay-logo">\n <img src="https://developers.google.com/static/pay/api/images/brand-guidelines/google-pay-mark.png" alt="Google Pay">\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <ul class="ff-payment-features">\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Easy and private payments with Face/Touch ID</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Keeps your financial info safe with end-to-end encryption</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Protected by Google Pay\'s unique Device Account Number</span>\n </li>\n </ul>\n <div class="ff-google-pay-button-container ff-payment-container" id="googlePayButton"></div>\n <div class="loader-container payment-button-loader">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <p class="ff-security-message">\n Your payment information is secure with SSL/TLS encryption\n </p>\n </div>\n</div>\n',[e.PaymentMethod.APPLE_PAY]:'\x3c!-- Apple Pay Section --\x3e\n<div class="ff-payment-method-card ff-payment-method-apple-pay">\n <label class="ff-payment-method-label">\n <input type="radio" name="payment-method" value="APPLE_PAY" class="ff-payment-method-radio">\n <div class="ff-payment-method-header">\n <div class="ff-payment-logo ff-apple-pay-logo">\n <svg class="payment-method-icon" height="26" viewBox="0 0 63 26" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path fill-rule="evenodd" clip-rule="evenodd" d="M8.41022 4.82398C9.5916 4.92293 10.773 4.23026 11.5113 3.35205C12.2374 2.4491 12.7173 1.23692 12.5943 0C11.5483 0.0494767 10.2561 0.692674 9.51777 1.59562C8.84093 2.37488 8.26255 3.63654 8.41022 4.82398ZM22.4638 20.7555V1.47193H29.6628C33.3793 1.47193 35.9758 4.04471 35.9758 7.80494C35.9758 11.5652 33.33 14.1627 29.5644 14.1627H25.4418V20.7555H22.4638ZM12.5819 5.05898C11.5411 4.99877 10.5914 5.37358 9.82438 5.67633C9.33075 5.87116 8.91274 6.03614 8.59472 6.03614C8.23784 6.03614 7.80257 5.86234 7.31387 5.66719C6.6735 5.4115 5.94138 5.11916 5.17364 5.13319C3.41387 5.15793 1.77716 6.15983 0.878819 7.75545C-0.967091 10.9467 0.398882 15.6717 2.18326 18.2693C3.05699 19.5556 4.10301 20.9657 5.48129 20.9163C6.08765 20.8933 6.52383 20.7072 6.97524 20.5147C7.49492 20.293 8.0348 20.0628 8.87776 20.0628C9.69151 20.0628 10.2078 20.287 10.7033 20.5023C11.1746 20.707 11.6271 20.9036 12.2989 20.8915C13.7264 20.8668 14.6247 19.6051 15.4984 18.3187C16.4413 16.9381 16.8557 15.5906 16.9186 15.3861C16.9222 15.3745 16.9246 15.3665 16.9259 15.3625C16.9244 15.361 16.9128 15.3556 16.8922 15.3462C16.577 15.2011 14.1679 14.0926 14.1448 11.1199C14.1216 8.62473 16.0556 7.36054 16.3601 7.16153C16.3786 7.14944 16.3911 7.14125 16.3968 7.137C15.1662 5.30636 13.2464 5.10845 12.5819 5.05898ZM41.4153 20.9039C43.2858 20.9039 45.0209 19.9515 45.8085 18.4424H45.8701V20.7555H48.6266V11.157C48.6266 8.37393 46.4115 6.5804 43.0027 6.5804C39.8401 6.5804 37.5019 8.39866 37.4158 10.8972H40.0985C40.32 9.70979 41.4153 8.93054 42.9166 8.93054C44.7379 8.93054 45.7593 9.78401 45.7593 11.3549V12.4186L42.0429 12.6413C38.5849 12.8516 36.7143 14.274 36.7143 16.7479C36.7143 19.2464 38.6464 20.9039 41.4153 20.9039ZM42.215 18.6156C40.6275 18.6156 39.6184 17.8487 39.6184 16.6736C39.6184 15.4615 40.5906 14.7564 42.4488 14.6451L45.7591 14.4348V15.5233C45.7591 17.3292 44.2332 18.6156 42.215 18.6156ZM57.7699 21.51C56.5762 24.8868 55.2103 26 52.306 26C52.0845 26 51.3461 25.9753 51.1739 25.9258V23.6127C51.3585 23.6375 51.8138 23.6622 52.0476 23.6622C53.3643 23.6622 54.1027 23.1056 54.558 21.6584L54.8288 20.8049L49.7833 6.76594H52.8967L56.4039 18.1579H56.4655L59.9727 6.76594H63L57.7699 21.51ZM25.4416 3.99524H28.875C31.4592 3.99524 32.936 5.38059 32.936 7.81731C32.936 10.254 31.4592 11.6518 28.8627 11.6518H25.4416V3.99524Z" fill="currentColor"/>\n </svg>\n </div>\n </div>\n </label>\n <div class="ff-payment-method-content">\n <ul class="ff-payment-features">\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Easy and private payments with Face/Touch ID</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Keeps your financial info safe with end-to-end encryption</span>\n </li>\n <li class="ff-payment-feature">\n <svg width="13" height="11" viewBox="0 0 13 11" fill="none">\n <path stroke="#F8545D" d="M11.1997 1.80133L6.99269 8.63774C6.68226 9.14218 5.9932 9.24721 5.54659 8.85815L2.19971 5.94254" stroke-width="2.66667" stroke-linecap="round"></path>\n </svg>\n <span>Protected by Apple Pay’s unique Device Account Number</span>\n </li>\n </ul>\n <div class="ff-apple-pay-button-container ff-payment-container" id="applePayButton"></div>\n <div class="loader-container payment-button-loader">\n <div class="loader"></div>\n </div>\n <div class="payment-errors-container"></div>\n <p class="ff-security-message">\n Your payment information is secure with Apple Pay encryption\n </p>\n </div>\n</div>\n'};class de{constructor(t){this.onLoaderChange=e=>{document.querySelectorAll(`${this.containerSelector} .loader-container`)?.forEach(t=>{t.style.display=e?"flex":"none"})},this.onError=(e,t)=>{if(!e)return void this.containerEl.querySelectorAll(".payment-errors-container")?.forEach(e=>{e.innerHTML=""});let n=null;if(t){const e=t.replace("_","-").toLowerCase();n=this.containerEl.querySelector(`.ff-payment-method-${e} .payment-errors-container`)}n&&(n.textContent=e?.message||"")},this.onStatusChange=(e,t)=>{["initializing"].includes(e)||"initializing"!==t||this.onLoaderChange(!1),"updating"===e&&this.onLoaderChange(!0),"ready"===e&&"updating"===t&&this.onLoaderChange(!1)},this.onSuccess=()=>{const e=document.querySelector("#success-screen")?.innerHTML;document.querySelectorAll(".ff-payment-container").forEach(t=>{t.innerHTML=e}),this.onLoaderChange(!1)},this.onDestroy=()=>{this.containerEl.innerHTML&&(this.containerEl.innerHTML="")},this.onInputError=e=>{this.cardInstance.onInputError(e)},this.onMethodRender=t=>{const n=t.replace("_","-").toLowerCase(),r=this.containerEl.querySelector(`.ff-payment-method-${n}`);t===e.PaymentMethod.PAYMENT_CARD&&this.cardInstance.onMethodRender(),r&&r.classList.add("visible")},this.onMethodsAvailable=e=>{this.availableMethods=e,this.initAccordion(),e.forEach(this.onMethodRender)},this.onStartPurchase=e=>{this.currentPurchaseMethod=e},this.onPurchaseFailure=e=>{this.currentPurchaseMethod&&this.onError(e,this.currentPurchaseMethod),this.currentPurchaseMethod=null},this.onPurchaseCompleted=()=>{this.currentPurchaseMethod=null},this.containerSelector=t.container,this.paymentMethodOrder=t.paymentMethodOrder;const n=document.querySelector(this.containerSelector);if(!n)throw new Error(`Container element not found for selector: ${this.containerSelector}`);this.containerEl=n,this.checkoutConfig=t}initAccordion(){const e=this.containerEl.querySelectorAll(".ff-payment-method-card"),t=this.containerEl.querySelectorAll(".ff-payment-method-radio"),n=t=>{e.forEach(e=>{const n=e.querySelector(".ff-payment-method-radio");n===t&&n?.checked?e.classList.add("expanded"):e.classList.remove("expanded")})},r=Array.from(t).find(e=>this.availableMethods.includes(e.value));if(!r)throw new Error("Default skin accordion initialization error: No radio button found");setTimeout(()=>{r.checked=!0,n(r)},0),t.forEach(e=>{e.addEventListener("change",()=>{e.checked&&n(e)})})}wireCardInputs(){this.cardInstance.wireCardInputs();const e=this.containerEl.querySelector("#submitButton");if(!e)throw new Error("One or more card input elements are missing in the default skin");this.cardInputElements={...this.cardInstance.getCardInputElements(),button:e}}async init(){this.containerEl.insertAdjacentHTML("beforeend",'<div class="ff-skin-default" id="ff-payment-method-containers">\n <div id="success-screen" style="display: none">\n <div class="success">\n <img alt="Loading" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI1IDAuMTExMzI4QzIwLjA3NzQgMC4xMTEzMjggMTUuMjY1NCAxLjU3MTA0IDExLjE3MjUgNC4zMDU4NkM3LjA3OTUyIDcuMDQwNjkgMy44ODk0NSAxMC45Mjc4IDIuMDA1NjYgMTUuNDc1N0MwLjEyMTg4MyAyMC4wMjM1IC0wLjM3MSAyNS4wMjc4IDAuNTg5MzQzIDI5Ljg1NThDMS41NDk2OSAzNC42ODM4IDMuOTIwMTIgMzkuMTE4NSA3LjQwMDkgNDIuNTk5M0MxMC44ODE3IDQ2LjA4MDEgMTUuMzE2NCA0OC40NTA1IDIwLjE0NDQgNDkuNDEwOUMyNC45NzI0IDUwLjM3MTIgMjkuOTc2NyA0OS44NzgzIDM0LjUyNDYgNDcuOTk0NkMzOS4wNzI0IDQ2LjExMDggNDIuOTU5NSA0Mi45MjA3IDQ1LjY5NDQgMzguODI3N0M0OC40MjkyIDM0LjczNDggNDkuODg4OSAyOS45MjI4IDQ5Ljg4ODkgMjUuMDAwMkM0OS44ODg5IDE4LjM5OTMgNDcuMjY2NyAxMi4wNjg3IDQyLjU5OTEgNy40MDExMkMzNy45MzE1IDIuNzMzNTQgMzEuNjAwOSAwLjExMTMyOCAyNSAwLjExMTMyOFpNNDEuMjU1NiAxNi42NDY5TDIwLjgxNTYgMzcuMDcxM0w4Ljc0NDQ0IDI1LjAwMDJDOC4zMzE4OCAyNC41ODc3IDguMTAwMTEgMjQuMDI4MSA4LjEwMDExIDIzLjQ0NDdDOC4xMDAxMSAyMi44NjEyIDguMzMxODggMjIuMzAxNyA4Ljc0NDQ0IDIxLjg4OTFDOS4xNTcgMjEuNDc2NSA5LjcxNjU1IDIxLjI0NDggMTAuMyAyMS4yNDQ4QzEwLjg4MzQgMjEuMjQ0OCAxMS40NDMgMjEuNDc2NSAxMS44NTU2IDIxLjg4OTFMMjAuODQ2NyAzMC44ODAyTDM4LjE3NTYgMTMuNTY2OUMzOC4zNzk4IDEzLjM2MjYgMzguNjIyMyAxMy4yMDA2IDM4Ljg4OTIgMTMuMDlDMzkuMTU2MiAxMi45Nzk1IDM5LjQ0MjIgMTIuOTIyNiAzOS43MzExIDEyLjkyMjZDNDAuMDIgMTIuOTIyNiA0MC4zMDYxIDEyLjk3OTUgNDAuNTczIDEzLjA5QzQwLjgzOTkgMTMuMjAwNiA0MS4wODI0IDEzLjM2MjYgNDEuMjg2NyAxMy41NjY5QzQxLjQ5MDkgMTMuNzcxMiA0MS42NTMgMTQuMDEzNyA0MS43NjM1IDE0LjI4MDZDNDEuODc0MSAxNC41NDc1IDQxLjkzMSAxNC44MzM1IDQxLjkzMSAxNS4xMjI0QzQxLjkzMSAxNS40MTEzIDQxLjg3NDEgMTUuNjk3NCA0MS43NjM1IDE1Ljk2NDNDNDEuNjUzIDE2LjIzMTIgNDEuNDkwOSAxNi40NzM3IDQxLjI4NjcgMTYuNjc4TDQxLjI1NTYgMTYuNjQ2OVoiIGZpbGw9IiM4RURGQzIiLz4KPC9zdmc+Cg==">\n <div>Payment completed successfully</div>\n </div>\n </div>\n</div>\n');const e=this.containerEl.querySelector("#ff-payment-method-containers");this.paymentMethodOrder.forEach(t=>{e.insertAdjacentHTML("beforeend",se[t])}),this.cardInstance=new ae(document.querySelector("#cardForm"),this.checkoutConfig),this.cardInstance.init(),this.wireCardInputs()}renderCardForm(){}getCardInputElements(){return{...this.cardInstance.getCardInputElements(),button:this.cardInputElements.button}}getPaymentButtonElements(){return{paypal:this.containerEl.querySelector("#paypalButton"),googlePay:this.containerEl.querySelector("#googlePayButton"),applePay:this.containerEl.querySelector("#applePayButton")}}getCheckoutOptions(){return{...this.cardInstance.getCheckoutOptions(),cardElements:this.getCardInputElements(),paymentButtonElements:this.getPaymentButtonElements(),applePay:_[e.PaymentMethod.APPLE_PAY],paypal:_[e.PaymentMethod.PAYPAL],googlePay:_[e.PaymentMethod.GOOGLE_PAY]}}}var ce=Object.freeze({__proto__:null,default:async e=>{const t=new de(e);return await t.init(),t}});e.APIError=o,e.Billing=oe,e.CHECKOUT_STATES={INITIALIZING:"initializing",READY:"ready",PROCESSING:"processing",ACTION_REQUIRED:"action_required",UPDATING:"updating",COMPLETED:"completed",ERROR:"error",DESTROYED:"destroyed"},e.CheckoutError=i,e.ConfigurationError=class extends n{constructor(e){super(e,R.CONFIGURATION_ERROR),this.name="ConfigurationError"}},e.DEFAULTS=M,e.ERROR_CODES=R,e.EVENTS=w,e.FunnefoxSDKError=n,e.NetworkError=s,e.PrimerError=a,e.SDK_VERSION=E,e.ValidationError=r,e.configure=X,e.createCheckout=te,e.createClientSession=ne,e.default=oe,e.getAvailablePaymentMethods=re,Object.defineProperty(e,"__esModule",{value:!0})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelfox/billing",
3
- "version": "0.6.3",
3
+ "version": "0.6.4-beta.0",
4
4
  "license": "MIT",
5
5
  "author": "Funnelfox",
6
6
  "description": "JavaScript SDK for Funnelfox billing with Primer integration",
@@ -26,7 +26,7 @@
26
26
  "scripts": {
27
27
  "build": "rm -rf dist && rollup -c",
28
28
  "build:watch": "rollup -c -w",
29
- "build:examples": "npm run build && npm pack && npm i ./funnelfox-billing-0.6.3.tgz --prefix examples/basic && npm run build --prefix examples/basic",
29
+ "build:examples": "npm run build && npm pack && npm i ./funnelfox-billing-0.6.4-beta.0.tgz --prefix examples/basic && npm run build --prefix examples/basic",
30
30
  "dev": "rollup -c -w",
31
31
  "lint": "eslint \"src/**/*.{ts,tsx}\"",
32
32
  "lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
package/src/types.d.ts CHANGED
@@ -376,6 +376,7 @@ export interface CreateClientSessionResponse {
376
376
  order_id: string;
377
377
  stripe_public_key?: string;
378
378
  collect_apple_pay_email?: boolean;
379
+ airwallex_risk_enabled?: boolean;
379
380
  };
380
381
  error?: {
381
382
  code: string;