@funnelfox/billing 0.4.5 → 0.5.0-beta.1

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.
@@ -217,7 +217,7 @@ exports.PaymentMethod = void 0;
217
217
  /**
218
218
  * @fileoverview Constants for Funnefox SDK
219
219
  */
220
- const SDK_VERSION = '0.4.5';
220
+ const SDK_VERSION = '0.5.0-beta.1';
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',
@@ -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,38 +487,22 @@ 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 => {
@@ -481,25 +521,33 @@ class PrimerWrapper {
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
529
  if (method === exports.PaymentMethod.PAYMENT_CARD) {
492
- await this.renderCardCheckout(methodOptions);
493
- onMethodRender(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 === exports.PaymentMethod.PAYPAL
497
- ? paymentButtonSelectors.paypal
498
- : method === exports.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";
@@ -803,6 +857,9 @@ class CheckoutInstance extends EventEmitter {
803
857
  this.handleMethodRender = (method) => {
804
858
  this.emit(EVENTS.METHOD_RENDER, method);
805
859
  };
860
+ this.handleMethodRenderError = (method) => {
861
+ this.emit(EVENTS.METHOD_RENDER_ERROR, method);
862
+ };
806
863
  this.handleSubmit = (isSubmitting) => {
807
864
  this.onLoaderChangeWithRace(isSubmitting);
808
865
  this._setState(isSubmitting ? 'processing' : 'ready');
@@ -875,9 +932,6 @@ class CheckoutInstance extends EventEmitter {
875
932
  this.primerWrapper = new PrimerWrapper();
876
933
  this.isDestroyed = false;
877
934
  this._setupCallbackBridges();
878
- this.initialize().then(() => {
879
- this.checkoutConfig?.onInitialized?.();
880
- });
881
935
  }
882
936
  _setupCallbackBridges() {
883
937
  if (this.callbacks.onSuccess) {
@@ -900,25 +954,10 @@ class CheckoutInstance extends EventEmitter {
900
954
  try {
901
955
  this.showInitializingLoader();
902
956
  this._setState('initializing');
903
- this.apiClient = new APIClient({
904
- baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
905
- orgId: this.orgId,
906
- timeout: DEFAULTS.REQUEST_TIMEOUT,
907
- retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
908
- });
909
- const sessionResponse = await this.apiClient.createClientSession({
910
- priceId: this.checkoutConfig.priceId,
911
- externalId: this.checkoutConfig.customer.externalId,
912
- email: this.checkoutConfig.customer.email,
913
- region: this.region || DEFAULTS.REGION,
914
- clientMetadata: this.checkoutConfig.clientMetadata,
915
- countryCode: this.checkoutConfig.customer.countryCode,
916
- });
917
- const sessionData = this.apiClient.processSessionResponse(sessionResponse);
918
- this.orderId = sessionData.orderId;
919
- this.clientToken = sessionData.clientToken;
957
+ await this.createSession();
920
958
  await this._initializePrimerCheckout();
921
959
  this._setState('ready');
960
+ this.checkoutConfig?.onInitialized?.();
922
961
  return this;
923
962
  }
924
963
  catch (error) {
@@ -930,48 +969,97 @@ class CheckoutInstance extends EventEmitter {
930
969
  this.hideInitializingLoader();
931
970
  }
932
971
  }
933
- async _initializePrimerCheckout() {
934
- const checkoutOptions = {
935
- ...this.checkoutConfig,
936
- onTokenizeSuccess: this.handleTokenizeSuccess,
937
- onResumeSuccess: this.handleResumeSuccess,
938
- onSubmit: this.handleSubmit,
939
- onInputChange: this.handleInputChange,
940
- onMethodRender: this.handleMethodRender,
941
- onResumeError: error => {
942
- if (error.stack?.includes('PROCESSOR_3DS') &&
943
- error.code === 'RESUME_ERROR' &&
944
- error.message?.includes('fetch resume key')) {
945
- // Ignore 3DS close error, because it is not understandable by user
946
- return;
947
- }
948
- this.emit(EVENTS.PURCHASE_FAILURE, error);
949
- },
950
- onCheckoutFail: error => {
951
- this.emit(EVENTS.PURCHASE_FAILURE, error);
952
- },
953
- onTokenizeError: error => {
954
- this.emit(EVENTS.PURCHASE_FAILURE, error);
955
- },
956
- onTokenizeShouldStart: data => {
957
- this.emit(EVENTS.ERROR, undefined);
958
- this.emit(EVENTS.START_PURCHASE, data.paymentMethodType);
959
- return true;
960
- },
972
+ async createSession() {
973
+ this.apiClient = new APIClient({
974
+ baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
975
+ orgId: this.orgId,
976
+ timeout: DEFAULTS.REQUEST_TIMEOUT,
977
+ retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
978
+ });
979
+ const sessionResponse = await this.apiClient.createClientSession({
980
+ priceId: this.checkoutConfig.priceId,
981
+ externalId: this.checkoutConfig.customer.externalId,
982
+ email: this.checkoutConfig.customer.email,
983
+ region: this.region || DEFAULTS.REGION,
984
+ clientMetadata: this.checkoutConfig.clientMetadata,
985
+ countryCode: this.checkoutConfig.customer.countryCode,
986
+ });
987
+ const sessionData = this.apiClient.processSessionResponse(sessionResponse);
988
+ this.orderId = sessionData.orderId;
989
+ this.clientToken = sessionData.clientToken;
990
+ }
991
+ convertCardSelectorsToElements(selectors, container) {
992
+ const cardNumber = container.querySelector(selectors.cardNumber);
993
+ const expiryDate = container.querySelector(selectors.expiryDate);
994
+ const cvv = container.querySelector(selectors.cvv);
995
+ const cardholderName = container.querySelector(selectors.cardholderName);
996
+ const button = container.querySelector(selectors.button);
997
+ if (!cardNumber || !expiryDate || !cvv || !button) {
998
+ throw new CheckoutError('Required card input elements not found in container');
999
+ }
1000
+ return {
1001
+ cardNumber,
1002
+ expiryDate,
1003
+ cvv,
1004
+ cardholderName,
1005
+ button,
1006
+ };
1007
+ }
1008
+ convertPaymentButtonSelectorsToElements(selectors) {
1009
+ const paypal = document.querySelector(selectors.paypal);
1010
+ const googlePay = document.querySelector(selectors.googlePay);
1011
+ const applePay = document.querySelector(selectors.applePay);
1012
+ if (!paypal || !googlePay || !applePay) {
1013
+ throw new CheckoutError('Required payment button elements not found in container');
1014
+ }
1015
+ return {
1016
+ paypal,
1017
+ googlePay,
1018
+ applePay,
961
1019
  };
1020
+ }
1021
+ async _initializePrimerCheckout() {
1022
+ // Get container element
1023
+ const containerElement = this.getContainer();
1024
+ if (!containerElement) {
1025
+ throw new CheckoutError(`Checkout container not found: ${this.checkoutConfig.container}`);
1026
+ }
1027
+ // Get selectors (either from config or default skin)
1028
+ let cardElements;
1029
+ let paymentButtonElements;
1030
+ let checkoutOptions;
962
1031
  if (!this.checkoutConfig.cardSelectors ||
963
1032
  !this.checkoutConfig.paymentButtonSelectors) {
964
1033
  if (this.checkoutConfig.paymentMethodOrder) {
965
1034
  this.paymentMethodOrder = this.checkoutConfig.paymentMethodOrder;
966
1035
  }
967
1036
  const defaultSkinCheckoutOptions = await this.getDefaultSkinCheckoutOptions();
968
- Object.assign(checkoutOptions, defaultSkinCheckoutOptions);
1037
+ if (!defaultSkinCheckoutOptions.cardElements ||
1038
+ !defaultSkinCheckoutOptions.paymentButtonElements) {
1039
+ throw new CheckoutError('Default skin must provide cardSelectors and paymentButtonSelectors');
1040
+ }
1041
+ cardElements =
1042
+ defaultSkinCheckoutOptions.cardElements;
1043
+ paymentButtonElements = defaultSkinCheckoutOptions.paymentButtonElements;
1044
+ checkoutOptions = this.getCheckoutOptions(defaultSkinCheckoutOptions);
1045
+ }
1046
+ else {
1047
+ cardElements = this.convertCardSelectorsToElements(this.checkoutConfig.cardSelectors, containerElement);
1048
+ paymentButtonElements = this.convertPaymentButtonSelectorsToElements(this.checkoutConfig.paymentButtonSelectors);
1049
+ checkoutOptions = this.getCheckoutOptions({});
969
1050
  }
970
1051
  if (this.checkoutConfig.paymentMethodOrder) {
971
1052
  // eslint-disable-next-line no-console
972
1053
  console.warn('paymentMethodOrder is using only for default skin and will be ignored if you are using custom checkout');
973
1054
  }
974
- await this.primerWrapper.renderCheckout(this.clientToken, checkoutOptions);
1055
+ await this.primerWrapper.renderCheckout(this.clientToken, checkoutOptions, {
1056
+ container: containerElement,
1057
+ cardElements,
1058
+ paymentButtonElements,
1059
+ onSubmit: this.handleSubmit,
1060
+ onInputChange: this.handleInputChange,
1061
+ onMethodRender: this.handleMethodRender,
1062
+ });
975
1063
  }
976
1064
  async _processPaymentResult(result, primerHandler) {
977
1065
  if (result.orderId) {
@@ -1001,6 +1089,48 @@ class CheckoutInstance extends EventEmitter {
1001
1089
  throw new CheckoutError(`Unknown payment result type: ${result.type}`);
1002
1090
  }
1003
1091
  }
1092
+ getCheckoutOptions(options) {
1093
+ let wasPaymentProcessedStarted = false;
1094
+ return {
1095
+ ...this.checkoutConfig,
1096
+ ...options,
1097
+ onTokenizeSuccess: this.handleTokenizeSuccess,
1098
+ onResumeSuccess: this.handleResumeSuccess,
1099
+ onResumeError: error => {
1100
+ if (error.stack?.includes('PROCESSOR_3DS') &&
1101
+ error.code === 'RESUME_ERROR' &&
1102
+ error.message?.includes('fetch resume key')) {
1103
+ // Ignore 3DS close error, because it is not understandable by user
1104
+ return;
1105
+ }
1106
+ this.emit(EVENTS.PURCHASE_FAILURE, error);
1107
+ },
1108
+ onCheckoutFail: error => {
1109
+ this.emit(EVENTS.PURCHASE_FAILURE, error);
1110
+ },
1111
+ onTokenizeError: error => {
1112
+ this.emit(EVENTS.PURCHASE_FAILURE, error);
1113
+ },
1114
+ onTokenizeShouldStart: data => {
1115
+ this.emit(EVENTS.ERROR, undefined);
1116
+ this.emit(EVENTS.START_PURCHASE, data.paymentMethodType);
1117
+ return true;
1118
+ },
1119
+ onPaymentMethodAction: action => {
1120
+ switch (action) {
1121
+ case 'PAYMENT_METHOD_SELECTED':
1122
+ this.emit(EVENTS.ERROR, undefined);
1123
+ break;
1124
+ case 'PAYMENT_METHOD_UNSELECTED':
1125
+ if (!wasPaymentProcessedStarted) {
1126
+ this.emit(EVENTS.PURCHASE_CANCELLED);
1127
+ }
1128
+ wasPaymentProcessedStarted = false;
1129
+ break;
1130
+ }
1131
+ },
1132
+ };
1133
+ }
1004
1134
  async updatePrice(newPriceId) {
1005
1135
  this._ensureNotDestroyed();
1006
1136
  requireString(newPriceId, 'priceId');
@@ -1091,6 +1221,13 @@ class CheckoutInstance extends EventEmitter {
1091
1221
  this.on(EVENTS.PURCHASE_COMPLETED, skin.onPurchaseCompleted);
1092
1222
  return skin.getCheckoutOptions();
1093
1223
  }
1224
+ async getCardDefaultSkinCheckoutOptions(node) {
1225
+ const CardSkin = (await Promise.resolve().then(function () { return require('./chunk-index.cjs2.js'); })).default;
1226
+ const skin = new CardSkin(node);
1227
+ skin.init();
1228
+ this.on(EVENTS.INPUT_ERROR, skin.onInputError);
1229
+ return skin.getCheckoutOptions();
1230
+ }
1094
1231
  showInitializingLoader() {
1095
1232
  renderLoader(this.checkoutConfig.container);
1096
1233
  }
@@ -1125,19 +1262,14 @@ async function createCheckout(options) {
1125
1262
  const primerWrapper = new PrimerWrapper();
1126
1263
  primerWrapper.ensurePrimerAvailable();
1127
1264
  const config = resolveConfig(options, 'createCheckout');
1128
- return new Promise(resolve => {
1129
- const onInitialized = () => {
1130
- resolve(checkout);
1131
- checkoutConfig.onInitialized?.();
1132
- };
1133
- const checkout = new CheckoutInstance({
1134
- ...config,
1135
- checkoutConfig: {
1136
- ...checkoutConfig,
1137
- onInitialized,
1138
- },
1139
- });
1265
+ const checkout = new CheckoutInstance({
1266
+ ...config,
1267
+ checkoutConfig: {
1268
+ ...checkoutConfig,
1269
+ },
1140
1270
  });
1271
+ await checkout.initialize();
1272
+ return checkout;
1141
1273
  }
1142
1274
  async function createClientSession(params) {
1143
1275
  const { priceId, externalId, email, clientMetadata, countryCode } = params;
@@ -1158,6 +1290,54 @@ async function createClientSession(params) {
1158
1290
  });
1159
1291
  return apiClient.processSessionResponse(sessionResponse);
1160
1292
  }
1293
+ async function initMethod(method, element, options) {
1294
+ const checkoutInstance = new CheckoutInstance({
1295
+ orgId: options.orgId,
1296
+ baseUrl: options.baseUrl,
1297
+ checkoutConfig: {
1298
+ priceId: options.priceId,
1299
+ customer: {
1300
+ externalId: options.externalId,
1301
+ email: options.email,
1302
+ },
1303
+ container: '',
1304
+ clientMetadata: options.meta,
1305
+ },
1306
+ });
1307
+ checkoutInstance._ensureNotDestroyed();
1308
+ if (!checkoutInstance.isReady()) {
1309
+ await checkoutInstance['createSession']();
1310
+ }
1311
+ checkoutInstance.on(EVENTS.METHOD_RENDER, options.onRenderSuccess);
1312
+ checkoutInstance.on(EVENTS.METHOD_RENDER_ERROR, options.onRenderError);
1313
+ checkoutInstance.on(EVENTS.LOADER_CHANGE, options.onLoaderChange);
1314
+ checkoutInstance.on(EVENTS.SUCCESS, options.onPaymentSuccess);
1315
+ checkoutInstance.on(EVENTS.PURCHASE_FAILURE, options.onPaymentFail);
1316
+ checkoutInstance.on(EVENTS.PURCHASE_CANCELLED, options.onPaymentCancel);
1317
+ checkoutInstance.on(EVENTS.ERROR, options.onErrorMessageChange);
1318
+ if (method === exports.PaymentMethod.PAYMENT_CARD) {
1319
+ const cardDefaultOptions = await checkoutInstance['getCardDefaultSkinCheckoutOptions'](element);
1320
+ const checkoutOptions = checkoutInstance['getCheckoutOptions']({
1321
+ style: options.styles,
1322
+ ...cardDefaultOptions,
1323
+ });
1324
+ await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutOptions);
1325
+ return checkoutInstance.primerWrapper.initMethod(method, element, {
1326
+ cardElements: cardDefaultOptions.cardElements,
1327
+ onSubmit: checkoutInstance['handleSubmit'],
1328
+ onInputChange: checkoutInstance['handleInputChange'],
1329
+ onMethodRender: checkoutInstance['handleMethodRender'],
1330
+ onMethodRenderError: checkoutInstance['handleMethodRenderError'],
1331
+ });
1332
+ }
1333
+ await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutInstance['getCheckoutOptions']({
1334
+ style: options.styles,
1335
+ }));
1336
+ return checkoutInstance.primerWrapper.initMethod(method, element, {
1337
+ onMethodRender: checkoutInstance['handleMethodRender'],
1338
+ onMethodRenderError: checkoutInstance['handleMethodRenderError'],
1339
+ });
1340
+ }
1161
1341
 
1162
1342
  /**
1163
1343
  * @fileoverview Main entry point for @funnelfox/billing
@@ -1166,6 +1346,7 @@ const Billing = {
1166
1346
  configure: configure,
1167
1347
  createCheckout: createCheckout,
1168
1348
  createClientSession: createClientSession,
1349
+ initMethod: initMethod,
1169
1350
  };
1170
1351
  if (typeof window !== 'undefined') {
1171
1352
  window.Billing = Billing;