@funnelfox/billing 0.4.3 → 0.5.0-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.
@@ -206,18 +206,18 @@ function withTimeout(promise, timeoutMs, message = 'Operation timed out') {
206
206
  return Promise.race([promise, timeoutPromise]);
207
207
  }
208
208
 
209
- var PaymentMethod;
209
+ exports.PaymentMethod = void 0;
210
210
  (function (PaymentMethod) {
211
211
  PaymentMethod["GOOGLE_PAY"] = "GOOGLE_PAY";
212
212
  PaymentMethod["APPLE_PAY"] = "APPLE_PAY";
213
213
  PaymentMethod["PAYPAL"] = "PAYPAL";
214
214
  PaymentMethod["PAYMENT_CARD"] = "PAYMENT_CARD";
215
- })(PaymentMethod || (PaymentMethod = {}));
215
+ })(exports.PaymentMethod || (exports.PaymentMethod = {}));
216
216
 
217
217
  /**
218
218
  * @fileoverview Constants for Funnefox SDK
219
219
  */
220
- const SDK_VERSION = '0.4.3';
220
+ const SDK_VERSION = '0.5.0-beta.0';
221
221
  const DEFAULTS = {
222
222
  BASE_URL: 'https://billing.funnelfox.com',
223
223
  REGION: 'default',
@@ -244,9 +244,11 @@ const EVENTS = {
244
244
  INPUT_ERROR: 'input-error',
245
245
  LOADER_CHANGE: 'loader-change',
246
246
  METHOD_RENDER: 'method-render',
247
+ METHOD_RENDER_ERROR: 'method-render-error',
247
248
  START_PURCHASE: 'start-purchase',
248
249
  PURCHASE_FAILURE: 'purchase-failure',
249
250
  PURCHASE_COMPLETED: 'purchase-completed',
251
+ PURCHASE_CANCELLED: 'purchase-cancelled',
250
252
  };
251
253
  const API_ENDPOINTS = {
252
254
  CREATE_CLIENT_SESSION: '/v1/checkout/create_client_session',
@@ -264,12 +266,12 @@ const ERROR_CODES = {
264
266
  NETWORK_ERROR: 'NETWORK_ERROR',
265
267
  };
266
268
  const ALLOWED_BUTTON_PAYMENT_METHODS = [
267
- PaymentMethod.GOOGLE_PAY,
268
- PaymentMethod.APPLE_PAY,
269
- PaymentMethod.PAYPAL,
269
+ exports.PaymentMethod.GOOGLE_PAY,
270
+ exports.PaymentMethod.APPLE_PAY,
271
+ exports.PaymentMethod.PAYPAL,
270
272
  ];
271
273
  const ALLOWED_CARD_PAYMENT_METHODS = [
272
- PaymentMethod.PAYMENT_CARD,
274
+ exports.PaymentMethod.PAYMENT_CARD,
273
275
  ];
274
276
  const ALLOWED_PAYMENT_METHODS = [
275
277
  ...ALLOWED_BUTTON_PAYMENT_METHODS,
@@ -322,10 +324,6 @@ class PrimerWrapper {
322
324
  const primerOptions = merge({
323
325
  paymentHandling: 'MANUAL',
324
326
  apiVersion: '2.4',
325
- paypal: {
326
- buttonColor: 'blue',
327
- paymentFlow: 'PREFER_VAULT',
328
- },
329
327
  }, options);
330
328
  try {
331
329
  const headless = await window.Primer.createHeadless(clientToken, primerOptions);
@@ -353,9 +351,64 @@ class PrimerWrapper {
353
351
  this.paymentMethodsInterfaces[method].setDisabled(disabled);
354
352
  }
355
353
  }
356
- async renderCardCheckout({ onSubmit, cardSelectors, onInputChange, }) {
354
+ async renderButton(allowedPaymentMethod, { container, }) {
355
+ const containerEl = this.validateContainer(container);
356
+ let button;
357
+ this.ensurePrimerAvailable();
358
+ if (!this.headless) {
359
+ throw new PrimerError('Headless checkout not found');
360
+ }
361
+ try {
362
+ const pmManager = await this.headless.createPaymentMethodManager(allowedPaymentMethod);
363
+ if (!pmManager) {
364
+ throw new Error('Payment method manager is not available');
365
+ }
366
+ button = pmManager.createButton();
367
+ await button.render(containerEl, {});
368
+ this.destroyCallbacks.push(() => button.clean());
369
+ }
370
+ catch (error) {
371
+ throw new PrimerError('Failed to initialize Primer checkout', error);
372
+ }
373
+ }
374
+ async initMethod(method, htmlNode, options) {
375
+ if (method === exports.PaymentMethod.PAYMENT_CARD) {
376
+ if (!options.cardElements ||
377
+ !options.onSubmit ||
378
+ !options.onInputChange) {
379
+ throw new PrimerError('Card elements, onSubmit, and onInputChange are required for PAYMENT_CARD method');
380
+ }
381
+ return this.renderCardCheckoutWithElements(options.cardElements, {
382
+ onSubmit: options.onSubmit,
383
+ onInputChange: options.onInputChange,
384
+ onMethodRenderError: options.onMethodRenderError,
385
+ onMethodRender: options.onMethodRender,
386
+ });
387
+ }
388
+ else {
389
+ // For button methods, render directly into htmlNode
390
+ this.ensurePrimerAvailable();
391
+ if (!this.headless) {
392
+ throw new PrimerError('Headless checkout not found');
393
+ }
394
+ try {
395
+ const pmManager = await this.headless.createPaymentMethodManager(method);
396
+ if (!pmManager) {
397
+ throw new Error('Payment method manager is not available');
398
+ }
399
+ const button = pmManager.createButton();
400
+ await button.render(htmlNode, {});
401
+ this.destroyCallbacks.push(() => button.clean());
402
+ options.onMethodRender(method);
403
+ }
404
+ catch (error) {
405
+ options.onMethodRenderError(method);
406
+ throw new PrimerError('Failed to initialize Primer checkout', error);
407
+ }
408
+ }
409
+ }
410
+ async renderCardCheckoutWithElements(elements, { onSubmit, onInputChange, onMethodRenderError, onMethodRender, }) {
357
411
  try {
358
- const elements = this.initializeCardElements(cardSelectors);
359
412
  const pmManager = await this.headless.createPaymentMethodManager('PAYMENT_CARD');
360
413
  if (!pmManager) {
361
414
  throw new Error('Payment method manager is not available');
@@ -402,7 +455,7 @@ class PrimerWrapper {
402
455
  onSubmit(false);
403
456
  }
404
457
  };
405
- elements.button.addEventListener('click', onSubmitHandler);
458
+ elements.button?.addEventListener('click', onSubmitHandler);
406
459
  await Promise.all([
407
460
  cardNumberInput.render(elements.cardNumber, {
408
461
  placeholder: '1234 1234 1234 1234',
@@ -420,10 +473,13 @@ class PrimerWrapper {
420
473
  style: inputStyle,
421
474
  }),
422
475
  ]);
423
- this.destroyCallbacks.push(() => {
476
+ const onDestroy = () => {
424
477
  pmManager.removeHostedInputs();
425
478
  elements.cardholderName.removeEventListener('change', cardHolderOnChange);
426
- });
479
+ elements.button.removeEventListener('click', onSubmitHandler);
480
+ };
481
+ this.destroyCallbacks.push(onDestroy);
482
+ onMethodRender(exports.PaymentMethod.PAYMENT_CARD);
427
483
  return {
428
484
  setDisabled: (disabled) => {
429
485
  cardNumberInput.setDisabled(disabled);
@@ -431,75 +487,67 @@ class PrimerWrapper {
431
487
  cvvInput.setDisabled(disabled);
432
488
  elements.button.disabled = disabled;
433
489
  },
490
+ submit: () => onSubmitHandler(),
491
+ destroy: () => {
492
+ this.destroyCallbacks = this.destroyCallbacks.filter(callback => callback !== onDestroy);
493
+ onDestroy();
494
+ },
434
495
  };
435
496
  }
436
497
  catch (error) {
437
498
  throw new PrimerError('Failed to initialize Primer checkout', error);
438
499
  }
439
500
  }
440
- async renderButton(allowedPaymentMethod, { container, }) {
441
- const containerEl = this.validateContainer(container);
442
- let button;
443
- this.ensurePrimerAvailable();
444
- if (!this.headless) {
445
- throw new PrimerError('Headless checkout not found');
446
- }
447
- try {
448
- const pmManager = await this.headless.createPaymentMethodManager(allowedPaymentMethod);
449
- if (!pmManager) {
450
- throw new Error('Payment method manager is not available');
451
- }
452
- button = pmManager.createButton();
453
- await button.render(containerEl, {});
454
- this.destroyCallbacks.push(() => button.clean());
455
- }
456
- catch (error) {
457
- throw new PrimerError('Failed to initialize Primer checkout', error);
458
- }
459
- }
460
- async renderCheckout(clientToken, options) {
461
- const { cardSelectors, paymentButtonSelectors, container, onTokenizeSuccess, onResumeSuccess, onSubmit, onInputChange, onMethodRender, ...restPrimerOptions } = options;
501
+ async initializeHeadlessCheckout(clientToken, primerOptions) {
462
502
  await this.createHeadlessCheckout(clientToken, {
463
- ...restPrimerOptions,
464
- onTokenizeSuccess: this.wrapTokenizeHandler(onTokenizeSuccess),
465
- onResumeSuccess: this.wrapResumeHandler(onResumeSuccess),
503
+ ...primerOptions,
504
+ onTokenizeSuccess: this.wrapTokenizeHandler(primerOptions.onTokenizeSuccess),
505
+ onResumeSuccess: this.wrapResumeHandler(primerOptions.onResumeSuccess),
466
506
  onAvailablePaymentMethodsLoad: (items) => {
467
507
  let isApplePayAvailable = false;
468
508
  this.availableMethods = ALLOWED_PAYMENT_METHODS.filter(method => {
469
509
  return items.some((item) => {
470
- if (item.type === PaymentMethod.APPLE_PAY) {
510
+ if (item.type === exports.PaymentMethod.APPLE_PAY) {
471
511
  isApplePayAvailable = true;
472
512
  }
473
513
  return item.type === method;
474
514
  });
475
515
  });
476
516
  if (isApplePayAvailable) {
477
- this.availableMethods = this.availableMethods.filter(method => method !== PaymentMethod.GOOGLE_PAY);
517
+ this.availableMethods = this.availableMethods.filter(method => method !== exports.PaymentMethod.GOOGLE_PAY);
478
518
  }
479
519
  if (this.availableMethods.length === 0) {
480
520
  throw new PrimerError('No allowed payment methods found');
481
521
  }
482
522
  },
483
523
  });
484
- const methodOptions = {
485
- cardSelectors,
486
- container,
487
- onSubmit,
488
- onInputChange,
489
- };
524
+ }
525
+ async renderCheckout(clientToken, checkoutOptions, checkoutRenderOptions) {
526
+ const { cardElements, paymentButtonElements, container, onSubmit, onInputChange, onMethodRender, onMethodRenderError, } = checkoutRenderOptions;
527
+ await this.initializeHeadlessCheckout(clientToken, checkoutOptions);
490
528
  for (const method of this.availableMethods) {
491
- if (method === PaymentMethod.PAYMENT_CARD) {
492
- await this.renderCardCheckout(methodOptions);
493
- onMethodRender(PaymentMethod.PAYMENT_CARD);
529
+ if (method === exports.PaymentMethod.PAYMENT_CARD) {
530
+ // For card, use the main container
531
+ await this.initMethod(method, container, {
532
+ cardElements,
533
+ onSubmit,
534
+ onInputChange,
535
+ onMethodRender,
536
+ onMethodRenderError,
537
+ });
494
538
  }
495
539
  else {
496
- const container = method === PaymentMethod.PAYPAL
497
- ? paymentButtonSelectors.paypal
498
- : method === PaymentMethod.GOOGLE_PAY
499
- ? paymentButtonSelectors.googlePay
500
- : paymentButtonSelectors.applePay;
501
- await this.renderButton(method, { container });
502
- onMethodRender(method);
540
+ const buttonElementsMap = {
541
+ [exports.PaymentMethod.PAYPAL]: paymentButtonElements.paypal,
542
+ [exports.PaymentMethod.GOOGLE_PAY]: paymentButtonElements.googlePay,
543
+ [exports.PaymentMethod.APPLE_PAY]: paymentButtonElements.applePay,
544
+ };
545
+ // For buttons, use the specific button container element
546
+ const buttonElement = buttonElementsMap[method];
547
+ await this.initMethod(method, buttonElement, {
548
+ onMethodRender,
549
+ onMethodRenderError,
550
+ });
503
551
  }
504
552
  }
505
553
  this.isInitialized = true;
@@ -760,6 +808,12 @@ class APIClient {
760
808
  }
761
809
  throw new APIError('Invalid payment response format', null, { response });
762
810
  }
811
+ async oneClick(payload) {
812
+ return (await this.request(`/billing/${this.orgId}/v1/checkout/one_click`, {
813
+ method: 'POST',
814
+ body: JSON.stringify(payload),
815
+ }));
816
+ }
763
817
  }
764
818
 
765
819
  var loaderHtml = "<div class=\"ff-sdk-loader-container\">\n <div class=\"ff-sdk-loader\"></div>\n</div>\n";
@@ -797,6 +851,9 @@ class CheckoutInstance extends EventEmitter {
797
851
  this.handleMethodRender = (method) => {
798
852
  this.emit(EVENTS.METHOD_RENDER, method);
799
853
  };
854
+ this.handleMethodRenderError = (method) => {
855
+ this.emit(EVENTS.METHOD_RENDER_ERROR, method);
856
+ };
800
857
  this.handleSubmit = (isSubmitting) => {
801
858
  this.onLoaderChangeWithRace(isSubmitting);
802
859
  this._setState(isSubmitting ? 'processing' : 'ready');
@@ -869,9 +926,6 @@ class CheckoutInstance extends EventEmitter {
869
926
  this.primerWrapper = new PrimerWrapper();
870
927
  this.isDestroyed = false;
871
928
  this._setupCallbackBridges();
872
- this.initialize().then(() => {
873
- this.checkoutConfig?.onInitialized?.();
874
- });
875
929
  }
876
930
  _setupCallbackBridges() {
877
931
  if (this.callbacks.onSuccess) {
@@ -894,25 +948,10 @@ class CheckoutInstance extends EventEmitter {
894
948
  try {
895
949
  this.showInitializingLoader();
896
950
  this._setState('initializing');
897
- this.apiClient = new APIClient({
898
- baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
899
- orgId: this.orgId,
900
- timeout: DEFAULTS.REQUEST_TIMEOUT,
901
- retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
902
- });
903
- const sessionResponse = await this.apiClient.createClientSession({
904
- priceId: this.checkoutConfig.priceId,
905
- externalId: this.checkoutConfig.customer.externalId,
906
- email: this.checkoutConfig.customer.email,
907
- region: this.region || DEFAULTS.REGION,
908
- clientMetadata: this.checkoutConfig.clientMetadata,
909
- countryCode: this.checkoutConfig.customer.countryCode,
910
- });
911
- const sessionData = this.apiClient.processSessionResponse(sessionResponse);
912
- this.orderId = sessionData.orderId;
913
- this.clientToken = sessionData.clientToken;
951
+ await this.createSession();
914
952
  await this._initializePrimerCheckout();
915
953
  this._setState('ready');
954
+ this.checkoutConfig?.onInitialized?.();
916
955
  return this;
917
956
  }
918
957
  catch (error) {
@@ -924,41 +963,90 @@ class CheckoutInstance extends EventEmitter {
924
963
  this.hideInitializingLoader();
925
964
  }
926
965
  }
927
- async _initializePrimerCheckout() {
928
- const checkoutOptions = {
929
- ...this.checkoutConfig,
930
- onTokenizeSuccess: this.handleTokenizeSuccess,
931
- onResumeSuccess: this.handleResumeSuccess,
932
- onSubmit: this.handleSubmit,
933
- onInputChange: this.handleInputChange,
934
- onMethodRender: this.handleMethodRender,
935
- onResumeError: error => {
936
- if (error.stack?.includes('PROCESSOR_3DS') &&
937
- error.code === 'RESUME_ERROR' &&
938
- error.message?.includes('fetch resume key')) {
939
- // Ignore 3DS close error, because it is not understandable by user
940
- return;
941
- }
942
- this.emit(EVENTS.PURCHASE_FAILURE, error);
943
- },
944
- onCheckoutFail: error => {
945
- this.emit(EVENTS.PURCHASE_FAILURE, error);
946
- },
947
- onTokenizeError: error => {
948
- this.emit(EVENTS.PURCHASE_FAILURE, error);
949
- },
950
- onTokenizeShouldStart: data => {
951
- this.emit(EVENTS.ERROR, undefined);
952
- this.emit(EVENTS.START_PURCHASE, data.paymentMethodType);
953
- return true;
954
- },
966
+ async createSession() {
967
+ this.apiClient = new APIClient({
968
+ baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
969
+ orgId: this.orgId,
970
+ timeout: DEFAULTS.REQUEST_TIMEOUT,
971
+ retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
972
+ });
973
+ const sessionResponse = await this.apiClient.createClientSession({
974
+ priceId: this.checkoutConfig.priceId,
975
+ externalId: this.checkoutConfig.customer.externalId,
976
+ email: this.checkoutConfig.customer.email,
977
+ region: this.region || DEFAULTS.REGION,
978
+ clientMetadata: this.checkoutConfig.clientMetadata,
979
+ countryCode: this.checkoutConfig.customer.countryCode,
980
+ });
981
+ const sessionData = this.apiClient.processSessionResponse(sessionResponse);
982
+ this.orderId = sessionData.orderId;
983
+ this.clientToken = sessionData.clientToken;
984
+ }
985
+ convertCardSelectorsToElements(selectors, container) {
986
+ const cardNumber = container.querySelector(selectors.cardNumber);
987
+ const expiryDate = container.querySelector(selectors.expiryDate);
988
+ const cvv = container.querySelector(selectors.cvv);
989
+ const cardholderName = container.querySelector(selectors.cardholderName);
990
+ const button = container.querySelector(selectors.button);
991
+ if (!cardNumber || !expiryDate || !cvv || !button) {
992
+ throw new CheckoutError('Required card input elements not found in container');
993
+ }
994
+ return {
995
+ cardNumber,
996
+ expiryDate,
997
+ cvv,
998
+ cardholderName,
999
+ button,
1000
+ };
1001
+ }
1002
+ convertPaymentButtonSelectorsToElements(selectors) {
1003
+ const paypal = document.querySelector(selectors.paypal);
1004
+ const googlePay = document.querySelector(selectors.googlePay);
1005
+ const applePay = document.querySelector(selectors.applePay);
1006
+ if (!paypal || !googlePay || !applePay) {
1007
+ throw new CheckoutError('Required payment button elements not found in container');
1008
+ }
1009
+ return {
1010
+ paypal,
1011
+ googlePay,
1012
+ applePay,
955
1013
  };
1014
+ }
1015
+ async _initializePrimerCheckout() {
1016
+ // Get container element
1017
+ const containerElement = this.getContainer();
1018
+ if (!containerElement) {
1019
+ throw new CheckoutError(`Checkout container not found: ${this.checkoutConfig.container}`);
1020
+ }
1021
+ // Get selectors (either from config or default skin)
1022
+ let cardElements;
1023
+ let paymentButtonElements;
1024
+ let checkoutOptions;
956
1025
  if (!this.checkoutConfig.cardSelectors ||
957
1026
  !this.checkoutConfig.paymentButtonSelectors) {
958
1027
  const defaultSkinCheckoutOptions = await this.getDefaultSkinCheckoutOptions();
959
- Object.assign(checkoutOptions, defaultSkinCheckoutOptions);
1028
+ if (!defaultSkinCheckoutOptions.cardElements ||
1029
+ !defaultSkinCheckoutOptions.paymentButtonElements) {
1030
+ throw new CheckoutError('Default skin must provide cardSelectors and paymentButtonSelectors');
1031
+ }
1032
+ cardElements =
1033
+ defaultSkinCheckoutOptions.cardElements;
1034
+ paymentButtonElements = defaultSkinCheckoutOptions.paymentButtonElements;
1035
+ checkoutOptions = this.getCheckoutOptions(defaultSkinCheckoutOptions);
1036
+ }
1037
+ else {
1038
+ cardElements = this.convertCardSelectorsToElements(this.checkoutConfig.cardSelectors, containerElement);
1039
+ paymentButtonElements = this.convertPaymentButtonSelectorsToElements(this.checkoutConfig.paymentButtonSelectors);
1040
+ checkoutOptions = this.getCheckoutOptions({});
960
1041
  }
961
- await this.primerWrapper.renderCheckout(this.clientToken, checkoutOptions);
1042
+ await this.primerWrapper.renderCheckout(this.clientToken, checkoutOptions, {
1043
+ container: containerElement,
1044
+ cardElements,
1045
+ paymentButtonElements,
1046
+ onSubmit: this.handleSubmit,
1047
+ onInputChange: this.handleInputChange,
1048
+ onMethodRender: this.handleMethodRender,
1049
+ });
962
1050
  }
963
1051
  async _processPaymentResult(result, primerHandler) {
964
1052
  if (result.orderId) {
@@ -988,6 +1076,48 @@ class CheckoutInstance extends EventEmitter {
988
1076
  throw new CheckoutError(`Unknown payment result type: ${result.type}`);
989
1077
  }
990
1078
  }
1079
+ getCheckoutOptions(options) {
1080
+ let wasPaymentProcessedStarted = false;
1081
+ return {
1082
+ ...this.checkoutConfig,
1083
+ ...options,
1084
+ onTokenizeSuccess: this.handleTokenizeSuccess,
1085
+ onResumeSuccess: this.handleResumeSuccess,
1086
+ onResumeError: error => {
1087
+ if (error.stack?.includes('PROCESSOR_3DS') &&
1088
+ error.code === 'RESUME_ERROR' &&
1089
+ error.message?.includes('fetch resume key')) {
1090
+ // Ignore 3DS close error, because it is not understandable by user
1091
+ return;
1092
+ }
1093
+ this.emit(EVENTS.PURCHASE_FAILURE, error);
1094
+ },
1095
+ onCheckoutFail: error => {
1096
+ this.emit(EVENTS.PURCHASE_FAILURE, error);
1097
+ },
1098
+ onTokenizeError: error => {
1099
+ this.emit(EVENTS.PURCHASE_FAILURE, error);
1100
+ },
1101
+ onTokenizeShouldStart: data => {
1102
+ this.emit(EVENTS.ERROR, undefined);
1103
+ this.emit(EVENTS.START_PURCHASE, data.paymentMethodType);
1104
+ return true;
1105
+ },
1106
+ onPaymentMethodAction: action => {
1107
+ switch (action) {
1108
+ case 'PAYMENT_METHOD_SELECTED':
1109
+ this.emit(EVENTS.ERROR, undefined);
1110
+ break;
1111
+ case 'PAYMENT_METHOD_UNSELECTED':
1112
+ if (!wasPaymentProcessedStarted) {
1113
+ this.emit(EVENTS.PURCHASE_CANCELLED);
1114
+ }
1115
+ wasPaymentProcessedStarted = false;
1116
+ break;
1117
+ }
1118
+ },
1119
+ };
1120
+ }
991
1121
  async updatePrice(newPriceId) {
992
1122
  this._ensureNotDestroyed();
993
1123
  requireString(newPriceId, 'priceId');
@@ -1078,6 +1208,13 @@ class CheckoutInstance extends EventEmitter {
1078
1208
  this.on(EVENTS.PURCHASE_COMPLETED, skin.onPurchaseCompleted);
1079
1209
  return skin.getCheckoutOptions();
1080
1210
  }
1211
+ async getCardDefaultSkinCheckoutOptions(node) {
1212
+ const CardSkin = (await Promise.resolve().then(function () { return require('./chunk-index.cjs2.js'); })).default;
1213
+ const skin = new CardSkin(node);
1214
+ skin.init();
1215
+ this.on(EVENTS.INPUT_ERROR, skin.onInputError);
1216
+ return skin.getCheckoutOptions();
1217
+ }
1081
1218
  showInitializingLoader() {
1082
1219
  renderLoader(this.checkoutConfig.container);
1083
1220
  }
@@ -1112,19 +1249,14 @@ async function createCheckout(options) {
1112
1249
  const primerWrapper = new PrimerWrapper();
1113
1250
  primerWrapper.ensurePrimerAvailable();
1114
1251
  const config = resolveConfig(options, 'createCheckout');
1115
- return new Promise(resolve => {
1116
- const onInitialized = () => {
1117
- resolve(checkout);
1118
- checkoutConfig.onInitialized?.();
1119
- };
1120
- const checkout = new CheckoutInstance({
1121
- ...config,
1122
- checkoutConfig: {
1123
- ...checkoutConfig,
1124
- onInitialized,
1125
- },
1126
- });
1252
+ const checkout = new CheckoutInstance({
1253
+ ...config,
1254
+ checkoutConfig: {
1255
+ ...checkoutConfig,
1256
+ },
1127
1257
  });
1258
+ await checkout.initialize();
1259
+ return checkout;
1128
1260
  }
1129
1261
  async function createClientSession(params) {
1130
1262
  const { priceId, externalId, email, clientMetadata, countryCode } = params;
@@ -1145,6 +1277,54 @@ async function createClientSession(params) {
1145
1277
  });
1146
1278
  return apiClient.processSessionResponse(sessionResponse);
1147
1279
  }
1280
+ async function initMethod(method, element, options) {
1281
+ const checkoutInstance = new CheckoutInstance({
1282
+ orgId: options.orgId,
1283
+ baseUrl: options.baseUrl,
1284
+ checkoutConfig: {
1285
+ priceId: options.priceId,
1286
+ customer: {
1287
+ externalId: options.externalId,
1288
+ email: options.email,
1289
+ },
1290
+ container: '',
1291
+ clientMetadata: options.meta,
1292
+ },
1293
+ });
1294
+ checkoutInstance._ensureNotDestroyed();
1295
+ if (!checkoutInstance.isReady()) {
1296
+ await checkoutInstance['createSession']();
1297
+ }
1298
+ checkoutInstance.on(EVENTS.METHOD_RENDER, options.onRenderSuccess);
1299
+ checkoutInstance.on(EVENTS.METHOD_RENDER_ERROR, options.onRenderError);
1300
+ checkoutInstance.on(EVENTS.LOADER_CHANGE, options.onLoaderChange);
1301
+ checkoutInstance.on(EVENTS.SUCCESS, options.onPaymentSuccess);
1302
+ checkoutInstance.on(EVENTS.PURCHASE_FAILURE, options.onPaymentFail);
1303
+ checkoutInstance.on(EVENTS.PURCHASE_CANCELLED, options.onPaymentCancel);
1304
+ checkoutInstance.on(EVENTS.ERROR, options.onErrorMessageChange);
1305
+ if (method === exports.PaymentMethod.PAYMENT_CARD) {
1306
+ const cardDefaultOptions = await checkoutInstance['getCardDefaultSkinCheckoutOptions'](element);
1307
+ const checkoutOptions = checkoutInstance['getCheckoutOptions']({
1308
+ style: options.styles,
1309
+ ...cardDefaultOptions,
1310
+ });
1311
+ await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutOptions);
1312
+ return checkoutInstance.primerWrapper.initMethod(method, element, {
1313
+ cardElements: cardDefaultOptions.cardElements,
1314
+ onSubmit: checkoutInstance['handleSubmit'],
1315
+ onInputChange: checkoutInstance['handleInputChange'],
1316
+ onMethodRender: checkoutInstance['handleMethodRender'],
1317
+ onMethodRenderError: checkoutInstance['handleMethodRenderError'],
1318
+ });
1319
+ }
1320
+ await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutInstance['getCheckoutOptions']({
1321
+ style: options.styles,
1322
+ }));
1323
+ return checkoutInstance.primerWrapper.initMethod(method, element, {
1324
+ onMethodRender: checkoutInstance['handleMethodRender'],
1325
+ onMethodRenderError: checkoutInstance['handleMethodRenderError'],
1326
+ });
1327
+ }
1148
1328
 
1149
1329
  /**
1150
1330
  * @fileoverview Main entry point for @funnelfox/billing
@@ -1153,6 +1333,7 @@ const Billing = {
1153
1333
  configure: configure,
1154
1334
  createCheckout: createCheckout,
1155
1335
  createClientSession: createClientSession,
1336
+ initMethod: initMethod,
1156
1337
  };
1157
1338
  if (typeof window !== 'undefined') {
1158
1339
  window.Billing = Billing;